1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt %s -instcombine -S | FileCheck %s
3
4; The pattern:
5;   icmp eq/ne (and (X shift Y), Z), 0
6; is equivalent to pattern
7;   icmp eq/ne (and (Z oppositeshift Y), X), 0
8; We should canonicalize to one of them.
9; Let's go with 'lshr'.
10; Exception: unless it's a shift of constant, then don't touch it.
11
12;------------------------------------------------------------------------------;
13; Basic scalar test
14;------------------------------------------------------------------------------;
15
16define i1 @t0(i32 %x, i32 %y, i32 %z) {
17; CHECK-LABEL: @t0(
18; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
19; CHECK-NEXT:    [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]]
20; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
21; CHECK-NEXT:    ret i1 [[T2]]
22;
23  %t0 = shl i32 %x, %y
24  %t1 = and i32 %t0, %z
25  %t2 = icmp eq i32 %t1, 0
26  ret i1 %t2
27}
28
29define i1 @t1_ne(i32 %x, i32 %y, i32 %z) {
30; CHECK-LABEL: @t1_ne(
31; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
32; CHECK-NEXT:    [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]]
33; CHECK-NEXT:    [[T2:%.*]] = icmp ne i32 [[T1]], 0
34; CHECK-NEXT:    ret i1 [[T2]]
35;
36  %t0 = shl i32 %x, %y
37  %t1 = and i32 %t0, %z
38  %t2 = icmp ne i32 %t1, 0
39  ret i1 %t2
40}
41
42;------------------------------------------------------------------------------;
43; Basic vector test
44;------------------------------------------------------------------------------;
45
46define <4 x i1> @t2_vec_splat(<4 x i32> %x, <4 x i32> %y, <4 x i32> %z) {
47; CHECK-LABEL: @t2_vec_splat(
48; CHECK-NEXT:    [[T0:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]]
49; CHECK-NEXT:    [[T1:%.*]] = and <4 x i32> [[T0]], [[Z:%.*]]
50; CHECK-NEXT:    [[T2:%.*]] = icmp eq <4 x i32> [[T1]], zeroinitializer
51; CHECK-NEXT:    ret <4 x i1> [[T2]]
52;
53  %t0 = shl <4 x i32> %x, %y
54  %t1 = and <4 x i32> %t0, %z
55  %t2 = icmp eq <4 x i32> %t1, <i32 0, i32 0, i32 0, i32 0>
56  ret <4 x i1> %t2
57}
58
59define <4 x i1> @t3_vec_splat_undef(<4 x i32> %x, <4 x i32> %y, <4 x i32> %z) {
60; CHECK-LABEL: @t3_vec_splat_undef(
61; CHECK-NEXT:    [[T0:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]]
62; CHECK-NEXT:    [[T1:%.*]] = and <4 x i32> [[T0]], [[Z:%.*]]
63; CHECK-NEXT:    [[T2:%.*]] = icmp eq <4 x i32> [[T1]], <i32 0, i32 0, i32 undef, i32 0>
64; CHECK-NEXT:    ret <4 x i1> [[T2]]
65;
66  %t0 = shl <4 x i32> %x, %y
67  %t1 = and <4 x i32> %t0, %z
68  %t2 = icmp eq <4 x i32> %t1, <i32 0, i32 0, i32 undef, i32 0>
69  ret <4 x i1> %t2
70}
71
72;------------------------------------------------------------------------------;
73; Commutativity
74;------------------------------------------------------------------------------;
75
76declare i32 @gen32()
77
78define i1 @t4_commutative(i32 %x, i32 %y) {
79; CHECK-LABEL: @t4_commutative(
80; CHECK-NEXT:    [[Z:%.*]] = call i32 @gen32()
81; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
82; CHECK-NEXT:    [[T1:%.*]] = and i32 [[Z]], [[T0]]
83; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
84; CHECK-NEXT:    ret i1 [[T2]]
85;
86  %z = call i32 @gen32()
87  %t0 = shl i32 %x, %y
88  %t1 = and i32 %z, %t0 ; swapped
89  %t2 = icmp eq i32 %t1, 0
90  ret i1 %t2
91}
92
93;------------------------------------------------------------------------------;
94; Shifts in both hands of 'and'
95;------------------------------------------------------------------------------;
96
97define i1 @t5_twoshifts0(i32 %a, i32 %b, i32 %c, i32 %d) {
98; CHECK-LABEL: @t5_twoshifts0(
99; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[A:%.*]], [[B:%.*]]
100; CHECK-NEXT:    [[T1:%.*]] = shl i32 [[T0]], [[C:%.*]]
101; CHECK-NEXT:    [[T2:%.*]] = and i32 [[T1]], [[D:%.*]]
102; CHECK-NEXT:    [[T3:%.*]] = icmp eq i32 [[T2]], 0
103; CHECK-NEXT:    ret i1 [[T3]]
104;
105  %t0 = shl i32 %a, %b
106  %t1 = shl i32 %t0, %c
107  %t2 = and i32 %t1, %d
108  %t3 = icmp eq i32 %t2, 0
109  ret i1 %t3
110}
111
112define i1 @t6_twoshifts1(i32 %a, i32 %b, i32 %c, i32 %d) {
113; CHECK-LABEL: @t6_twoshifts1(
114; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[A:%.*]], [[B:%.*]]
115; CHECK-NEXT:    [[T1:%.*]] = shl i32 [[C:%.*]], [[D:%.*]]
116; CHECK-NEXT:    [[T2:%.*]] = and i32 [[T1]], [[T0]]
117; CHECK-NEXT:    [[T3:%.*]] = icmp eq i32 [[T2]], 0
118; CHECK-NEXT:    ret i1 [[T3]]
119;
120  %t0 = shl i32 %a, %b
121  %t1 = shl i32 %c, %d
122  %t2 = and i32 %t1, %t0
123  %t3 = icmp eq i32 %t2, 0
124  ret i1 %t3
125}
126
127define i1 @t7_twoshifts2(i32 %a, i32 %b, i32 %c, i32 %d) {
128; CHECK-LABEL: @t7_twoshifts2(
129; CHECK-NEXT:    [[T0:%.*]] = shl i32 1, [[B:%.*]]
130; CHECK-NEXT:    [[T1:%.*]] = shl i32 [[C:%.*]], [[D:%.*]]
131; CHECK-NEXT:    [[T2:%.*]] = and i32 [[T1]], [[T0]]
132; CHECK-NEXT:    [[T3:%.*]] = icmp eq i32 [[T2]], 0
133; CHECK-NEXT:    ret i1 [[T3]]
134;
135  %t0 = shl i32 1, %b
136  %t1 = shl i32 %c, %d
137  %t2 = and i32 %t1, %t0
138  %t3 = icmp eq i32 %t2, 0
139  ret i1 %t3
140}
141
142define i1 @t8_twoshifts3(i32 %a, i32 %b, i32 %c, i32 %d) {
143; CHECK-LABEL: @t8_twoshifts3(
144; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[A:%.*]], [[B:%.*]]
145; CHECK-NEXT:    [[T1:%.*]] = shl i32 1, [[D:%.*]]
146; CHECK-NEXT:    [[T2:%.*]] = and i32 [[T1]], [[T0]]
147; CHECK-NEXT:    [[T3:%.*]] = icmp eq i32 [[T2]], 0
148; CHECK-NEXT:    ret i1 [[T3]]
149;
150  %t0 = shl i32 %a, %b
151  %t1 = shl i32 1, %d
152  %t2 = and i32 %t1, %t0
153  %t3 = icmp eq i32 %t2, 0
154  ret i1 %t3
155}
156
157;------------------------------------------------------------------------------;
158; Extra uses
159;------------------------------------------------------------------------------;
160
161declare void @use32(i32)
162
163define i1 @t9_extrause0(i32 %x, i32 %y, i32 %z) {
164; CHECK-LABEL: @t9_extrause0(
165; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
166; CHECK-NEXT:    call void @use32(i32 [[T0]])
167; CHECK-NEXT:    [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]]
168; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
169; CHECK-NEXT:    ret i1 [[T2]]
170;
171  %t0 = shl i32 %x, %y
172  call void @use32(i32 %t0)
173  %t1 = and i32 %t0, %z
174  %t2 = icmp eq i32 %t1, 0
175  ret i1 %t2
176}
177
178define i1 @t10_extrause1(i32 %x, i32 %y, i32 %z) {
179; CHECK-LABEL: @t10_extrause1(
180; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
181; CHECK-NEXT:    [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]]
182; CHECK-NEXT:    call void @use32(i32 [[T1]])
183; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
184; CHECK-NEXT:    ret i1 [[T2]]
185;
186  %t0 = shl i32 %x, %y
187  %t1 = and i32 %t0, %z
188  call void @use32(i32 %t1)
189  %t2 = icmp eq i32 %t1, 0
190  ret i1 %t2
191}
192
193define i1 @t11_extrause2(i32 %x, i32 %y, i32 %z) {
194; CHECK-LABEL: @t11_extrause2(
195; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
196; CHECK-NEXT:    call void @use32(i32 [[T0]])
197; CHECK-NEXT:    [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]]
198; CHECK-NEXT:    call void @use32(i32 [[T1]])
199; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
200; CHECK-NEXT:    ret i1 [[T2]]
201;
202  %t0 = shl i32 %x, %y
203  call void @use32(i32 %t0)
204  %t1 = and i32 %t0, %z
205  call void @use32(i32 %t1)
206  %t2 = icmp eq i32 %t1, 0
207  ret i1 %t2
208}
209
210;------------------------------------------------------------------------------;
211; Constants
212;------------------------------------------------------------------------------;
213
214define i1 @t12_shift_of_const0(i32 %x, i32 %y, i32 %z) {
215; CHECK-LABEL: @t12_shift_of_const0(
216; CHECK-NEXT:    [[T0:%.*]] = shl i32 1, [[Y:%.*]]
217; CHECK-NEXT:    [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]]
218; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
219; CHECK-NEXT:    ret i1 [[T2]]
220;
221  %t0 = shl i32 1, %y
222  %t1 = and i32 %t0, %z
223  %t2 = icmp eq i32 %t1, 0
224  ret i1 %t2
225}
226define i1 @t13_shift_of_const1(i32 %x, i32 %y, i32 %z) {
227; CHECK-LABEL: @t13_shift_of_const1(
228; CHECK-NEXT:    [[T0:%.*]] = lshr i32 1, [[Y:%.*]]
229; CHECK-NEXT:    [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]]
230; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
231; CHECK-NEXT:    ret i1 [[T2]]
232;
233  %t0 = lshr i32 1, %y
234  %t1 = and i32 %t0, %z
235  %t2 = icmp eq i32 %t1, 0
236  ret i1 %t2
237}
238
239define i1 @t14_and_with_const0(i32 %x, i32 %y, i32 %z) {
240; CHECK-LABEL: @t14_and_with_const0(
241; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 1, [[Y:%.*]]
242; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]]
243; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[TMP2]], 0
244; CHECK-NEXT:    ret i1 [[T2]]
245;
246  %t0 = shl i32 %x, %y
247  %t1 = and i32 %t0, 1
248  %t2 = icmp eq i32 %t1, 0
249  ret i1 %t2
250}
251define i1 @t15_and_with_const1(i32 %x, i32 %y, i32 %z) {
252; CHECK-LABEL: @t15_and_with_const1(
253; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 1, [[Y:%.*]]
254; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]]
255; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[TMP2]], 0
256; CHECK-NEXT:    ret i1 [[T2]]
257;
258  %t0 = lshr i32 %x, %y
259  %t1 = and i32 %t0, 1
260  %t2 = icmp eq i32 %t1, 0
261  ret i1 %t2
262}
263
264;------------------------------------------------------------------------------;
265; Negative test
266;------------------------------------------------------------------------------;
267
268define i1 @n16(i32 %x, i32 %y, i32 %z) {
269; CHECK-LABEL: @n16(
270; CHECK-NEXT:    [[T0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
271; CHECK-NEXT:    [[T1:%.*]] = and i32 [[T0]], [[Z:%.*]]
272; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 1
273; CHECK-NEXT:    ret i1 [[T2]]
274;
275  %t0 = shl i32 %x, %y
276  %t1 = and i32 %t0, %z
277  %t2 = icmp eq i32 %t1, 1 ; not with '0'
278  ret i1 %t2
279}
280