Skip to content

Commit b652b3a

Browse files
committed
[InstCombine] Add Tests for umul.overflow(x, c1) | x*c1 > c2; NFC
1 parent e64289b commit b652b3a

File tree

1 file changed

+298
-0
lines changed

1 file changed

+298
-0
lines changed
Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3+
4+
declare void @use.i1(i1 %x)
5+
declare void @use.i64(i64 %x)
6+
declare void @use.i64i1({i64, i1} %x)
7+
8+
define i1 @umul_greater_than_or_overflow_const(i64 %in) {
9+
; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const(
10+
; CHECK-SAME: i64 [[IN:%.*]]) {
11+
; CHECK-NEXT: [[TMP2:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 168)
12+
; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0
13+
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1
14+
; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt i64 [[TMP3]], -16
15+
; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]]
16+
; CHECK-NEXT: ret i1 [[TMP6]]
17+
;
18+
%mwo = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 168)
19+
%mul = extractvalue { i64, i1 } %mwo, 0
20+
%ovf = extractvalue { i64, i1 } %mwo, 1
21+
%cmp = icmp ugt i64 %mul, -16
22+
%ret = or i1 %ovf, %cmp
23+
ret i1 %ret
24+
}
25+
26+
define i1 @umul_greater_than_or_overflow_const_i8(i8 %in) {
27+
; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_i8(
28+
; CHECK-SAME: i8 [[IN:%.*]]) {
29+
; CHECK-NEXT: [[TMP2:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[IN]], i8 24)
30+
; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i8, i1 } [[TMP2]], 0
31+
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i8, i1 } [[TMP2]], 1
32+
; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt i8 [[TMP3]], -16
33+
; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]]
34+
; CHECK-NEXT: ret i1 [[TMP6]]
35+
;
36+
%mwo = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %in, i8 24)
37+
%mul = extractvalue { i8, i1 } %mwo, 0
38+
%ovf = extractvalue { i8, i1 } %mwo, 1
39+
%cmp = icmp ugt i8 %mul, -16
40+
%ret = or i1 %ovf, %cmp
41+
ret i1 %ret
42+
}
43+
44+
define i1 @umul_greater_than_or_overflow_const_commuted(i64 %in) {
45+
; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_commuted(
46+
; CHECK-SAME: i64 [[IN:%.*]]) {
47+
; CHECK-NEXT: [[TMP2:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)
48+
; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0
49+
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1
50+
; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt i64 [[TMP3]], 9223372036854775800
51+
; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP5]], [[TMP4]]
52+
; CHECK-NEXT: ret i1 [[TMP6]]
53+
;
54+
%mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)
55+
%mul = extractvalue { i64, i1 } %mwo, 0
56+
%ovf = extractvalue { i64, i1 } %mwo, 1
57+
%cmp = icmp ugt i64 %mul, 9223372036854775800
58+
%ret = or i1 %cmp, %ovf
59+
ret i1 %ret
60+
}
61+
62+
define i1 @umul_greater_than_or_overflow_const_disjoint(i64 %in) {
63+
; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_disjoint(
64+
; CHECK-SAME: i64 [[IN:%.*]]) {
65+
; CHECK-NEXT: [[TMP2:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 40)
66+
; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0
67+
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1
68+
; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt i64 [[TMP3]], 9223372036854775800
69+
; CHECK-NEXT: [[TMP6:%.*]] = or disjoint i1 [[TMP4]], [[TMP5]]
70+
; CHECK-NEXT: ret i1 [[TMP6]]
71+
;
72+
%mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 40)
73+
%mul = extractvalue { i64, i1 } %mwo, 0
74+
%ovf = extractvalue { i64, i1 } %mwo, 1
75+
%cmp = icmp ugt i64 %mul, 9223372036854775800
76+
%ret = or disjoint i1 %ovf, %cmp
77+
ret i1 %ret
78+
}
79+
80+
define <2 x i1> @umul_greater_than_or_overflow_const_vector_splat(<2 x i64> %in) {
81+
; CHECK-LABEL: define <2 x i1> @umul_greater_than_or_overflow_const_vector_splat(
82+
; CHECK-SAME: <2 x i64> [[IN:%.*]]) {
83+
; CHECK-NEXT: [[TMP2:%.*]] = tail call { <2 x i64>, <2 x i1> } @llvm.umul.with.overflow.v2i64(<2 x i64> [[IN]], <2 x i64> splat (i64 1424))
84+
; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { <2 x i64>, <2 x i1> } [[TMP2]], 0
85+
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { <2 x i64>, <2 x i1> } [[TMP2]], 1
86+
; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt <2 x i64> [[TMP3]], splat (i64 9223372036854775800)
87+
; CHECK-NEXT: [[TMP6:%.*]] = or <2 x i1> [[TMP4]], [[TMP5]]
88+
; CHECK-NEXT: ret <2 x i1> [[TMP6]]
89+
;
90+
%mwo = tail call { <2 x i64>, <2 x i1> } @llvm.umul.with.overflow.v2i64(<2 x i64> %in, <2 x i64> <i64 1424, i64 1424>)
91+
%mul = extractvalue { <2 x i64>, <2 x i1> } %mwo, 0
92+
%ovf = extractvalue { <2 x i64>, <2 x i1> } %mwo, 1
93+
%cmp = icmp ugt <2 x i64> %mul, <i64 9223372036854775800, i64 9223372036854775800>
94+
%ret = or <2 x i1> %ovf, %cmp
95+
ret <2 x i1> %ret
96+
}
97+
98+
; Negative test
99+
define <4 x i1> @umul_greater_than_or_overflow_const_vector_non_splat_negative(<4 x i64> %in) {
100+
; CHECK-LABEL: define <4 x i1> @umul_greater_than_or_overflow_const_vector_non_splat_negative(
101+
; CHECK-SAME: <4 x i64> [[IN:%.*]]) {
102+
; CHECK-NEXT: [[MWO:%.*]] = tail call { <4 x i64>, <4 x i1> } @llvm.umul.with.overflow.v4i64(<4 x i64> [[IN]], <4 x i64> <i64 24, i64 1424, i64 0, i64 -1>)
103+
; CHECK-NEXT: [[MUL:%.*]] = extractvalue { <4 x i64>, <4 x i1> } [[MWO]], 0
104+
; CHECK-NEXT: [[OVF:%.*]] = extractvalue { <4 x i64>, <4 x i1> } [[MWO]], 1
105+
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <4 x i64> [[MUL]], <i64 9223372036854775000, i64 9223372036854775800, i64 -16, i64 -16>
106+
; CHECK-NEXT: [[RET:%.*]] = or <4 x i1> [[OVF]], [[CMP]]
107+
; CHECK-NEXT: ret <4 x i1> [[RET]]
108+
;
109+
%mwo = tail call { <4 x i64>, <4 x i1> } @llvm.umul.with.overflow.v2i64(<4 x i64> %in, <4 x i64> <i64 24, i64 1424, i64 0, i64 -1>)
110+
%mul = extractvalue { <4 x i64>, <4 x i1> } %mwo, 0
111+
%ovf = extractvalue { <4 x i64>, <4 x i1> } %mwo, 1
112+
%cmp = icmp ugt <4 x i64> %mul, <i64 9223372036854775000, i64 9223372036854775800, i64 -16, i64 -16>
113+
%ret = or <4 x i1> %ovf, %cmp
114+
ret <4 x i1> %ret
115+
}
116+
117+
; Negative test
118+
define <2 x i1> @umul_greater_than_or_overflow_const_vector_c1_poison_splat_negative(<2 x i64> %in) {
119+
; CHECK-LABEL: define <2 x i1> @umul_greater_than_or_overflow_const_vector_c1_poison_splat_negative(
120+
; CHECK-SAME: <2 x i64> [[IN:%.*]]) {
121+
; CHECK-NEXT: ret <2 x i1> poison
122+
;
123+
%mwo = tail call { <2 x i64>, <2 x i1> } @llvm.umul.with.overflow.v2i64(<2 x i64> %in, <2 x i64> <i64 poison, i64 poison>)
124+
%mul = extractvalue { <2 x i64>, <2 x i1> } %mwo, 0
125+
%ovf = extractvalue { <2 x i64>, <2 x i1> } %mwo, 1
126+
%cmp = icmp ugt <2 x i64> %mul, <i64 9223372036854775800, i64 9223372036854775800>
127+
%ret = or <2 x i1> %ovf, %cmp
128+
ret <2 x i1> %ret
129+
}
130+
131+
; Negative test
132+
define <2 x i1> @umul_greater_than_or_overflow_const_vector_c2_poison_splat_negative(<2 x i64> %in) {
133+
; CHECK-LABEL: define <2 x i1> @umul_greater_than_or_overflow_const_vector_c2_poison_splat_negative(
134+
; CHECK-SAME: <2 x i64> [[IN:%.*]]) {
135+
; CHECK-NEXT: ret <2 x i1> poison
136+
;
137+
%mwo = tail call { <2 x i64>, <2 x i1> } @llvm.umul.with.overflow.v2i64(<2 x i64> %in, <2 x i64> <i64 1424, i64 1424>)
138+
%mul = extractvalue { <2 x i64>, <2 x i1> } %mwo, 0
139+
%ovf = extractvalue { <2 x i64>, <2 x i1> } %mwo, 1
140+
%cmp = icmp ugt <2 x i64> %mul, <i64 poison, i64 poison>
141+
%ret = or <2 x i1> %ovf, %cmp
142+
ret <2 x i1> %ret
143+
}
144+
145+
; Negative test
146+
define <2 x i1> @umul_greater_than_or_overflow_const_vector_poison_non_splat_negative(<2 x i64> %in) {
147+
; CHECK-LABEL: define <2 x i1> @umul_greater_than_or_overflow_const_vector_poison_non_splat_negative(
148+
; CHECK-SAME: <2 x i64> [[IN:%.*]]) {
149+
; CHECK-NEXT: [[MWO:%.*]] = tail call { <2 x i64>, <2 x i1> } @llvm.umul.with.overflow.v2i64(<2 x i64> [[IN]], <2 x i64> <i64 poison, i64 1424>)
150+
; CHECK-NEXT: [[MUL:%.*]] = extractvalue { <2 x i64>, <2 x i1> } [[MWO]], 0
151+
; CHECK-NEXT: [[OVF:%.*]] = extractvalue { <2 x i64>, <2 x i1> } [[MWO]], 1
152+
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i64> [[MUL]], <i64 9223372036854775800, i64 poison>
153+
; CHECK-NEXT: [[RET:%.*]] = or <2 x i1> [[OVF]], [[CMP]]
154+
; CHECK-NEXT: ret <2 x i1> [[RET]]
155+
;
156+
%mwo = tail call { <2 x i64>, <2 x i1> } @llvm.umul.with.overflow.v2i64(<2 x i64> %in, <2 x i64> <i64 poison, i64 1424>)
157+
%mul = extractvalue { <2 x i64>, <2 x i1> } %mwo, 0
158+
%ovf = extractvalue { <2 x i64>, <2 x i1> } %mwo, 1
159+
%cmp = icmp ugt <2 x i64> %mul, <i64 9223372036854775800, i64 poison>
160+
%ret = or <2 x i1> %ovf, %cmp
161+
ret <2 x i1> %ret
162+
}
163+
164+
; Negative test
165+
define i1 @umul_greater_than_and_overflow_const_negative(i64 %in) {
166+
; CHECK-LABEL: define i1 @umul_greater_than_and_overflow_const_negative(
167+
; CHECK-SAME: i64 [[IN:%.*]]) {
168+
; CHECK-NEXT: [[TMP2:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)
169+
; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0
170+
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1
171+
; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i64 [[TMP3]], 9223372036854775800
172+
; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP4]], [[TMP5]]
173+
; CHECK-NEXT: ret i1 [[TMP6]]
174+
;
175+
%mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)
176+
%mul = extractvalue { i64, i1 } %mwo, 0
177+
%ovf = extractvalue { i64, i1 } %mwo, 1
178+
%cmp = icmp ult i64 %mul, 9223372036854775800
179+
%ret = and i1 %ovf, %cmp
180+
ret i1 %ret
181+
}
182+
183+
; Negative test
184+
define i1 @umul_less_than_or_overflow_const_negative(i64 %in) {
185+
; CHECK-LABEL: define i1 @umul_less_than_or_overflow_const_negative(
186+
; CHECK-SAME: i64 [[IN:%.*]]) {
187+
; CHECK-NEXT: [[TMP2:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)
188+
; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0
189+
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1
190+
; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i64 [[TMP3]], 9223372036854775800
191+
; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]]
192+
; CHECK-NEXT: ret i1 [[TMP6]]
193+
;
194+
%mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)
195+
%mul = extractvalue { i64, i1 } %mwo, 0
196+
%ovf = extractvalue { i64, i1 } %mwo, 1
197+
%cmp = icmp ult i64 %mul, 9223372036854775800
198+
%ret = or i1 %ovf, %cmp
199+
ret i1 %ret
200+
}
201+
202+
; Negative test
203+
define i1 @umul_greater_than_or_overflow_const_multiuse_add_negative(i64 %in) {
204+
; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_multiuse_add_negative(
205+
; CHECK-SAME: i64 [[IN:%.*]]) {
206+
; CHECK-NEXT: [[TMP2:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)
207+
; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0
208+
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1
209+
; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt i64 [[TMP3]], 9223372036854775800
210+
; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]]
211+
; CHECK-NEXT: tail call void @use.i64(i64 [[TMP3]])
212+
; CHECK-NEXT: ret i1 [[TMP6]]
213+
;
214+
%mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)
215+
%mul = extractvalue { i64, i1 } %mwo, 0
216+
%ovf = extractvalue { i64, i1 } %mwo, 1
217+
%cmp = icmp ugt i64 %mul, 9223372036854775800
218+
%ret = or i1 %ovf, %cmp
219+
tail call void @use.i64(i64 %mul)
220+
ret i1 %ret
221+
}
222+
223+
; Negative test
224+
define i1 @umul_greater_than_or_overflow_const_multiuse_overflow_negative(i64 %in) {
225+
; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_multiuse_overflow_negative(
226+
; CHECK-SAME: i64 [[IN:%.*]]) {
227+
; CHECK-NEXT: [[TMP2:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)
228+
; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0
229+
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1
230+
; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt i64 [[TMP3]], 9223372036854775800
231+
; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]]
232+
; CHECK-NEXT: tail call void @use.i1(i1 [[TMP4]])
233+
; CHECK-NEXT: ret i1 [[TMP6]]
234+
;
235+
%mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)
236+
%mul = extractvalue { i64, i1 } %mwo, 0
237+
%ovf = extractvalue { i64, i1 } %mwo, 1
238+
%cmp = icmp ugt i64 %mul, 9223372036854775800
239+
%ret = or i1 %ovf, %cmp
240+
tail call void @use.i1(i1 %ovf)
241+
ret i1 %ret
242+
}
243+
244+
; Negative test
245+
define i1 @umul_greater_than_or_overflow_const_multiuse_icmp_negative(i64 %in) {
246+
; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_multiuse_icmp_negative(
247+
; CHECK-SAME: i64 [[IN:%.*]]) {
248+
; CHECK-NEXT: [[TMP2:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)
249+
; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0
250+
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1
251+
; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt i64 [[TMP3]], 9223372036854775800
252+
; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]]
253+
; CHECK-NEXT: tail call void @use.i1(i1 [[TMP5]])
254+
; CHECK-NEXT: ret i1 [[TMP6]]
255+
;
256+
%mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)
257+
%mul = extractvalue { i64, i1 } %mwo, 0
258+
%ovf = extractvalue { i64, i1 } %mwo, 1
259+
%cmp = icmp ugt i64 %mul, 9223372036854775800
260+
%ret = or i1 %ovf, %cmp
261+
tail call void @use.i1(i1 %cmp)
262+
ret i1 %ret
263+
}
264+
265+
; Negative test
266+
define i1 @umul_greater_than_or_overflow_const_multiuse_umul_call_negative(i64 %in) {
267+
; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_multiuse_umul_call_negative(
268+
; CHECK-SAME: i64 [[IN:%.*]]) {
269+
; CHECK-NEXT: [[TMP2:%.*]] = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[IN]], i64 48)
270+
; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP2]], 0
271+
; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP2]], 1
272+
; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt i64 [[TMP3]], 9223372036854775800
273+
; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]]
274+
; CHECK-NEXT: tail call void @use.i64i1({ i64, i1 } [[TMP2]])
275+
; CHECK-NEXT: ret i1 [[TMP6]]
276+
;
277+
%mwo = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 48)
278+
%mul = extractvalue { i64, i1 } %mwo, 0
279+
%ovf = extractvalue { i64, i1 } %mwo, 1
280+
%cmp = icmp ugt i64 %mul, 9223372036854775800
281+
%ret = or i1 %ovf, %cmp
282+
tail call void @use.i64i1({ i64, i1 } %mwo)
283+
ret i1 %ret
284+
}
285+
286+
; Negative test. The umul.with.overflow should be folded away before.
287+
define i1 @umul_greater_than_or_overflow_const_0_negative(i64 %in) {
288+
; CHECK-LABEL: define i1 @umul_greater_than_or_overflow_const_0_negative(
289+
; CHECK-SAME: i64 [[IN:%.*]]) {
290+
; CHECK-NEXT: ret i1 false
291+
;
292+
%mwo = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %in, i64 0)
293+
%mul = extractvalue { i64, i1 } %mwo, 0
294+
%ovf = extractvalue { i64, i1 } %mwo, 1
295+
%cmp = icmp ugt i64 %mul, 0
296+
%ret = or i1 %ovf, %cmp
297+
ret i1 %ret
298+
}

0 commit comments

Comments
 (0)