Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / InstCombine / xor-icmps.ll
blobf104cd7fdcada554c139cac765c76ac637ad5cbd
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 define i1 @eq_zero(i4 %x, i4 %y) {
5 ; CHECK-LABEL: @eq_zero(
6 ; CHECK-NEXT:    [[I0:%.*]] = icmp eq i4 [[X:%.*]], 0
7 ; CHECK-NEXT:    [[I1:%.*]] = icmp eq i4 [[Y:%.*]], 0
8 ; CHECK-NEXT:    [[R:%.*]] = xor i1 [[I0]], [[I1]]
9 ; CHECK-NEXT:    ret i1 [[R]]
11   %i0 = icmp eq i4 %x, 0
12   %i1 = icmp eq i4 %y, 0
13   %r = xor i1 %i0, %i1
14   ret i1 %r
17 define i1 @ne_zero(i4 %x, i4 %y) {
18 ; CHECK-LABEL: @ne_zero(
19 ; CHECK-NEXT:    [[I0:%.*]] = icmp ne i4 [[X:%.*]], 0
20 ; CHECK-NEXT:    [[I1:%.*]] = icmp ne i4 [[Y:%.*]], 0
21 ; CHECK-NEXT:    [[R:%.*]] = xor i1 [[I0]], [[I1]]
22 ; CHECK-NEXT:    ret i1 [[R]]
24   %i0 = icmp ne i4 %x, 0
25   %i1 = icmp ne i4 %y, 0
26   %r = xor i1 %i0, %i1
27   ret i1 %r
30 define i1 @eq_ne_zero(i4 %x, i4 %y) {
31 ; CHECK-LABEL: @eq_ne_zero(
32 ; CHECK-NEXT:    [[I0:%.*]] = icmp eq i4 [[X:%.*]], 0
33 ; CHECK-NEXT:    [[I1:%.*]] = icmp ne i4 [[Y:%.*]], 0
34 ; CHECK-NEXT:    [[R:%.*]] = xor i1 [[I0]], [[I1]]
35 ; CHECK-NEXT:    ret i1 [[R]]
37   %i0 = icmp eq i4 %x, 0
38   %i1 = icmp ne i4 %y, 0
39   %r = xor i1 %i0, %i1
40   ret i1 %r
43 define i1 @slt_zero(i4 %x, i4 %y) {
44 ; CHECK-LABEL: @slt_zero(
45 ; CHECK-NEXT:    [[TMP1:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
46 ; CHECK-NEXT:    [[R:%.*]] = icmp slt i4 [[TMP1]], 0
47 ; CHECK-NEXT:    ret i1 [[R]]
49   %i0 = icmp slt i4 %x, 0
50   %i1 = icmp slt i4 %y, 0
51   %r = xor i1 %i0, %i1
52   ret i1 %r
55 ; Don't increase the instruction count.
57 declare void @use(i1)
59 define i1 @slt_zero_extra_uses(i4 %x, i4 %y) {
60 ; CHECK-LABEL: @slt_zero_extra_uses(
61 ; CHECK-NEXT:    [[I0:%.*]] = icmp slt i4 [[X:%.*]], 0
62 ; CHECK-NEXT:    [[I1:%.*]] = icmp slt i4 [[Y:%.*]], 0
63 ; CHECK-NEXT:    [[R:%.*]] = xor i1 [[I0]], [[I1]]
64 ; CHECK-NEXT:    call void @use(i1 [[I0]])
65 ; CHECK-NEXT:    call void @use(i1 [[I1]])
66 ; CHECK-NEXT:    ret i1 [[R]]
68   %i0 = icmp slt i4 %x, 0
69   %i1 = icmp slt i4 %y, 0
70   %r = xor i1 %i0, %i1
71   call void @use(i1 %i0)
72   call void @use(i1 %i1)
73   ret i1 %r
76 define i1 @sgt_zero(i4 %x, i4 %y) {
77 ; CHECK-LABEL: @sgt_zero(
78 ; CHECK-NEXT:    [[I0:%.*]] = icmp sgt i4 [[X:%.*]], 0
79 ; CHECK-NEXT:    [[I1:%.*]] = icmp sgt i4 [[Y:%.*]], 0
80 ; CHECK-NEXT:    [[R:%.*]] = xor i1 [[I0]], [[I1]]
81 ; CHECK-NEXT:    ret i1 [[R]]
83   %i0 = icmp sgt i4 %x, 0
84   %i1 = icmp sgt i4 %y, 0
85   %r = xor i1 %i0, %i1
86   ret i1 %r
89 define i1 @sgt_minus1(i4 %x, i4 %y) {
90 ; CHECK-LABEL: @sgt_minus1(
91 ; CHECK-NEXT:    [[TMP1:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
92 ; CHECK-NEXT:    [[R:%.*]] = icmp slt i4 [[TMP1]], 0
93 ; CHECK-NEXT:    ret i1 [[R]]
95   %i0 = icmp sgt i4 %x, -1
96   %i1 = icmp sgt i4 %y, -1
97   %r = xor i1 %i0, %i1
98   ret i1 %r
101 define i1 @slt_zero_sgt_minus1(i4 %x, i4 %y) {
102 ; CHECK-LABEL: @slt_zero_sgt_minus1(
103 ; CHECK-NEXT:    [[TMP1:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
104 ; CHECK-NEXT:    [[R:%.*]] = icmp sgt i4 [[TMP1]], -1
105 ; CHECK-NEXT:    ret i1 [[R]]
107   %i0 = icmp slt i4 %x, 0
108   %i1 = icmp sgt i4 %y, -1
109   %r = xor i1 %i0, %i1
110   ret i1 %r
113 define <2 x i1> @sgt_minus1_slt_zero_sgt(<2 x i4> %x, <2 x i4> %y) {
114 ; CHECK-LABEL: @sgt_minus1_slt_zero_sgt(
115 ; CHECK-NEXT:    [[TMP1:%.*]] = xor <2 x i4> [[Y:%.*]], [[X:%.*]]
116 ; CHECK-NEXT:    [[R:%.*]] = icmp sgt <2 x i4> [[TMP1]], <i4 -1, i4 -1>
117 ; CHECK-NEXT:    ret <2 x i1> [[R]]
119   %i1 = icmp sgt <2 x i4> %x, <i4 -1, i4 -1>
120   %i0 = icmp slt <2 x i4> %y, zeroinitializer
121   %r = xor <2 x i1> %i0, %i1
122   ret <2 x i1> %r
125 ; Don't try (crash) if the operand types don't match.
127 define i1 @different_type_cmp_ops(i32 %x, i64 %y) {
128 ; CHECK-LABEL: @different_type_cmp_ops(
129 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[X:%.*]], 0
130 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i64 [[Y:%.*]], 0
131 ; CHECK-NEXT:    [[R:%.*]] = xor i1 [[CMP1]], [[CMP2]]
132 ; CHECK-NEXT:    ret i1 [[R]]
134   %cmp1 = icmp slt i32 %x, 0
135   %cmp2 = icmp slt i64 %y, 0
136   %r = xor i1 %cmp1, %cmp2
137   ret i1 %r
140 define i1 @test13(i8 %A, i8 %B) {
141 ; CHECK-LABEL: @test13(
142 ; CHECK-NEXT:    [[E:%.*]] = icmp ne i8 [[A:%.*]], [[B:%.*]]
143 ; CHECK-NEXT:    ret i1 [[E]]
145   %C = icmp ult i8 %A, %B
146   %D = icmp ugt i8 %A, %B
147   %E = xor i1 %C, %D
148   ret i1 %E
151 define i1 @test14(i8 %A, i8 %B) {
152 ; CHECK-LABEL: @test14(
153 ; CHECK-NEXT:    ret i1 true
155   %C = icmp eq i8 %A, %B
156   %D = icmp ne i8 %B, %A
157   %E = xor i1 %C, %D
158   ret i1 %E
161 define i1 @xor_icmp_ptr(ptr %c, ptr %d) {
162 ; CHECK-LABEL: @xor_icmp_ptr(
163 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt ptr [[C:%.*]], null
164 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt ptr [[D:%.*]], null
165 ; CHECK-NEXT:    [[XOR:%.*]] = xor i1 [[CMP]], [[CMP1]]
166 ; CHECK-NEXT:    ret i1 [[XOR]]
168   %cmp = icmp slt ptr %c, null
169   %cmp1 = icmp slt ptr %d, null
170   %xor = xor i1 %cmp, %cmp1
171   ret i1 %xor
174 ; Tests from PR70928
175 define i1 @xor_icmp_true_signed(i32 %a) {
176 ; CHECK-LABEL: @xor_icmp_true_signed(
177 ; CHECK-NEXT:    ret i1 true
179   %cmp = icmp sgt i32 %a, 5
180   %cmp1 = icmp slt i32 %a, 6
181   %cmp3 = xor i1 %cmp, %cmp1
182   ret i1 %cmp3
184 define i1 @xor_icmp_true_signed_multiuse1(i32 %a) {
185 ; CHECK-LABEL: @xor_icmp_true_signed_multiuse1(
186 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5
187 ; CHECK-NEXT:    call void @use(i1 [[CMP]])
188 ; CHECK-NEXT:    ret i1 true
190   %cmp = icmp sgt i32 %a, 5
191   call void @use(i1 %cmp)
192   %cmp1 = icmp slt i32 %a, 6
193   %cmp3 = xor i1 %cmp, %cmp1
194   ret i1 %cmp3
196 define i1 @xor_icmp_true_signed_multiuse2(i32 %a) {
197 ; CHECK-LABEL: @xor_icmp_true_signed_multiuse2(
198 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5
199 ; CHECK-NEXT:    call void @use(i1 [[CMP]])
200 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A]], 6
201 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
202 ; CHECK-NEXT:    ret i1 true
204   %cmp = icmp sgt i32 %a, 5
205   call void @use(i1 %cmp)
206   %cmp1 = icmp slt i32 %a, 6
207   call void @use(i1 %cmp1)
208   %cmp3 = xor i1 %cmp, %cmp1
209   ret i1 %cmp3
211 define i1 @xor_icmp_true_signed_commuted(i32 %a) {
212 ; CHECK-LABEL: @xor_icmp_true_signed_commuted(
213 ; CHECK-NEXT:    ret i1 true
215   %cmp = icmp sgt i32 %a, 5
216   %cmp1 = icmp slt i32 %a, 6
217   %cmp3 = xor i1 %cmp1, %cmp
218   ret i1 %cmp3
220 define i1 @xor_icmp_true_unsigned(i32 %a) {
221 ; CHECK-LABEL: @xor_icmp_true_unsigned(
222 ; CHECK-NEXT:    ret i1 true
224   %cmp = icmp ugt i32 %a, 5
225   %cmp1 = icmp ult i32 %a, 6
226   %cmp3 = xor i1 %cmp, %cmp1
227   ret i1 %cmp3
229 define i1 @xor_icmp_to_ne(i32 %a) {
230 ; CHECK-LABEL: @xor_icmp_to_ne(
231 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp ne i32 [[A:%.*]], 5
232 ; CHECK-NEXT:    ret i1 [[CMP3]]
234   %cmp = icmp sgt i32 %a, 4
235   %cmp1 = icmp slt i32 %a, 6
236   %cmp3 = xor i1 %cmp, %cmp1
237   ret i1 %cmp3
239 define i1 @xor_icmp_to_ne_multiuse1(i32 %a) {
240 ; CHECK-LABEL: @xor_icmp_to_ne_multiuse1(
241 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 4
242 ; CHECK-NEXT:    call void @use(i1 [[CMP]])
243 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp ne i32 [[A]], 5
244 ; CHECK-NEXT:    ret i1 [[CMP3]]
246   %cmp = icmp sgt i32 %a, 4
247   call void @use(i1 %cmp)
248   %cmp1 = icmp slt i32 %a, 6
249   %cmp3 = xor i1 %cmp, %cmp1
250   ret i1 %cmp3
252 define i1 @xor_icmp_to_icmp_add(i32 %a) {
253 ; CHECK-LABEL: @xor_icmp_to_icmp_add(
254 ; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[A:%.*]], -6
255 ; CHECK-NEXT:    [[CMP3:%.*]] = icmp ult i32 [[TMP1]], -2
256 ; CHECK-NEXT:    ret i1 [[CMP3]]
258   %cmp = icmp sgt i32 %a, 3
259   %cmp1 = icmp slt i32 %a, 6
260   %cmp3 = xor i1 %cmp, %cmp1
261   ret i1 %cmp3
263 ; Negative tests
264 ; The result of ConstantRange::difference is not exact.
265 define i1 @xor_icmp_invalid_range(i8 %x0) {
266 ; CHECK-LABEL: @xor_icmp_invalid_range(
267 ; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[X0:%.*]], -5
268 ; CHECK-NEXT:    [[OR_COND:%.*]] = icmp ne i8 [[TMP1]], 0
269 ; CHECK-NEXT:    ret i1 [[OR_COND]]
271   %cmp = icmp eq i8 %x0, 0
272   %cmp4 = icmp ne i8 %x0, 4
273   %or.cond = xor i1 %cmp, %cmp4
274   ret i1 %or.cond
276 define i1 @xor_icmp_to_ne_multiuse2(i32 %a) {
277 ; CHECK-LABEL: @xor_icmp_to_ne_multiuse2(
278 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 4
279 ; CHECK-NEXT:    call void @use(i1 [[CMP]])
280 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A]], 6
281 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
282 ; CHECK-NEXT:    [[CMP3:%.*]] = xor i1 [[CMP]], [[CMP1]]
283 ; CHECK-NEXT:    ret i1 [[CMP3]]
285   %cmp = icmp sgt i32 %a, 4
286   call void @use(i1 %cmp)
287   %cmp1 = icmp slt i32 %a, 6
288   call void @use(i1 %cmp1)
289   %cmp3 = xor i1 %cmp, %cmp1
290   ret i1 %cmp3
292 define i1 @xor_icmp_to_icmp_add_multiuse1(i32 %a) {
293 ; CHECK-LABEL: @xor_icmp_to_icmp_add_multiuse1(
294 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 3
295 ; CHECK-NEXT:    call void @use(i1 [[CMP]])
296 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A]], 6
297 ; CHECK-NEXT:    [[CMP3:%.*]] = xor i1 [[CMP]], [[CMP1]]
298 ; CHECK-NEXT:    ret i1 [[CMP3]]
300   %cmp = icmp sgt i32 %a, 3
301   call void @use(i1 %cmp)
302   %cmp1 = icmp slt i32 %a, 6
303   %cmp3 = xor i1 %cmp, %cmp1
304   ret i1 %cmp3
306 define i1 @xor_icmp_to_icmp_add_multiuse2(i32 %a) {
307 ; CHECK-LABEL: @xor_icmp_to_icmp_add_multiuse2(
308 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 3
309 ; CHECK-NEXT:    call void @use(i1 [[CMP]])
310 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A]], 6
311 ; CHECK-NEXT:    call void @use(i1 [[CMP1]])
312 ; CHECK-NEXT:    [[CMP3:%.*]] = xor i1 [[CMP]], [[CMP1]]
313 ; CHECK-NEXT:    ret i1 [[CMP3]]
315   %cmp = icmp sgt i32 %a, 3
316   call void @use(i1 %cmp)
317   %cmp1 = icmp slt i32 %a, 6
318   call void @use(i1 %cmp1)
319   %cmp3 = xor i1 %cmp, %cmp1
320   ret i1 %cmp3