1 ; RUN: opt -S -instcombine < %s | FileCheck %s
3 ; return mul(zext x, zext y) > MAX
4 define i32 @pr4917_1(i32 %x, i32 %y) nounwind {
5 ; CHECK-LABEL: @pr4917_1(
7 %l = zext i32 %x to i64
8 %r = zext i32 %y to i64
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
18 ; return mul(zext x, zext y) >= MAX+1
19 define i32 @pr4917_1a(i32 %x, i32 %y) nounwind {
20 ; CHECK-LABEL: @pr4917_1a(
22 %l = zext i32 %x to i64
23 %r = zext i32 %y to i64
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
33 ; mul(zext x, zext y) > MAX
35 define i32 @pr4917_2(i32 %x, i32 %y) nounwind {
36 ; CHECK-LABEL: @pr4917_2(
38 %l = zext i32 %x to i64
39 %r = zext i32 %y to i64
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]]
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(
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
66 ; return mul(zext x, zext y) <= MAX
67 define i32 @pr4917_4(i32 %x, i32 %y) nounwind {
68 ; CHECK-LABEL: @pr4917_4(
70 %l = zext i32 %x to i64
71 %r = zext i32 %y to i64
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
78 %retval = zext i1 %overflow to i32
82 ; return mul(zext x, zext y) < MAX+1
83 define i32 @pr4917_4a(i32 %x, i32 %y) nounwind {
84 ; CHECK-LABEL: @pr4917_4a(
86 %l = zext i32 %x to i64
87 %r = zext i32 %y to i64
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
94 %retval = zext i1 %overflow to i32
98 ; operands of mul are of different size
99 define i32 @pr4917_5(i32 %x, i8 %y) nounwind {
100 ; CHECK-LABEL: @pr4917_5(
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]]
116 ; mul(zext x, zext y) != zext trunc mul
117 define i32 @pr4918_1(i32 %x, i32 %y) nounwind {
118 ; CHECK-LABEL: @pr4918_1(
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
132 ; mul(zext x, zext y) == zext trunc mul
133 define i32 @pr4918_2(i32 %x, i32 %y) nounwind {
134 ; CHECK-LABEL: @pr4918_2(
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
149 ; zext trunc mul != mul(zext x, zext y)
150 define i32 @pr4918_3(i32 %x, i32 %y) nounwind {
151 ; CHECK-LABEL: @pr4918_3(
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
165 define <4 x i32> @pr20113(<4 x i16> %a, <4 x i16> %b) {
166 ; CHECK-LABEL: @pr20113
167 ; CHECK-NOT: mul.with.overflow
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
178 ; The last test needs this weird datalayout.
179 target datalayout = "i32:8:8"
180 ; Without it, InstCombine will align the pointed on 4 Bytes
181 ; The KnownBitsZero that result from the alignment allows to
186 ; The mask is no longer in the form 2^n-1 and this prevents the transformation.
188 @pr21445_data = external global i32
189 define i1 @pr21445(i8 %a) {
190 ; CHECK-LABEL: @pr21445(
191 ; CHECK-NEXT: %[[umul:.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 ptrtoint (i32* @pr21445_data to i8))
192 ; CHECK-NEXT: %[[cmp:.*]] = extractvalue { i8, i1 } %[[umul]], 1
193 ; CHECK-NEXT: ret i1 %[[cmp]]
194 %ext = zext i8 %a to i32
195 %mul = mul i32 %ext, zext (i8 ptrtoint (i32* @pr21445_data to i8) to i32)
196 %and = and i32 %mul, 255
197 %cmp = icmp ne i32 %mul, %and