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