1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=m68k-linux -verify-machineinstrs | FileCheck %s
define zeroext i8 @smul_i8(i8 signext %a, i8 signext %b) nounwind ssp {
; CHECK-LABEL: smul_i8:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: move.b (11,%sp), %d0
; CHECK-NEXT: and.l #255, %d0
; CHECK-NEXT: move.b (7,%sp), %d1
; CHECK-NEXT: and.l #255, %d1
; CHECK-NEXT: muls %d0, %d1
; CHECK-NEXT: move.l %d1, %d0
; CHECK-NEXT: and.l #65535, %d0
; CHECK-NEXT: and.l #255, %d0
; CHECK-NEXT: rts
entry:
%smul = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 %b)
%cmp = extractvalue { i8, i1 } %smul, 1
%smul.result = extractvalue { i8, i1 } %smul, 0
%X = select i1 %cmp, i8 42, i8 %smul.result
ret i8 %X
}
define zeroext i8 @smul_i8_no_ovf(i8 signext %a, i8 signext %b) nounwind ssp {
; CHECK-LABEL: smul_i8_no_ovf:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: moveq #42, %d0
; CHECK-NEXT: rts
entry:
%smul = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 %b)
%cmp = extractvalue { i8, i1 } %smul, 1
%smul.result = extractvalue { i8, i1 } %smul, 0
%X = select i1 %cmp, i8 %smul.result, i8 42
ret i8 %X
}
declare { i8, i1 } @llvm.smul.with.overflow.i8(i8, i8) nounwind readnone
define zeroext i16 @smul_i16(i16 signext %a, i16 signext %b) nounwind ssp {
; CHECK-LABEL: smul_i16:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: move.w (6,%sp), %d0
; CHECK-NEXT: move.w (10,%sp), %d1
; CHECK-NEXT: muls %d1, %d0
; CHECK-NEXT: and.l #65535, %d0
; CHECK-NEXT: rts
entry:
%smul = tail call { i16, i1 } @llvm.smul.with.overflow.i16(i16 %a, i16 %b)
%cmp = extractvalue { i16, i1 } %smul, 1
%smul.result = extractvalue { i16, i1 } %smul, 0
%X = select i1 %cmp, i16 42, i16 %smul.result
ret i16 %X
}
declare { i16, i1 } @llvm.smul.with.overflow.i16(i16, i16) nounwind readnone
declare i32 @printf(ptr, ...) nounwind
declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32)
@ok = internal constant [4 x i8] c"%d\0A\00"
@no = internal constant [4 x i8] c"no\0A\00"
define fastcc i1 @test1(i32 %v1, i32 %v2) nounwind {
; CHECK-LABEL: test1:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: suba.l #12, %sp
; CHECK-NEXT: muls.l %d1, %d0
; CHECK-NEXT: bvc .LBB3_1
; CHECK-NEXT: ; %bb.2: ; %overflow
; CHECK-NEXT: lea (no,%pc), %a0
; CHECK-NEXT: move.l %a0, (%sp)
; CHECK-NEXT: jsr printf
; CHECK-NEXT: moveq #0, %d0
; CHECK-NEXT: adda.l #12, %sp
; CHECK-NEXT: rts
; CHECK-NEXT: .LBB3_1: ; %normal
; CHECK-NEXT: move.l %d0, (4,%sp)
; CHECK-NEXT: lea (ok,%pc), %a0
; CHECK-NEXT: move.l %a0, (%sp)
; CHECK-NEXT: jsr printf
; CHECK-NEXT: moveq #1, %d0
; CHECK-NEXT: adda.l #12, %sp
; CHECK-NEXT: rts
entry:
%t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2)
%sum = extractvalue {i32, i1} %t, 0
%obit = extractvalue {i32, i1} %t, 1
br i1 %obit, label %overflow, label %normal
normal:
%t1 = tail call i32 (ptr, ...) @printf( ptr @ok, i32 %sum ) nounwind
ret i1 true
overflow:
%t2 = tail call i32 (ptr, ...) @printf( ptr @no ) nounwind
ret i1 false
}
define fastcc i1 @test2(i32 %v1, i32 %v2) nounwind {
; CHECK-LABEL: test2:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: suba.l #12, %sp
; CHECK-NEXT: muls.l %d1, %d0
; CHECK-NEXT: svs %d1
; CHECK-NEXT: sub.b #1, %d1
; CHECK-NEXT: bne .LBB4_2
; CHECK-NEXT: ; %bb.1: ; %overflow
; CHECK-NEXT: lea (no,%pc), %a0
; CHECK-NEXT: move.l %a0, (%sp)
; CHECK-NEXT: jsr printf
; CHECK-NEXT: moveq #0, %d0
; CHECK-NEXT: adda.l #12, %sp
; CHECK-NEXT: rts
; CHECK-NEXT: .LBB4_2: ; %normal
; CHECK-NEXT: move.l %d0, (4,%sp)
; CHECK-NEXT: lea (ok,%pc), %a0
; CHECK-NEXT: move.l %a0, (%sp)
; CHECK-NEXT: jsr printf
; CHECK-NEXT: moveq #1, %d0
; CHECK-NEXT: adda.l #12, %sp
; CHECK-NEXT: rts
entry:
%t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2)
%sum = extractvalue {i32, i1} %t, 0
%obit = extractvalue {i32, i1} %t, 1
br i1 %obit, label %overflow, label %normal
overflow:
%t2 = tail call i32 (ptr, ...) @printf( ptr @no ) nounwind
ret i1 false
normal:
%t1 = tail call i32 (ptr, ...) @printf( ptr @ok, i32 %sum ) nounwind
ret i1 true
}
define i32 @test3(i32 %a, i32 %b) nounwind readnone {
; CHECK-LABEL: test3:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: move.l (8,%sp), %d0
; CHECK-NEXT: add.l (4,%sp), %d0
; CHECK-NEXT: add.l %d0, %d0
; CHECK-NEXT: rts
entry:
%tmp0 = add i32 %b, %a
%tmp1 = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %tmp0, i32 2)
%tmp2 = extractvalue { i32, i1 } %tmp1, 0
ret i32 %tmp2
}
; Same as umul-with-overflow, we shouldn't fallback to
; builtin here
define i32 @test4(i32 %a, i32 %b) nounwind readnone {
; CHECK-LABEL: test4:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: move.l (8,%sp), %d0
; CHECK-NEXT: add.l (4,%sp), %d0
; CHECK-NEXT: moveq #4, %d1
; CHECK-NEXT: muls.l %d1, %d0
; CHECK-NEXT: rts
entry:
%tmp0 = add i32 %b, %a
%tmp1 = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %tmp0, i32 4)
%tmp2 = extractvalue { i32, i1 } %tmp1, 0
ret i32 %tmp2
}
|