xref: /llvm-project/llvm/test/Transforms/InstCombine/icmp-of-and-x.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
4declare i1 @barrier()
5declare void @llvm.assume(i1)
6declare void @use.i8(i8)
7
8define i1 @icmp_ult_x_y(i8 %x, i8 %y) {
9; CHECK-LABEL: @icmp_ult_x_y(
10; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], [[Y:%.*]]
11; CHECK-NEXT:    [[Z:%.*]] = icmp ne i8 [[AND]], [[X]]
12; CHECK-NEXT:    ret i1 [[Z]]
13;
14  %and = and i8 %x, %y
15  %z = icmp ult i8 %and, %x
16  ret i1 %z
17}
18
19define i1 @icmp_ult_x_y_2(i8 %xx, i8 %y) {
20; CHECK-LABEL: @icmp_ult_x_y_2(
21; CHECK-NEXT:    [[X:%.*]] = mul i8 [[XX:%.*]], [[XX]]
22; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X]], [[Y:%.*]]
23; CHECK-NEXT:    [[Z:%.*]] = icmp ne i8 [[AND]], [[X]]
24; CHECK-NEXT:    ret i1 [[Z]]
25;
26  %x = mul i8 %xx, %xx
27  %and = and i8 %x, %y
28  %z = icmp ugt i8 %x, %and
29  ret i1 %z
30}
31
32define <2 x i1> @icmp_uge_x_y(<2 x i8> %x, <2 x i8> %y) {
33; CHECK-LABEL: @icmp_uge_x_y(
34; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], [[Y:%.*]]
35; CHECK-NEXT:    [[Z:%.*]] = icmp eq <2 x i8> [[AND]], [[X]]
36; CHECK-NEXT:    ret <2 x i1> [[Z]]
37;
38  %and = and <2 x i8> %x, %y
39  %z = icmp uge <2 x i8> %and, %x
40  ret <2 x i1> %z
41}
42
43define i1 @icmp_uge_x_y_2(i8 %xx, i8 %y) {
44; CHECK-LABEL: @icmp_uge_x_y_2(
45; CHECK-NEXT:    [[X:%.*]] = mul i8 [[XX:%.*]], [[XX]]
46; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X]], [[Y:%.*]]
47; CHECK-NEXT:    [[Z:%.*]] = icmp eq i8 [[AND]], [[X]]
48; CHECK-NEXT:    ret i1 [[Z]]
49;
50  %x = mul i8 %xx, %xx
51  %and = and i8 %x, %y
52  %z = icmp ule i8 %x, %and
53  ret i1 %z
54}
55
56define i1 @icmp_sge_x_negy(i8 %x, i8 %y) {
57; CHECK-LABEL: @icmp_sge_x_negy(
58; CHECK-NEXT:    [[CY:%.*]] = icmp slt i8 [[Y:%.*]], 0
59; CHECK-NEXT:    call void @llvm.assume(i1 [[CY]])
60; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], [[Y]]
61; CHECK-NEXT:    [[Z:%.*]] = icmp eq i8 [[AND]], [[X]]
62; CHECK-NEXT:    ret i1 [[Z]]
63;
64  %cy = icmp slt i8 %y, 0
65  call void @llvm.assume(i1 %cy)
66  %and = and i8 %x, %y
67  %z = icmp sge i8 %and, %x
68  ret i1 %z
69}
70
71define i1 @icmp_slt_x_negy(i8 %x, i8 %y) {
72; CHECK-LABEL: @icmp_slt_x_negy(
73; CHECK-NEXT:    [[CY:%.*]] = icmp slt i8 [[Y:%.*]], 0
74; CHECK-NEXT:    br i1 [[CY]], label [[NEGY:%.*]], label [[POSY:%.*]]
75; CHECK:       negy:
76; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], [[Y]]
77; CHECK-NEXT:    [[Z:%.*]] = icmp ne i8 [[AND]], [[X]]
78; CHECK-NEXT:    ret i1 [[Z]]
79; CHECK:       posy:
80; CHECK-NEXT:    [[R:%.*]] = call i1 @barrier()
81; CHECK-NEXT:    ret i1 [[R]]
82;
83  %cy = icmp slt i8 %y, 0
84  br i1 %cy, label %negy, label %posy
85negy:
86  %and = and i8 %x, %y
87  %z = icmp slt i8 %and, %x
88  ret i1 %z
89posy:
90  %r = call i1 @barrier()
91  ret i1 %r
92}
93
94define i1 @icmp_slt_x_negy_fail_maybe_zero(i8 %x, i8 %y) {
95; CHECK-LABEL: @icmp_slt_x_negy_fail_maybe_zero(
96; CHECK-NEXT:    [[CY:%.*]] = icmp slt i8 [[Y:%.*]], 1
97; CHECK-NEXT:    br i1 [[CY]], label [[NEGY:%.*]], label [[POSY:%.*]]
98; CHECK:       negy:
99; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], [[Y]]
100; CHECK-NEXT:    [[Z:%.*]] = icmp slt i8 [[AND]], [[X]]
101; CHECK-NEXT:    ret i1 [[Z]]
102; CHECK:       posy:
103; CHECK-NEXT:    [[R:%.*]] = call i1 @barrier()
104; CHECK-NEXT:    ret i1 [[R]]
105;
106  %cy = icmp sle i8 %y, 0
107  br i1 %cy, label %negy, label %posy
108negy:
109  %and = and i8 %x, %y
110  %z = icmp slt i8 %and, %x
111  ret i1 %z
112posy:
113  %r = call i1 @barrier()
114  ret i1 %r
115}
116
117define i1 @icmp_sle_x_negy(i8 %x, i8 %yy) {
118; CHECK-LABEL: @icmp_sle_x_negy(
119; CHECK-NEXT:    ret i1 true
120;
121  %y = or i8 %yy, 128
122  %and = and i8 %y, %x
123  %z = icmp sle i8 %and, %x
124  ret i1 %z
125}
126
127define <2 x i1> @icmp_sgt_x_negy(<2 x i8> %x, <2 x i8> %yy) {
128; CHECK-LABEL: @icmp_sgt_x_negy(
129; CHECK-NEXT:    ret <2 x i1> zeroinitializer
130;
131  %y = or <2 x i8> %yy, <i8 128, i8 128>
132  %and = and <2 x i8> %y, %x
133  %z = icmp sgt <2 x i8> %and, %x
134  ret <2 x i1> %z
135}
136
137define <2 x i1> @icmp_sgt_x_negy_fail_partial(<2 x i8> %x, <2 x i8> %yy) {
138; CHECK-LABEL: @icmp_sgt_x_negy_fail_partial(
139; CHECK-NEXT:    [[Y:%.*]] = or <2 x i8> [[YY:%.*]], <i8 -128, i8 4>
140; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y]], [[X:%.*]]
141; CHECK-NEXT:    [[Z:%.*]] = icmp sgt <2 x i8> [[AND]], [[X]]
142; CHECK-NEXT:    ret <2 x i1> [[Z]]
143;
144  %y = or <2 x i8> %yy, <i8 128, i8 4>
145  %and = and <2 x i8> %y, %x
146  %z = icmp sgt <2 x i8> %and, %x
147  ret <2 x i1> %z
148}
149
150define <2 x i1> @icmp_sle_x_posy(<2 x i8> %x, <2 x i8> %yy) {
151; CHECK-LABEL: @icmp_sle_x_posy(
152; CHECK-NEXT:    [[Z:%.*]] = icmp sgt <2 x i8> [[X:%.*]], splat (i8 -1)
153; CHECK-NEXT:    ret <2 x i1> [[Z]]
154;
155  %y = and <2 x i8> %yy, <i8 127, i8 127>
156  %and = and <2 x i8> %y, %x
157  %z = icmp sle <2 x i8> %and, %x
158  ret <2 x i1> %z
159}
160
161define <2 x i1> @icmp_sle_x_posy_fail_partial(<2 x i8> %x, <2 x i8> %yy) {
162; CHECK-LABEL: @icmp_sle_x_posy_fail_partial(
163; CHECK-NEXT:    [[Y:%.*]] = and <2 x i8> [[YY:%.*]], <i8 127, i8 -65>
164; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y]], [[X:%.*]]
165; CHECK-NEXT:    [[Z:%.*]] = icmp sle <2 x i8> [[AND]], [[X]]
166; CHECK-NEXT:    ret <2 x i1> [[Z]]
167;
168  %y = and <2 x i8> %yy, <i8 127, i8 191>
169  %and = and <2 x i8> %y, %x
170  %z = icmp sle <2 x i8> %and, %x
171  ret <2 x i1> %z
172}
173
174define i1 @icmp_sgt_x_posy(i8 %x, i8 %y) {
175; CHECK-LABEL: @icmp_sgt_x_posy(
176; CHECK-NEXT:    [[CY:%.*]] = icmp sgt i8 [[Y:%.*]], -1
177; CHECK-NEXT:    call void @llvm.assume(i1 [[CY]])
178; CHECK-NEXT:    [[Z:%.*]] = icmp slt i8 [[X:%.*]], 0
179; CHECK-NEXT:    ret i1 [[Z]]
180;
181  %cy = icmp sge i8 %y, 0
182  call void @llvm.assume(i1 %cy)
183  %and = and i8 %x, %y
184  %z = icmp sgt i8 %and, %x
185  ret i1 %z
186}
187
188define <2 x i1> @icmp_sgt_negx_y(<2 x i8> %xx, <2 x i8> %y) {
189; CHECK-LABEL: @icmp_sgt_negx_y(
190; CHECK-NEXT:    [[Z:%.*]] = icmp sgt <2 x i8> [[Y:%.*]], splat (i8 -1)
191; CHECK-NEXT:    ret <2 x i1> [[Z]]
192;
193  %x = or <2 x i8> %xx, <i8 128, i8 128>
194  %and = and <2 x i8> %x, %y
195  %z = icmp sgt <2 x i8> %and, %x
196  ret <2 x i1> %z
197}
198
199define i1 @icmp_sle_negx_y(i8 %x, i8 %y) {
200; CHECK-LABEL: @icmp_sle_negx_y(
201; CHECK-NEXT:    [[CX:%.*]] = icmp slt i8 [[X:%.*]], 0
202; CHECK-NEXT:    call void @llvm.assume(i1 [[CX]])
203; CHECK-NEXT:    [[Z:%.*]] = icmp slt i8 [[Y:%.*]], 0
204; CHECK-NEXT:    ret i1 [[Z]]
205;
206  %cx = icmp slt i8 %x, 0
207  call void @llvm.assume(i1 %cx)
208  %and = and i8 %x, %y
209  %z = icmp sle i8 %and, %x
210  ret i1 %z
211}
212
213define i1 @icmp_sle_negx_y_fail_maybe_zero(i8 %x, i8 %y) {
214; CHECK-LABEL: @icmp_sle_negx_y_fail_maybe_zero(
215; CHECK-NEXT:    [[CX:%.*]] = icmp slt i8 [[X:%.*]], 1
216; CHECK-NEXT:    call void @llvm.assume(i1 [[CX]])
217; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X]], [[Y:%.*]]
218; CHECK-NEXT:    [[Z:%.*]] = icmp sle i8 [[AND]], [[X]]
219; CHECK-NEXT:    ret i1 [[Z]]
220;
221  %cx = icmp sle i8 %x, 0
222  call void @llvm.assume(i1 %cx)
223  %and = and i8 %x, %y
224  %z = icmp sle i8 %and, %x
225  ret i1 %z
226}
227
228define i1 @icmp_eq_x_invertable_y_todo(i8 %x, i1 %y) {
229; CHECK-LABEL: @icmp_eq_x_invertable_y_todo(
230; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[Y:%.*]], i8 -8, i8 -25
231; CHECK-NEXT:    [[TMP2:%.*]] = and i8 [[X:%.*]], [[TMP1]]
232; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[TMP2]], 0
233; CHECK-NEXT:    ret i1 [[R]]
234;
235  %yy = select i1 %y, i8 7, i8 24
236  %and = and i8 %x, %yy
237  %r = icmp eq i8 %x, %and
238  ret i1 %r
239}
240
241define i1 @icmp_eq_x_invertable_y(i8 %x, i8 %y) {
242; CHECK-LABEL: @icmp_eq_x_invertable_y(
243; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[X:%.*]], [[Y:%.*]]
244; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[TMP1]], 0
245; CHECK-NEXT:    ret i1 [[R]]
246;
247  %yy = xor i8 %y, -1
248  %and = and i8 %x, %yy
249  %r = icmp eq i8 %x, %and
250  ret i1 %r
251}
252
253define i1 @icmp_eq_x_invertable_y_fail_multiuse(i8 %x, i8 %y) {
254; CHECK-LABEL: @icmp_eq_x_invertable_y_fail_multiuse(
255; CHECK-NEXT:    [[YY:%.*]] = xor i8 [[Y:%.*]], -1
256; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], [[YY]]
257; CHECK-NEXT:    call void @use.i8(i8 [[AND]])
258; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[X]], [[AND]]
259; CHECK-NEXT:    ret i1 [[R]]
260;
261  %yy = xor i8 %y, -1
262  %and = and i8 %x, %yy
263  call void @use.i8(i8 %and)
264  %r = icmp eq i8 %x, %and
265  ret i1 %r
266}
267
268define i1 @icmp_eq_x_invertable_y2_todo(i8 %x, i1 %y) {
269; CHECK-LABEL: @icmp_eq_x_invertable_y2_todo(
270; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[Y:%.*]], i8 -8, i8 -25
271; CHECK-NEXT:    [[TMP2:%.*]] = or i8 [[X:%.*]], [[TMP1]]
272; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[TMP2]], -1
273; CHECK-NEXT:    ret i1 [[R]]
274;
275  %yy = select i1 %y, i8 7, i8 24
276  %and = and i8 %x, %yy
277  %r = icmp eq i8 %yy, %and
278  ret i1 %r
279}
280
281define i1 @icmp_eq_x_invertable_y2(i8 %x, i8 %y) {
282; CHECK-LABEL: @icmp_eq_x_invertable_y2(
283; CHECK-NEXT:    [[TMP1:%.*]] = or i8 [[X:%.*]], [[Y:%.*]]
284; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[TMP1]], -1
285; CHECK-NEXT:    ret i1 [[R]]
286;
287  %yy = xor i8 %y, -1
288  %and = and i8 %x, %yy
289  %r = icmp eq i8 %yy, %and
290  ret i1 %r
291}
292
293define i1 @icmp_eq_x_invertable_y_fail_immconstant(i8 %x, i8 %y) {
294; CHECK-LABEL: @icmp_eq_x_invertable_y_fail_immconstant(
295; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], 7
296; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[AND]], 7
297; CHECK-NEXT:    ret i1 [[R]]
298;
299  %and = and i8 %x, 7
300  %r = icmp eq i8 %and, 7
301  ret i1 %r
302}
303