xref: /llvm-project/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4; For pattern ((X l>> Y) & ~C) ==/!= 0; when C+1 is power of 2
5; it may be optimal to fold into (X l>> Y) </>= C+1
6; rather than X & (~C << Y) ==/!= 0
7
8; Scalar tests
9
10define i1 @scalar_i8_lshr_and_negC_eq(i8 %x, i8 %y) {
11; CHECK-LABEL: @scalar_i8_lshr_and_negC_eq(
12; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X:%.*]], [[Y:%.*]]
13; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[LSHR]], 4
14; CHECK-NEXT:    ret i1 [[R]]
15;
16  %lshr = lshr i8 %x, %y
17  %and = and i8 %lshr, 252  ; ~3
18  %r = icmp eq i8 %and, 0
19  ret i1 %r
20}
21
22define i1 @scalar_i16_lshr_and_negC_eq(i16 %x, i16 %y) {
23; CHECK-LABEL: @scalar_i16_lshr_and_negC_eq(
24; CHECK-NEXT:    [[LSHR:%.*]] = lshr i16 [[X:%.*]], [[Y:%.*]]
25; CHECK-NEXT:    [[R:%.*]] = icmp ult i16 [[LSHR]], 128
26; CHECK-NEXT:    ret i1 [[R]]
27;
28  %lshr = lshr i16 %x, %y
29  %and = and i16 %lshr, 65408  ; ~127
30  %r = icmp eq i16 %and, 0
31  ret i1 %r
32}
33
34define i1 @scalar_i32_lshr_and_negC_eq(i32 %x, i32 %y) {
35; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq(
36; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
37; CHECK-NEXT:    [[R:%.*]] = icmp ult i32 [[LSHR]], 262144
38; CHECK-NEXT:    ret i1 [[R]]
39;
40  %lshr = lshr i32 %x, %y
41  %and = and i32 %lshr, 4294705152  ; ~262143
42  %r = icmp eq i32 %and, 0
43  ret i1 %r
44}
45
46define i1 @scalar_i64_lshr_and_negC_eq(i64 %x, i64 %y) {
47; CHECK-LABEL: @scalar_i64_lshr_and_negC_eq(
48; CHECK-NEXT:    [[LSHR:%.*]] = lshr i64 [[X:%.*]], [[Y:%.*]]
49; CHECK-NEXT:    [[R:%.*]] = icmp ult i64 [[LSHR]], 8589934592
50; CHECK-NEXT:    ret i1 [[R]]
51;
52  %lshr = lshr i64 %x, %y
53  %and = and i64 %lshr, 18446744065119617024  ; ~8589934591
54  %r = icmp eq i64 %and, 0
55  ret i1 %r
56}
57
58define i1 @scalar_i32_lshr_and_negC_ne(i32 %x, i32 %y) {
59; CHECK-LABEL: @scalar_i32_lshr_and_negC_ne(
60; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
61; CHECK-NEXT:    [[R:%.*]] = icmp ugt i32 [[LSHR]], 262143
62; CHECK-NEXT:    ret i1 [[R]]
63;
64  %lshr = lshr i32 %x, %y
65  %and = and i32 %lshr, 4294705152  ; ~262143
66  %r = icmp ne i32 %and, 0   ; check 'ne' predicate
67  ret i1 %r
68}
69
70; Vector tests
71
72define <4 x i1> @vec_4xi32_lshr_and_negC_eq(<4 x i32> %x, <4 x i32> %y) {
73; CHECK-LABEL: @vec_4xi32_lshr_and_negC_eq(
74; CHECK-NEXT:    [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]]
75; CHECK-NEXT:    [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], splat (i32 8)
76; CHECK-NEXT:    ret <4 x i1> [[R]]
77;
78  %lshr = lshr <4 x i32> %x, %y
79  %and = and <4 x i32> %lshr, <i32 4294967288, i32 4294967288, i32 4294967288, i32 4294967288>  ; ~7
80  %r = icmp eq <4 x i32> %and, <i32 0, i32 0, i32 0, i32 0>
81  ret <4 x i1> %r
82}
83
84define <4 x i1> @vec_lshr_and_negC_eq_poison1(<4 x i32> %x, <4 x i32> %y) {
85; CHECK-LABEL: @vec_lshr_and_negC_eq_poison1(
86; CHECK-NEXT:    [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]]
87; CHECK-NEXT:    [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], splat (i32 8)
88; CHECK-NEXT:    ret <4 x i1> [[R]]
89;
90  %lshr = lshr <4 x i32> %x, %y
91  %and = and <4 x i32> %lshr, <i32 4294967288, i32 poison, i32 4294967288, i32 4294967288>  ; ~7
92  %r = icmp eq <4 x i32> %and, <i32 0, i32 0, i32 0, i32 0>
93  ret <4 x i1> %r
94}
95
96define <4 x i1> @vec_lshr_and_negC_eq_poison2(<4 x i32> %x, <4 x i32> %y) {
97; CHECK-LABEL: @vec_lshr_and_negC_eq_poison2(
98; CHECK-NEXT:    [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]]
99; CHECK-NEXT:    [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], splat (i32 8)
100; CHECK-NEXT:    ret <4 x i1> [[R]]
101;
102  %lshr = lshr <4 x i32> %x, %y
103  %and = and <4 x i32> %lshr, <i32 4294967288, i32 4294967288, i32 4294967288, i32 4294967288>  ; ~7
104  %r = icmp eq <4 x i32> %and, <i32 0, i32 0, i32 0, i32 poison>
105  ret <4 x i1> %r
106}
107
108define <4 x i1> @vec_lshr_and_negC_eq_poison3(<4 x i32> %x, <4 x i32> %y) {
109; CHECK-LABEL: @vec_lshr_and_negC_eq_poison3(
110; CHECK-NEXT:    [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]]
111; CHECK-NEXT:    [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], splat (i32 8)
112; CHECK-NEXT:    ret <4 x i1> [[R]]
113;
114  %lshr = lshr <4 x i32> %x, %y
115  %and = and <4 x i32> %lshr, <i32 4294967288, i32 4294967288, i32 poison, i32 4294967288>  ; ~7
116  %r = icmp eq <4 x i32> %and, <i32 0, i32 0, i32 0, i32 poison>
117  ret <4 x i1> %r
118}
119
120; Extra use
121
122; Fold happened
123define i1 @scalar_lshr_and_negC_eq_extra_use_lshr(i32 %x, i32 %y, i32 %z, ptr %p) {
124; CHECK-LABEL: @scalar_lshr_and_negC_eq_extra_use_lshr(
125; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
126; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[LSHR]], [[Z:%.*]]
127; CHECK-NEXT:    store i32 [[XOR]], ptr [[P:%.*]], align 4
128; CHECK-NEXT:    [[R:%.*]] = icmp ult i32 [[LSHR]], 8
129; CHECK-NEXT:    ret i1 [[R]]
130;
131  %lshr = lshr i32 %x, %y
132  %xor = xor i32 %lshr, %z  ; extra use of lshr
133  store i32 %xor, ptr %p
134  %and = and i32 %lshr, 4294967288  ; ~7
135  %r = icmp eq i32 %and, 0
136  ret i1 %r
137}
138
139; Not fold
140define i1 @scalar_lshr_and_negC_eq_extra_use_and(i32 %x, i32 %y, i32 %z, ptr %p) {
141; CHECK-LABEL: @scalar_lshr_and_negC_eq_extra_use_and(
142; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
143; CHECK-NEXT:    [[AND:%.*]] = and i32 [[LSHR]], -8
144; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[AND]], [[Z:%.*]]
145; CHECK-NEXT:    store i32 [[MUL]], ptr [[P:%.*]], align 4
146; CHECK-NEXT:    [[R:%.*]] = icmp eq i32 [[AND]], 0
147; CHECK-NEXT:    ret i1 [[R]]
148;
149  %lshr = lshr i32 %x, %y
150  %and = and i32 %lshr, 4294967288  ; ~7
151  %mul = mul i32 %and, %z  ; extra use of and
152  store i32 %mul, ptr %p
153  %r = icmp eq i32 %and, 0
154  ret i1 %r
155}
156
157; Not fold
158define i1 @scalar_lshr_and_negC_eq_extra_use_lshr_and(i32 %x, i32 %y, i32 %z, ptr %p, ptr %q) {
159; CHECK-LABEL: @scalar_lshr_and_negC_eq_extra_use_lshr_and(
160; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
161; CHECK-NEXT:    [[AND:%.*]] = and i32 [[LSHR]], -8
162; CHECK-NEXT:    store i32 [[AND]], ptr [[P:%.*]], align 4
163; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[LSHR]], [[Z:%.*]]
164; CHECK-NEXT:    store i32 [[ADD]], ptr [[Q:%.*]], align 4
165; CHECK-NEXT:    [[R:%.*]] = icmp eq i32 [[AND]], 0
166; CHECK-NEXT:    ret i1 [[R]]
167;
168  %lshr = lshr i32 %x, %y
169  %and = and i32 %lshr, 4294967288  ; ~7
170  store i32 %and, ptr %p  ; extra use of and
171  %add = add i32 %lshr, %z  ; extra use of lshr
172  store i32 %add, ptr %q
173  %r = icmp eq i32 %and, 0
174  ret i1 %r
175}
176
177define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant1(i32 %y) {
178; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_X_is_constant1(
179; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 12345, [[Y:%.*]]
180; CHECK-NEXT:    [[R:%.*]] = icmp samesign ult i32 [[LSHR]], 8
181; CHECK-NEXT:    ret i1 [[R]]
182;
183  %lshr = lshr i32 12345, %y
184  %and = and i32 %lshr, 4294967288  ; ~7
185  %r = icmp eq i32 %and, 0
186  ret i1 %r
187}
188
189define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant2(i32 %y) {
190; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_X_is_constant2(
191; CHECK-NEXT:    [[R:%.*]] = icmp ugt i32 [[Y:%.*]], 25
192; CHECK-NEXT:    ret i1 [[R]]
193;
194  %lshr = lshr i32 268435456, %y
195  %and = and i32 %lshr, 4294967288  ; ~7
196  %r = icmp eq i32 %and, 0
197  ret i1 %r
198}
199define i1 @scalar_i32_udiv_and_negC_eq_X_is_constant3(i32 %y) {
200; CHECK-LABEL: @scalar_i32_udiv_and_negC_eq_X_is_constant3(
201; CHECK-NEXT:    [[R:%.*]] = icmp ult i32 [[Y:%.*]], 1544
202; CHECK-NEXT:    ret i1 [[R]]
203;
204  %lshr = udiv  i32 12345, %y
205  %and = and i32 %lshr, 16376    ; 0x3ff8
206  %r = icmp ne i32 %and, 0
207  ret i1 %r
208}
209
210; Negative test
211
212define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant_negative(i32 %y) {
213; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_X_is_constant_negative(
214; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 16384, [[Y:%.*]]
215; CHECK-NEXT:    [[AND:%.*]] = and i32 [[LSHR]], 16376
216; CHECK-NEXT:    [[R:%.*]] = icmp eq i32 [[AND]], 0
217; CHECK-NEXT:    ret i1 [[R]]
218;
219  %lshr = lshr i32 16384, %y    ; 0x4000
220  %and = and i32 %lshr, 16376   ; 0x3ff8
221  %r = icmp eq i32 %and, 0
222  ret i1 %r
223}
224; Check 'slt' predicate
225
226define i1 @scalar_i32_lshr_and_negC_slt(i32 %x, i32 %y) {
227; CHECK-LABEL: @scalar_i32_lshr_and_negC_slt(
228; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
229; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[LSHR]], 0
230; CHECK-NEXT:    ret i1 [[R]]
231;
232  %lshr = lshr i32 %x, %y
233  %and = and i32 %lshr, 4294967288  ; ~7
234  %r = icmp slt i32 %and, 0
235  ret i1 %r
236}
237
238; Compare with nonzero
239
240define i1 @scalar_i32_lshr_and_negC_eq_nonzero(i32 %x, i32 %y) {
241; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_nonzero(
242; CHECK-NEXT:    ret i1 false
243;
244  %lshr = lshr i32 %x, %y
245  %and = and i32 %lshr, 4294967288  ; ~7
246  %r = icmp eq i32 %and, 1  ; should be comparing with 0
247  ret i1 %r
248}
249
250; Not NegatedPowerOf2
251
252define i1 @scalar_i8_lshr_and_negC_eq_not_negatedPowerOf2(i8 %x, i8 %y) {
253; CHECK-LABEL: @scalar_i8_lshr_and_negC_eq_not_negatedPowerOf2(
254; CHECK-NEXT:    [[TMP1:%.*]] = shl i8 -3, [[Y:%.*]]
255; CHECK-NEXT:    [[TMP2:%.*]] = and i8 [[X:%.*]], [[TMP1]]
256; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[TMP2]], 0
257; CHECK-NEXT:    ret i1 [[R]]
258;
259  %lshr = lshr i8 %x, %y
260  %and = and i8 %lshr, 253  ; -3
261  %r = icmp eq i8 %and, 0
262  ret i1 %r
263}
264