[ARM] Better OR's for MVE compares
[llvm-core.git] / test / Transforms / InstCombine / and-or-icmps.ll
blob481e0f2fd20dc3dcaf8825284cf58cd6d96f2e97
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 define i1 @PR1817_1(i32 %X) {
5 ; CHECK-LABEL: @PR1817_1(
6 ; CHECK-NEXT:    [[B:%.*]] = icmp ult i32 %X, 10
7 ; CHECK-NEXT:    ret i1 [[B]]
9   %A = icmp slt i32 %X, 10
10   %B = icmp ult i32 %X, 10
11   %C = and i1 %A, %B
12   ret i1 %C
15 define i1 @PR1817_2(i32 %X) {
16 ; CHECK-LABEL: @PR1817_2(
17 ; CHECK-NEXT:    [[A:%.*]] = icmp slt i32 %X, 10
18 ; CHECK-NEXT:    ret i1 [[A]]
20   %A = icmp slt i32 %X, 10
21   %B = icmp ult i32 %X, 10
22   %C = or i1 %A, %B
23   ret i1 %C
26 define i1 @PR2330(i32 %a, i32 %b) {
27 ; CHECK-LABEL: @PR2330(
28 ; CHECK-NEXT:    [[TMP1:%.*]] = or i32 %b, %a
29 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[TMP1]], 8
30 ; CHECK-NEXT:    ret i1 [[TMP2]]
32   %cmp1 = icmp ult i32 %a, 8
33   %cmp2 = icmp ult i32 %b, 8
34   %and = and i1 %cmp2, %cmp1
35   ret i1 %and
38 ; if LHSC and RHSC differ only by one bit:
39 ; (X == C1 || X == C2) -> (X | (C1 ^ C2)) == C2
40 ; PR14708: https://bugs.llvm.org/show_bug.cgi?id=14708
42 define i1 @or_eq_with_one_bit_diff_constants1(i32 %x) {
43 ; CHECK-LABEL: @or_eq_with_one_bit_diff_constants1(
44 ; CHECK-NEXT:    [[TMP1:%.*]] = or i32 %x, 1
45 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 51
46 ; CHECK-NEXT:    ret i1 [[TMP2]]
48   %cmp1 = icmp eq i32 %x, 50
49   %cmp2 = icmp eq i32 %x, 51
50   %or = or i1 %cmp1, %cmp2
51   ret i1 %or
54 ; (X != C1 && X != C2) -> (X | (C1 ^ C2)) != C2
56 define i1 @and_ne_with_one_bit_diff_constants1(i32 %x) {
57 ; CHECK-LABEL: @and_ne_with_one_bit_diff_constants1(
58 ; CHECK-NEXT:    [[TMP1:%.*]] = or i32 %x, 1
59 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 51
60 ; CHECK-NEXT:    ret i1 [[TMP2]]
62   %cmp1 = icmp ne i32 %x, 51
63   %cmp2 = icmp ne i32 %x, 50
64   %and = and i1 %cmp1, %cmp2
65   ret i1 %and
68 ; The constants are not necessarily off-by-one, just off-by-one-bit.
70 define i1 @or_eq_with_one_bit_diff_constants2(i32 %x) {
71 ; CHECK-LABEL: @or_eq_with_one_bit_diff_constants2(
72 ; CHECK-NEXT:    [[TMP1:%.*]] = or i32 %x, 32
73 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 97
74 ; CHECK-NEXT:    ret i1 [[TMP2]]
76   %cmp1 = icmp eq i32 %x, 97
77   %cmp2 = icmp eq i32 %x, 65
78   %or = or i1 %cmp1, %cmp2
79   ret i1 %or
82 define i1 @and_ne_with_one_bit_diff_constants2(i19 %x) {
83 ; CHECK-LABEL: @and_ne_with_one_bit_diff_constants2(
84 ; CHECK-NEXT:    [[TMP1:%.*]] = or i19 %x, 128
85 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i19 [[TMP1]], 193
86 ; CHECK-NEXT:    ret i1 [[TMP2]]
88   %cmp1 = icmp ne i19 %x, 65
89   %cmp2 = icmp ne i19 %x, 193
90   %and = and i1 %cmp1, %cmp2
91   ret i1 %and
94 ; Make sure the constants are treated as unsigned when comparing them.
96 define i1 @or_eq_with_one_bit_diff_constants3(i8 %x) {
97 ; CHECK-LABEL: @or_eq_with_one_bit_diff_constants3(
98 ; CHECK-NEXT:    [[TMP1:%.*]] = or i8 %x, -128
99 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP1]], -2
100 ; CHECK-NEXT:    ret i1 [[TMP2]]
102   %cmp1 = icmp eq i8 %x, 254
103   %cmp2 = icmp eq i8 %x, 126
104   %or = or i1 %cmp1, %cmp2
105   ret i1 %or
108 define i1 @and_ne_with_one_bit_diff_constants3(i8 %x) {
109 ; CHECK-LABEL: @and_ne_with_one_bit_diff_constants3(
110 ; CHECK-NEXT:    [[TMP1:%.*]] = or i8 %x, -128
111 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i8 [[TMP1]], -63
112 ; CHECK-NEXT:    ret i1 [[TMP2]]
114   %cmp1 = icmp ne i8 %x, 65
115   %cmp2 = icmp ne i8 %x, 193
116   %and = and i1 %cmp1, %cmp2
117   ret i1 %and
120 ; Use an 'add' to eliminate an icmp if the constants are off-by-one (not off-by-one-bit).
121 ; (X == 13 | X == 14) -> X-13 <u 2
123 define i1 @or_eq_with_diff_one(i8 %x) {
124 ; CHECK-LABEL: @or_eq_with_diff_one(
125 ; CHECK-NEXT:    [[TMP1:%.*]] = add i8 %x, -13
126 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], 2
127 ; CHECK-NEXT:    ret i1 [[TMP2]]
129   %cmp1 = icmp eq i8 %x, 13
130   %cmp2 = icmp eq i8 %x, 14
131   %or = or i1 %cmp1, %cmp2
132   ret i1 %or
135 ; (X != 40 | X != 39) -> X-39 >u 1
137 define i1 @and_ne_with_diff_one(i32 %x) {
138 ; CHECK-LABEL: @and_ne_with_diff_one(
139 ; CHECK-NEXT:    [[TMP1:%.*]] = add i32 %x, -39
140 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[TMP1]], 1
141 ; CHECK-NEXT:    ret i1 [[TMP2]]
143   %cmp1 = icmp ne i32 %x, 40
144   %cmp2 = icmp ne i32 %x, 39
145   %and = and i1 %cmp1, %cmp2
146   ret i1 %and
149 ; Make sure the constants are treated as signed when comparing them.
150 ; PR32524: https://bugs.llvm.org/show_bug.cgi?id=32524
152 define i1 @or_eq_with_diff_one_signed(i32 %x) {
153 ; CHECK-LABEL: @or_eq_with_diff_one_signed(
154 ; CHECK-NEXT:    [[TMP1:%.*]] = add i32 %x, 1
155 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[TMP1]], 2
156 ; CHECK-NEXT:    ret i1 [[TMP2]]
158   %cmp1 = icmp eq i32 %x, 0
159   %cmp2 = icmp eq i32 %x, -1
160   %or = or i1 %cmp1, %cmp2
161   ret i1 %or
164 define i1 @and_ne_with_diff_one_signed(i64 %x) {
165 ; CHECK-LABEL: @and_ne_with_diff_one_signed(
166 ; CHECK-NEXT:    [[TMP1:%.*]] = add i64 %x, 1
167 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i64 [[TMP1]], 1
168 ; CHECK-NEXT:    ret i1 [[TMP2]]
170   %cmp1 = icmp ne i64 %x, -1
171   %cmp2 = icmp ne i64 %x, 0
172   %and = and i1 %cmp1, %cmp2
173   ret i1 %and
176 ; Vectors with splat constants get the same folds.
178 define <2 x i1> @or_eq_with_one_bit_diff_constants2_splatvec(<2 x i32> %x) {
179 ; CHECK-LABEL: @or_eq_with_one_bit_diff_constants2_splatvec(
180 ; CHECK-NEXT:    [[TMP1:%.*]] = or <2 x i32> %x, <i32 32, i32 32>
181 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq <2 x i32> [[TMP1]], <i32 97, i32 97>
182 ; CHECK-NEXT:    ret <2 x i1> [[TMP2]]
184   %cmp1 = icmp eq <2 x i32> %x, <i32 97, i32 97>
185   %cmp2 = icmp eq <2 x i32> %x, <i32 65, i32 65>
186   %or = or <2 x i1> %cmp1, %cmp2
187   ret <2 x i1> %or
190 define <2 x i1> @and_ne_with_diff_one_splatvec(<2 x i32> %x) {
191 ; CHECK-LABEL: @and_ne_with_diff_one_splatvec(
192 ; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i32> %x, <i32 -39, i32 -39>
193 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt <2 x i32> [[TMP1]], <i32 1, i32 1>
194 ; CHECK-NEXT:    ret <2 x i1> [[TMP2]]
196   %cmp1 = icmp ne <2 x i32> %x, <i32 40, i32 40>
197   %cmp2 = icmp ne <2 x i32> %x, <i32 39, i32 39>
198   %and = and <2 x i1> %cmp1, %cmp2
199   ret <2 x i1> %and
202 ; This is a fuzzer-generated test that would assert because
203 ; we'd get into foldAndOfICmps() without running InstSimplify
204 ; on an 'and' that should have been killed. It's not obvious
205 ; why, but removing anything hides the bug, hence the long test.
207 define void @simplify_before_foldAndOfICmps() {
208 ; CHECK-LABEL: @simplify_before_foldAndOfICmps(
209 ; CHECK-NEXT:    [[A8:%.*]] = alloca i16, align 2
210 ; CHECK-NEXT:    [[L7:%.*]] = load i16, i16* [[A8]], align 2
211 ; CHECK-NEXT:    [[C10:%.*]] = icmp ult i16 [[L7]], 2
212 ; CHECK-NEXT:    [[C7:%.*]] = icmp slt i16 [[L7]], 0
213 ; CHECK-NEXT:    [[C18:%.*]] = or i1 [[C7]], [[C10]]
214 ; CHECK-NEXT:    [[L7_LOBIT:%.*]] = ashr i16 [[L7]], 15
215 ; CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[L7_LOBIT]] to i64
216 ; CHECK-NEXT:    [[G26:%.*]] = getelementptr i1, i1* null, i64 [[TMP1]]
217 ; CHECK-NEXT:    store i16 [[L7]], i16* undef, align 2
218 ; CHECK-NEXT:    store i1 [[C18]], i1* undef, align 1
219 ; CHECK-NEXT:    store i1* [[G26]], i1** undef, align 8
220 ; CHECK-NEXT:    ret void
222   %A8 = alloca i16
223   %L7 = load i16, i16* %A8
224   %G21 = getelementptr i16, i16* %A8, i8 -1
225   %B11 = udiv i16 %L7, -1
226   %G4 = getelementptr i16, i16* %A8, i16 %B11
227   %L2 = load i16, i16* %G4
228   %L = load i16, i16* %G4
229   %B23 = mul i16 %B11, %B11
230   %L4 = load i16, i16* %A8
231   %B21 = sdiv i16 %L7, %L4
232   %B7 = sub i16 0, %B21
233   %B18 = mul i16 %B23, %B7
234   %C10 = icmp ugt i16 %L, %B11
235   %B20 = and i16 %L7, %L2
236   %B1 = mul i1 %C10, true
237   %C5 = icmp sle i16 %B21, %L
238   %C11 = icmp ule i16 %B21, %L
239   %C7 = icmp slt i16 %B20, 0
240   %B29 = srem i16 %L4, %B18
241   %B15 = add i1 %C7, %C10
242   %B19 = add i1 %C11, %B15
243   %C6 = icmp sge i1 %C11, %B19
244   %B33 = or i16 %B29, %L4
245   %C13 = icmp uge i1 %C5, %B1
246   %C3 = icmp ult i1 %C13, %C6
247   store i16 undef, i16* %G21
248   %C18 = icmp ule i1 %C10, %C7
249   %G26 = getelementptr i1, i1* null, i1 %C3
250   store i16 %B33, i16* undef
251   store i1 %C18, i1* undef
252   store i1* %G26, i1** undef
253   ret void
256 define i1 @PR42691_1(i32 %x) {
257 ; CHECK-LABEL: @PR42691_1(
258 ; CHECK-NEXT:    [[C1:%.*]] = icmp slt i32 %x, 0
259 ; CHECK-NEXT:    [[C2:%.*]] = icmp eq i32 %x, 2147483647
260 ; CHECK-NEXT:    [[C:%.*]] = or i1 [[C1]], [[C2]]
261 ; CHECK-NEXT:    ret i1 [[C]]
263   %c1 = icmp slt i32 %x, 0
264   %c2 = icmp eq i32 %x, 2147483647
265   %c = or i1 %c1, %c2
266   ret i1 %c
269 define i1 @PR42691_2(i32 %x) {
270 ; CHECK-LABEL: @PR42691_2(
271 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 %x, -2
272 ; CHECK-NEXT:    ret i1 [[TMP1]]
274   %c1 = icmp ult i32 %x, 2147483648
275   %c2 = icmp eq i32 %x, 4294967295
276   %c = or i1 %c1, %c2
277   ret i1 %c
280 define i1 @PR42691_3(i32 %x) {
281 ; CHECK-LABEL: @PR42691_3(
282 ; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i32 %x, -1
283 ; CHECK-NEXT:    [[C2:%.*]] = icmp eq i32 %x, -2147483648
284 ; CHECK-NEXT:    [[C:%.*]] = or i1 [[C1]], [[C2]]
285 ; CHECK-NEXT:    ret i1 [[C]]
287   %c1 = icmp sge i32 %x, 0
288   %c2 = icmp eq i32 %x, -2147483648
289   %c = or i1 %c1, %c2
290   ret i1 %c
293 define i1 @PR42691_4(i32 %x) {
294 ; CHECK-LABEL: @PR42691_4(
295 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 %x, 1
296 ; CHECK-NEXT:    ret i1 [[TMP1]]
298   %c1 = icmp uge i32 %x, 2147483648
299   %c2 = icmp eq i32 %x, 0
300   %c = or i1 %c1, %c2
301   ret i1 %c
304 define i1 @PR42691_5(i32 %x) {
305 ; CHECK-LABEL: @PR42691_5(
306 ; CHECK-NEXT:    [[C1:%.*]] = icmp slt i32 %x, 1
307 ; CHECK-NEXT:    [[C2:%.*]] = icmp eq i32 %x, 2147483647
308 ; CHECK-NEXT:    [[C:%.*]] = or i1 [[C1]], [[C2]]
309 ; CHECK-NEXT:    ret i1 [[C]]
311   %c1 = icmp slt i32 %x, 1
312   %c2 = icmp eq i32 %x, 2147483647
313   %c = or i1 %c1, %c2
314   ret i1 %c
317 define i1 @PR42691_6(i32 %x) {
318 ; CHECK-LABEL: @PR42691_6(
319 ; CHECK-NEXT:    [[C1:%.*]] = icmp ult i32 %x, -2147483647
320 ; CHECK-NEXT:    [[C2:%.*]] = icmp eq i32 %x, -1
321 ; CHECK-NEXT:    [[C:%.*]] = or i1 [[C1]], [[C2]]
322 ; CHECK-NEXT:    ret i1 [[C]]
324   %c1 = icmp ult i32 %x, 2147483649
325   %c2 = icmp eq i32 %x, 4294967295
326   %c = or i1 %c1, %c2
327   ret i1 %c
330 define i1 @PR42691_7(i32 %x) {
331 ; CHECK-LABEL: @PR42691_7(
332 ; CHECK-NEXT:    [[TMP1:%.*]] = add i32 %x, -1
333 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
334 ; CHECK-NEXT:    ret i1 [[TMP2]]
336   %c1 = icmp uge i32 %x, 2147483649
337   %c2 = icmp eq i32 %x, 0
338   %c = or i1 %c1, %c2
339   ret i1 %c
342 define i1 @PR42691_8(i32 %x) {
343 ; CHECK-LABEL: @PR42691_8(
344 ; CHECK-NEXT:    [[C1:%.*]] = icmp slt i32 %x, 14
345 ; CHECK-NEXT:    [[C2:%.*]] = icmp ne i32 %x, -2147483648
346 ; CHECK-NEXT:    [[C:%.*]] = and i1 [[C1]], [[C2]]
347 ; CHECK-NEXT:    ret i1 [[C]]
349   %c1 = icmp slt i32 %x, 14
350   %c2 = icmp ne i32 %x, -2147483648
351   %c = and i1 %c1, %c2
352   ret i1 %c
355 define i1 @PR42691_9(i32 %x) {
356 ; CHECK-LABEL: @PR42691_9(
357 ; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i32 %x, 13
358 ; CHECK-NEXT:    [[C2:%.*]] = icmp ne i32 %x, 2147483647
359 ; CHECK-NEXT:    [[C:%.*]] = and i1 [[C1]], [[C2]]
360 ; CHECK-NEXT:    ret i1 [[C]]
362   %c1 = icmp sgt i32 %x, 13
363   %c2 = icmp ne i32 %x, 2147483647
364   %c = and i1 %c1, %c2
365   ret i1 %c
368 define i1 @PR42691_10(i32 %x) {
369 ; CHECK-LABEL: @PR42691_10(
370 ; CHECK-NEXT:    [[C1:%.*]] = icmp ugt i32 %x, 13
371 ; CHECK-NEXT:    [[C2:%.*]] = icmp ne i32 %x, -1
372 ; CHECK-NEXT:    [[C:%.*]] = and i1 [[C1]], [[C2]]
373 ; CHECK-NEXT:    ret i1 [[C]]
375   %c1 = icmp ugt i32 %x, 13
376   %c2 = icmp ne i32 %x, 4294967295
377   %c = and i1 %c1, %c2
378   ret i1 %c