Skip to content

Commit efd7fc0

Browse files
committed
pre-commit test
[InstCombine] Fold `ceil(X >> C) == 0 -> X == 0` update test 1 address review comments rm header 1 1
1 parent 937be17 commit efd7fc0

File tree

2 files changed

+286
-0
lines changed

2 files changed

+286
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,7 @@ Instruction *InstCombinerImpl::foldICmpWithZero(ICmpInst &Cmp) {
12981298
// eq/ne (mul X, Y)) with (icmp eq/ne X/Y) and if X/Y is known non-zero that
12991299
// will fold to a constant elsewhere.
13001300
}
1301+
13011302
return nullptr;
13021303
}
13031304

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
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+
define i1 @ceil_shift4(i32 %arg0) {
5+
; CHECK-LABEL: define i1 @ceil_shift4(
6+
; CHECK-SAME: i32 [[ARG0:%.*]]) {
7+
; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 4
8+
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 15
9+
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
10+
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
11+
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
12+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
13+
; CHECK-NEXT: ret i1 [[TMP1]]
14+
;
15+
%quot = lshr i32 %arg0, 4
16+
%rem = and i32 %arg0, 15
17+
%has_rem = icmp ne i32 %rem, 0
18+
%zext_has_rem = zext i1 %has_rem to i32
19+
%quot_or_rem = or i32 %quot, %zext_has_rem
20+
%is_zero = icmp eq i32 %quot_or_rem, 0
21+
ret i1 %is_zero
22+
}
23+
24+
define i1 @ceil_shift4_add(i32 %arg0) {
25+
; CHECK-LABEL: define i1 @ceil_shift4_add(
26+
; CHECK-SAME: i32 [[ARG0:%.*]]) {
27+
; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 4
28+
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 15
29+
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
30+
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
31+
; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
32+
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP1]], 0
33+
; CHECK-NEXT: ret i1 [[TMP6]]
34+
;
35+
%quot = lshr i32 %arg0, 4
36+
%rem = and i32 %arg0, 15
37+
%has_rem = icmp ne i32 %rem, 0
38+
%zext_has_rem = zext i1 %has_rem to i32
39+
%ceil = add i32 %quot, %zext_has_rem
40+
%res = icmp eq i32 %ceil, 0
41+
ret i1 %res
42+
}
43+
44+
define i1 @ceil_shift6(i32 %arg0) {
45+
; CHECK-LABEL: define i1 @ceil_shift6(
46+
; CHECK-SAME: i32 [[ARG0:%.*]]) {
47+
; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 6
48+
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 63
49+
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
50+
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
51+
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
52+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
53+
; CHECK-NEXT: ret i1 [[TMP1]]
54+
;
55+
%quot = lshr i32 %arg0, 6
56+
%rem = and i32 %arg0, 63
57+
%has_rem = icmp ne i32 %rem, 0
58+
%zext_has_rem = zext i1 %has_rem to i32
59+
%quot_or_rem = or i32 %quot, %zext_has_rem
60+
%res = icmp eq i32 %quot_or_rem, 0
61+
ret i1 %res
62+
}
63+
64+
define i1 @ceil_shift6_ne(i32 %arg0) {
65+
; CHECK-LABEL: define i1 @ceil_shift6_ne(
66+
; CHECK-SAME: i32 [[ARG0:%.*]]) {
67+
; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 6
68+
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 63
69+
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
70+
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
71+
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
72+
; CHECK-NEXT: [[RES:%.*]] = icmp ne i32 [[QUOT_OR_REM]], 0
73+
; CHECK-NEXT: ret i1 [[RES]]
74+
;
75+
%quot = lshr i32 %arg0, 6
76+
%rem = and i32 %arg0, 63
77+
%has_rem = icmp ne i32 %rem, 0
78+
%zext_has_rem = zext i1 %has_rem to i32
79+
%quot_or_rem = or i32 %quot, %zext_has_rem
80+
%res = icmp ne i32 %quot_or_rem, 0
81+
ret i1 %res
82+
}
83+
84+
define i1 @ceil_shift11(i32 %arg0) {
85+
; CHECK-LABEL: define i1 @ceil_shift11(
86+
; CHECK-SAME: i32 [[ARG0:%.*]]) {
87+
; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 11
88+
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 2047
89+
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
90+
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
91+
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
92+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
93+
; CHECK-NEXT: ret i1 [[TMP1]]
94+
;
95+
%quot = lshr i32 %arg0, 11
96+
%rem = and i32 %arg0, 2047
97+
%has_rem = icmp ne i32 %rem, 0
98+
%zext_has_rem = zext i1 %has_rem to i32
99+
%quot_or_rem = or i32 %quot, %zext_has_rem
100+
%res = icmp eq i32 %quot_or_rem, 0
101+
ret i1 %res
102+
}
103+
104+
define i1 @ceil_shift11_ne(i32 %arg0) {
105+
; CHECK-LABEL: define i1 @ceil_shift11_ne(
106+
; CHECK-SAME: i32 [[ARG0:%.*]]) {
107+
; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 6
108+
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 63
109+
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
110+
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
111+
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
112+
; CHECK-NEXT: [[RES:%.*]] = icmp ne i32 [[QUOT_OR_REM]], 0
113+
; CHECK-NEXT: ret i1 [[RES]]
114+
;
115+
%quot = lshr i32 %arg0, 6
116+
%rem = and i32 %arg0, 63
117+
%has_rem = icmp ne i32 %rem, 0
118+
%zext_has_rem = zext i1 %has_rem to i32
119+
%quot_or_rem = or i32 %quot, %zext_has_rem
120+
%res = icmp ne i32 %quot_or_rem, 0
121+
ret i1 %res
122+
}
123+
124+
define i1 @ceil_shift0(i32 %arg0) {
125+
; CHECK-LABEL: define i1 @ceil_shift0(
126+
; CHECK-SAME: i32 [[ARG0:%.*]]) {
127+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
128+
; CHECK-NEXT: ret i1 [[TMP1]]
129+
;
130+
%quot = lshr i32 %arg0, 0
131+
%rem = and i32 %arg0, 0
132+
%has_rem = icmp ne i32 %rem, 0
133+
%zext_has_rem = zext i1 %has_rem to i32
134+
%quot_or_rem = or i32 %quot, %zext_has_rem
135+
%res = icmp eq i32 %quot_or_rem, 0
136+
ret i1 %res
137+
}
138+
139+
define i1 @ceil_shift4_comm(i32 %arg0) {
140+
; CHECK-LABEL: define i1 @ceil_shift4_comm(
141+
; CHECK-SAME: i32 [[ARG0:%.*]]) {
142+
; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 4
143+
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 15
144+
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
145+
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
146+
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
147+
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
148+
; CHECK-NEXT: ret i1 [[TMP6]]
149+
;
150+
%quot = lshr i32 %arg0, 4
151+
%rem = and i32 %arg0, 15
152+
%has_rem = icmp ne i32 %rem, 0
153+
%zext_has_rem = zext i1 %has_rem to i32
154+
%quot_or_rem = or i32 %zext_has_rem, %quot
155+
%res = icmp eq i32 %quot_or_rem, 0
156+
ret i1 %res
157+
}
158+
159+
declare void @use(i32)
160+
161+
define i1 @ceil_shift4_used_1(i32 %arg0) {
162+
; CHECK-LABEL: define i1 @ceil_shift4_used_1(
163+
; CHECK-SAME: i32 [[ARG0:%.*]]) {
164+
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[ARG0]], 4
165+
; CHECK-NEXT: call void @use(i32 [[TMP1]])
166+
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 15
167+
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
168+
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
169+
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or i32 [[TMP1]], [[ZEXT_HAS_REM]]
170+
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
171+
; CHECK-NEXT: ret i1 [[TMP6]]
172+
;
173+
%quot = lshr i32 %arg0, 4
174+
call void @use(i32 %quot)
175+
%rem = and i32 %arg0, 15
176+
%has_rem = icmp ne i32 %rem, 0
177+
%zext_has_rem = zext i1 %has_rem to i32
178+
%quot_or_rem = or i32 %quot, %zext_has_rem
179+
%res = icmp eq i32 %quot_or_rem, 0
180+
ret i1 %res
181+
}
182+
183+
define i1 @ceil_shift4_used_5(i32 %arg0) {
184+
; CHECK-LABEL: define i1 @ceil_shift4_used_5(
185+
; CHECK-SAME: i32 [[ARG0:%.*]]) {
186+
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[ARG0]], 4
187+
; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[ARG0]], 15
188+
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
189+
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
190+
; CHECK-NEXT: [[TMP5:%.*]] = or i32 [[TMP1]], [[TMP4]]
191+
; CHECK-NEXT: call void @use(i32 [[TMP5]])
192+
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
193+
; CHECK-NEXT: ret i1 [[TMP6]]
194+
;
195+
%quot = lshr i32 %arg0, 4
196+
%rem = and i32 %arg0, 15
197+
%has_rem = icmp ne i32 %rem, 0
198+
%zext_has_rem = zext i1 %has_rem to i32
199+
%quot_or_rem = or i32 %quot, %zext_has_rem
200+
call void @use(i32 %quot_or_rem)
201+
%res = icmp eq i32 %quot_or_rem, 0
202+
ret i1 %res
203+
}
204+
205+
define <4 x i1> @ceil_shift4_v4i32(<4 x i32> %arg0) {
206+
; CHECK-LABEL: define <4 x i1> @ceil_shift4_v4i32(
207+
; CHECK-SAME: <4 x i32> [[ARG0:%.*]]) {
208+
; CHECK-NEXT: [[QUOT:%.*]] = lshr <4 x i32> [[ARG0]], splat (i32 16)
209+
; CHECK-NEXT: [[REM:%.*]] = and <4 x i32> [[ARG0]], splat (i32 65535)
210+
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne <4 x i32> [[REM]], zeroinitializer
211+
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext <4 x i1> [[HAS_REM]] to <4 x i32>
212+
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or <4 x i32> [[QUOT]], [[ZEXT_HAS_REM]]
213+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <4 x i32> [[QUOT_OR_REM]], zeroinitializer
214+
; CHECK-NEXT: ret <4 x i1> [[TMP1]]
215+
;
216+
%quot = lshr <4 x i32> %arg0, splat (i32 16)
217+
%rem = and <4 x i32> %arg0, splat (i32 65535)
218+
%has_rem = icmp ne <4 x i32> %rem, zeroinitializer
219+
%zext_has_rem = zext <4 x i1> %has_rem to <4 x i32>
220+
%quot_or_rem = or <4 x i32> %quot, %zext_has_rem
221+
%res = icmp eq <4 x i32> %quot_or_rem, zeroinitializer
222+
ret <4 x i1> %res
223+
}
224+
225+
define <8 x i1> @ceil_shift4_v8i16(<8 x i16> %arg0) {
226+
; CHECK-LABEL: define <8 x i1> @ceil_shift4_v8i16(
227+
; CHECK-SAME: <8 x i16> [[ARG0:%.*]]) {
228+
; CHECK-NEXT: [[QUOT:%.*]] = lshr <8 x i16> [[ARG0]], splat (i16 4)
229+
; CHECK-NEXT: [[REM:%.*]] = and <8 x i16> [[ARG0]], splat (i16 15)
230+
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne <8 x i16> [[REM]], zeroinitializer
231+
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext <8 x i1> [[HAS_REM]] to <8 x i16>
232+
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or <8 x i16> [[QUOT]], [[ZEXT_HAS_REM]]
233+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <8 x i16> [[QUOT_OR_REM]], zeroinitializer
234+
; CHECK-NEXT: ret <8 x i1> [[TMP1]]
235+
;
236+
%quot = lshr <8 x i16> %arg0, splat (i16 4)
237+
%rem = and <8 x i16> %arg0, splat (i16 15)
238+
%has_rem = icmp ne <8 x i16> %rem, zeroinitializer
239+
%zext_has_rem = zext <8 x i1> %has_rem to <8 x i16>
240+
%quot_or_rem = or <8 x i16> %quot, %zext_has_rem
241+
%res = icmp eq <8 x i16> %quot_or_rem, zeroinitializer
242+
ret <8 x i1> %res
243+
}
244+
245+
; negative tests
246+
247+
define i1 @ceil_shift_not_mask_1(i32 %arg0) {
248+
; CHECK-LABEL: define i1 @ceil_shift_not_mask_1(
249+
; CHECK-SAME: i32 [[ARG0:%.*]]) {
250+
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[ARG0]], 4
251+
; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[ARG0]], 31
252+
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
253+
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
254+
; CHECK-NEXT: [[TMP5:%.*]] = or i32 [[TMP1]], [[TMP4]]
255+
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
256+
; CHECK-NEXT: ret i1 [[TMP6]]
257+
;
258+
%quot = lshr i32 %arg0, 4
259+
%rem = and i32 %arg0, 31
260+
%has_rem = icmp ne i32 %rem, 0
261+
%zext_has_rem = zext i1 %has_rem to i32
262+
%quot_or_rem = or i32 %quot, %zext_has_rem
263+
%res = icmp eq i32 %quot_or_rem, 0
264+
ret i1 %res
265+
}
266+
267+
define i1 @ceil_shift_not_mask_2(i32 %arg0) {
268+
; CHECK-LABEL: define i1 @ceil_shift_not_mask_2(
269+
; CHECK-SAME: i32 [[ARG0:%.*]]) {
270+
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[ARG0]], 5
271+
; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[ARG0]], 15
272+
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
273+
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
274+
; CHECK-NEXT: [[TMP5:%.*]] = or i32 [[TMP1]], [[TMP4]]
275+
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
276+
; CHECK-NEXT: ret i1 [[TMP6]]
277+
;
278+
%quot = lshr i32 %arg0, 5
279+
%rem = and i32 %arg0, 15
280+
%has_rem = icmp ne i32 %rem, 0
281+
%zext_has_rem = zext i1 %has_rem to i32
282+
%quot_or_rem = or i32 %quot, %zext_has_rem
283+
%res = icmp eq i32 %quot_or_rem, 0
284+
ret i1 %res
285+
}

0 commit comments

Comments
 (0)