1 ; RUN: opt -S -instcombine < %s | FileCheck %s 2 3 ; return mul(zext x, zext y) > MAX 4 define i32 @pr4917_1(i32 %x, i32 %y) nounwind { 5 ; CHECK-LABEL: @pr4917_1( 6 entry: 7 %l = zext i32 %x to i64 8 %r = zext i32 %y to i64 9 ; CHECK-NOT: zext i32 10 %mul64 = mul i64 %l, %r 11 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y) 12 %overflow = icmp ugt i64 %mul64, 4294967295 13 ; CHECK: extractvalue { i32, i1 } [[MUL]], 1 14 %retval = zext i1 %overflow to i32 15 ret i32 %retval 16 } 17 18 ; return mul(zext x, zext y) >= MAX+1 19 define i32 @pr4917_1a(i32 %x, i32 %y) nounwind { 20 ; CHECK-LABEL: @pr4917_1a( 21 entry: 22 %l = zext i32 %x to i64 23 %r = zext i32 %y to i64 24 ; CHECK-NOT: zext i32 25 %mul64 = mul i64 %l, %r 26 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y) 27 %overflow = icmp uge i64 %mul64, 4294967296 28 ; CHECK: extractvalue { i32, i1 } [[MUL]], 1 29 %retval = zext i1 %overflow to i32 30 ret i32 %retval 31 } 32 33 ; mul(zext x, zext y) > MAX 34 ; mul(x, y) is used 35 define i32 @pr4917_2(i32 %x, i32 %y) nounwind { 36 ; CHECK-LABEL: @pr4917_2( 37 entry: 38 %l = zext i32 %x to i64 39 %r = zext i32 %y to i64 40 ; CHECK-NOT: zext i32 41 %mul64 = mul i64 %l, %r 42 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y) 43 %overflow = icmp ugt i64 %mul64, 4294967295 44 ; CHECK-DAG: [[VAL:%.*]] = extractvalue { i32, i1 } [[MUL]], 0 45 %mul32 = trunc i64 %mul64 to i32 46 ; CHECK-DAG: [[OVFL:%.*]] = extractvalue { i32, i1 } [[MUL]], 1 47 %retval = select i1 %overflow, i32 %mul32, i32 111 48 ; CHECK: select i1 [[OVFL]], i32 [[VAL]] 49 ret i32 %retval 50 } 51 52 ; return mul(zext x, zext y) > MAX 53 ; mul is used in non-truncate 54 define i64 @pr4917_3(i32 %x, i32 %y) nounwind { 55 ; CHECK-LABEL: @pr4917_3( 56 entry: 57 %l = zext i32 %x to i64 58 %r = zext i32 %y to i64 59 %mul64 = mul i64 %l, %r 60 ; CHECK-NOT: umul.with.overflow.i32 61 %overflow = icmp ugt i64 %mul64, 4294967295 62 %retval = select i1 %overflow, i64 %mul64, i64 111 63 ret i64 %retval 64 } 65 66 ; return mul(zext x, zext y) <= MAX 67 define i32 @pr4917_4(i32 %x, i32 %y) nounwind { 68 ; CHECK-LABEL: @pr4917_4( 69 entry: 70 %l = zext i32 %x to i64 71 %r = zext i32 %y to i64 72 ; CHECK-NOT: zext i32 73 %mul64 = mul i64 %l, %r 74 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y) 75 %overflow = icmp ule i64 %mul64, 4294967295 76 ; CHECK: extractvalue { i32, i1 } [[MUL]], 1 77 ; CHECK: xor 78 %retval = zext i1 %overflow to i32 79 ret i32 %retval 80 } 81 82 ; return mul(zext x, zext y) < MAX+1 83 define i32 @pr4917_4a(i32 %x, i32 %y) nounwind { 84 ; CHECK-LABEL: @pr4917_4a( 85 entry: 86 %l = zext i32 %x to i64 87 %r = zext i32 %y to i64 88 ; CHECK-NOT: zext i32 89 %mul64 = mul i64 %l, %r 90 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y) 91 %overflow = icmp ult i64 %mul64, 4294967296 92 ; CHECK: extractvalue { i32, i1 } [[MUL]], 1 93 ; CHECK: xor 94 %retval = zext i1 %overflow to i32 95 ret i32 %retval 96 } 97 98 ; operands of mul are of different size 99 define i32 @pr4917_5(i32 %x, i8 %y) nounwind { 100 ; CHECK-LABEL: @pr4917_5( 101 entry: 102 %l = zext i32 %x to i64 103 %r = zext i8 %y to i64 104 ; CHECK: [[Y:%.*]] = zext i8 %y to i32 105 %mul64 = mul i64 %l, %r 106 %overflow = icmp ugt i64 %mul64, 4294967295 107 %mul32 = trunc i64 %mul64 to i32 108 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 [[Y]]) 109 ; CHECK-DAG: [[VAL:%.*]] = extractvalue { i32, i1 } [[MUL]], 0 110 ; CHECK-DAG: [[OVFL:%.*]] = extractvalue { i32, i1 } [[MUL]], 1 111 %retval = select i1 %overflow, i32 %mul32, i32 111 112 ; CHECK: select i1 [[OVFL]], i32 [[VAL]] 113 ret i32 %retval 114 } 115 116 ; mul(zext x, zext y) != zext trunc mul 117 define i32 @pr4918_1(i32 %x, i32 %y) nounwind { 118 ; CHECK-LABEL: @pr4918_1( 119 entry: 120 %l = zext i32 %x to i64 121 %r = zext i32 %y to i64 122 %mul64 = mul i64 %l, %r 123 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y) 124 %part32 = trunc i64 %mul64 to i32 125 %part64 = zext i32 %part32 to i64 126 %overflow = icmp ne i64 %mul64, %part64 127 ; CHECK: [[OVFL:%.*]] = extractvalue { i32, i1 } [[MUL:%.*]], 1 128 %retval = zext i1 %overflow to i32 129 ret i32 %retval 130 } 131 132 ; mul(zext x, zext y) == zext trunc mul 133 define i32 @pr4918_2(i32 %x, i32 %y) nounwind { 134 ; CHECK-LABEL: @pr4918_2( 135 entry: 136 %l = zext i32 %x to i64 137 %r = zext i32 %y to i64 138 %mul64 = mul i64 %l, %r 139 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y) 140 %part32 = trunc i64 %mul64 to i32 141 %part64 = zext i32 %part32 to i64 142 %overflow = icmp eq i64 %mul64, %part64 143 ; CHECK: extractvalue { i32, i1 } [[MUL]] 144 %retval = zext i1 %overflow to i32 145 ; CHECK: xor 146 ret i32 %retval 147 } 148 149 ; zext trunc mul != mul(zext x, zext y) 150 define i32 @pr4918_3(i32 %x, i32 %y) nounwind { 151 ; CHECK-LABEL: @pr4918_3( 152 entry: 153 %l = zext i32 %x to i64 154 %r = zext i32 %y to i64 155 %mul64 = mul i64 %l, %r 156 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y) 157 %part32 = trunc i64 %mul64 to i32 158 %part64 = zext i32 %part32 to i64 159 %overflow = icmp ne i64 %part64, %mul64 160 ; CHECK: extractvalue { i32, i1 } [[MUL]], 1 161 %retval = zext i1 %overflow to i32 162 ret i32 %retval 163 } 164 165 define <4 x i32> @pr20113(<4 x i16> %a, <4 x i16> %b) { 166 ; CHECK-LABEL: @pr20113 167 ; CHECK-NOT: mul.with.overflow 168 ; CHECK: ret 169 %vmovl.i.i726 = zext <4 x i16> %a to <4 x i32> 170 %vmovl.i.i712 = zext <4 x i16> %b to <4 x i32> 171 %mul.i703 = mul <4 x i32> %vmovl.i.i712, %vmovl.i.i726 172 %tmp = icmp sge <4 x i32> %mul.i703, zeroinitializer 173 %vcgez.i = sext <4 x i1> %tmp to <4 x i32> 174 ret <4 x i32> %vcgez.i 175 } 176