[AArch64][NFC] NFC for const vector as Instruction operand (#116790)
[llvm-project.git] / llvm / test / Transforms / InstCombine / select-of-bittest.ll
blob4495e7f6ed067a51b0ce6a1082cd3f36e4ffc820
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 ; https://bugs.llvm.org/show_bug.cgi?id=36950
6 ; These all should be just and+icmp, there should be no select.
8 define i32 @and_lshr_and(i32 %arg) {
9 ; CHECK-LABEL: @and_lshr_and(
10 ; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARG:%.*]], 3
11 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
12 ; CHECK-NEXT:    [[T4:%.*]] = zext i1 [[TMP2]] to i32
13 ; CHECK-NEXT:    ret i32 [[T4]]
15   %t = and i32 %arg, 1
16   %t1 = icmp eq i32 %t, 0
17   %t2 = lshr i32 %arg, 1
18   %t3 = and i32 %t2, 1
19   %t4 = select i1 %t1, i32 %t3, i32 1
20   ret i32 %t4
23 define <2 x i32> @and_lshr_and_splatvec(<2 x i32> %arg) {
24 ; CHECK-LABEL: @and_lshr_and_splatvec(
25 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[ARG:%.*]], splat (i32 3)
26 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
27 ; CHECK-NEXT:    [[T4:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32>
28 ; CHECK-NEXT:    ret <2 x i32> [[T4]]
30   %t = and <2 x i32> %arg, <i32 1, i32 1>
31   %t1 = icmp eq <2 x i32> %t, zeroinitializer
32   %t2 = lshr <2 x i32> %arg, <i32 1, i32 1>
33   %t3 = and <2 x i32> %t2, <i32 1, i32 1>
34   %t4 = select <2 x i1> %t1, <2 x i32> %t3, <2 x i32> <i32 1, i32 1>
35   ret <2 x i32> %t4
38 define <2 x i32> @and_lshr_and_vec_v0(<2 x i32> %arg) {
39 ; CHECK-LABEL: @and_lshr_and_vec_v0(
40 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[ARG:%.*]], <i32 3, i32 6>
41 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
42 ; CHECK-NEXT:    [[T4:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32>
43 ; CHECK-NEXT:    ret <2 x i32> [[T4]]
45   %t = and <2 x i32> %arg, <i32 1, i32 4> ; mask is not splat
46   %t1 = icmp eq <2 x i32> %t, zeroinitializer
47   %t2 = lshr <2 x i32> %arg, <i32 1, i32 1>
48   %t3 = and <2 x i32> %t2, <i32 1, i32 1>
49   %t4 = select <2 x i1> %t1, <2 x i32> %t3, <2 x i32> <i32 1, i32 1>
50   ret <2 x i32> %t4
53 define <2 x i32> @and_lshr_and_vec_v1(<2 x i32> %arg) {
54 ; CHECK-LABEL: @and_lshr_and_vec_v1(
55 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[ARG:%.*]], <i32 3, i32 5>
56 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
57 ; CHECK-NEXT:    [[T4:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32>
58 ; CHECK-NEXT:    ret <2 x i32> [[T4]]
60   %t = and <2 x i32> %arg, <i32 1, i32 1>
61   %t1 = icmp eq <2 x i32> %t, zeroinitializer
62   %t2 = lshr <2 x i32> %arg, <i32 1, i32 2> ; shift is not splat
63   %t3 = and <2 x i32> %t2, <i32 1, i32 1>
64   %t4 = select <2 x i1> %t1, <2 x i32> %t3, <2 x i32> <i32 1, i32 1>
65   ret <2 x i32> %t4
68 define <2 x i32> @and_lshr_and_vec_v2(<2 x i32> %arg) {
69 ; CHECK-LABEL: @and_lshr_and_vec_v2(
70 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[ARG:%.*]], <i32 12, i32 3>
71 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
72 ; CHECK-NEXT:    [[T4:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32>
73 ; CHECK-NEXT:    ret <2 x i32> [[T4]]
75   %t = and <2 x i32> %arg, <i32 8, i32 1> ; mask is not splat
76   %t1 = icmp eq <2 x i32> %t, zeroinitializer
77   %t2 = lshr <2 x i32> %arg, <i32 2, i32 1> ; shift is not splat
78   %t3 = and <2 x i32> %t2, <i32 1, i32 1>
79   %t4 = select <2 x i1> %t1, <2 x i32> %t3, <2 x i32> <i32 1, i32 1>
80   ret <2 x i32> %t4
83 define <3 x i32> @and_lshr_and_vec_poison(<3 x i32> %arg) {
84 ; CHECK-LABEL: @and_lshr_and_vec_poison(
85 ; CHECK-NEXT:    [[TMP1:%.*]] = and <3 x i32> [[ARG:%.*]], <i32 3, i32 poison, i32 3>
86 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne <3 x i32> [[TMP1]], zeroinitializer
87 ; CHECK-NEXT:    [[T4:%.*]] = zext <3 x i1> [[TMP2]] to <3 x i32>
88 ; CHECK-NEXT:    ret <3 x i32> [[T4]]
90   %t = and <3 x i32> %arg, <i32 1, i32 poison, i32 1>
91   %t1 = icmp eq <3 x i32> %t, <i32 0, i32 poison, i32 0>
92   %t2 = lshr <3 x i32> %arg, <i32 1, i32 poison, i32 1>
93   %t3 = and <3 x i32> %t2, <i32 1, i32 poison, i32 1>
94   %t4 = select <3 x i1> %t1, <3 x i32> %t3, <3 x i32> <i32 1, i32 poison, i32 1>
95   ret <3 x i32> %t4
98 define i32 @and_and(i32 %arg) {
99 ; CHECK-LABEL: @and_and(
100 ; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARG:%.*]], 3
101 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
102 ; CHECK-NEXT:    [[T3:%.*]] = zext i1 [[TMP2]] to i32
103 ; CHECK-NEXT:    ret i32 [[T3]]
105   %t = and i32 %arg, 2
106   %t1 = icmp eq i32 %t, 0
107   %t2 = and i32 %arg, 1
108   %t3 = select i1 %t1, i32 %t2, i32 1
109   ret i32 %t3
112 define <2 x i32> @and_and_splatvec(<2 x i32> %arg) {
113 ; CHECK-LABEL: @and_and_splatvec(
114 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[ARG:%.*]], splat (i32 3)
115 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
116 ; CHECK-NEXT:    [[T3:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32>
117 ; CHECK-NEXT:    ret <2 x i32> [[T3]]
119   %t = and <2 x i32> %arg, <i32 2, i32 2>
120   %t1 = icmp eq <2 x i32> %t, zeroinitializer
121   %t2 = and <2 x i32> %arg, <i32 1, i32 1>
122   %t3 = select <2 x i1> %t1, <2 x i32> %t2, <2 x i32> <i32 1, i32 1>
123   ret <2 x i32> %t3
126 define <2 x i32> @and_and_vec(<2 x i32> %arg) {
127 ; CHECK-LABEL: @and_and_vec(
128 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[ARG:%.*]], <i32 7, i32 3>
129 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
130 ; CHECK-NEXT:    [[T3:%.*]] = zext <2 x i1> [[TMP2]] to <2 x i32>
131 ; CHECK-NEXT:    ret <2 x i32> [[T3]]
133   %t = and <2 x i32> %arg, <i32 6, i32 2> ; mask is not splat
134   %t1 = icmp eq <2 x i32> %t, zeroinitializer
135   %t2 = and <2 x i32> %arg, <i32 1, i32 1>
136   %t3 = select <2 x i1> %t1, <2 x i32> %t2, <2 x i32> <i32 1, i32 1>
137   ret <2 x i32> %t3
140 define <3 x i32> @and_and_vec_poison(<3 x i32> %arg) {
141 ; CHECK-LABEL: @and_and_vec_poison(
142 ; CHECK-NEXT:    [[TMP1:%.*]] = and <3 x i32> [[ARG:%.*]], <i32 3, i32 poison, i32 3>
143 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne <3 x i32> [[TMP1]], zeroinitializer
144 ; CHECK-NEXT:    [[T3:%.*]] = zext <3 x i1> [[TMP2]] to <3 x i32>
145 ; CHECK-NEXT:    ret <3 x i32> [[T3]]
147   %t = and <3 x i32> %arg, <i32 2, i32 poison, i32 2>
148   %t1 = icmp eq <3 x i32> %t, <i32 0, i32 poison, i32 0>
149   %t2 = and <3 x i32> %arg, <i32 1, i32 poison, i32 1>
150   %t3 = select <3 x i1> %t1, <3 x i32> %t2, <3 x i32> <i32 1, i32 poison, i32 1>
151   ret <3 x i32> %t3
154 ; ============================================================================ ;
155 ; Mask can be a variable, too.
156 ; ============================================================================ ;
158 define i32 @f_var0(i32 %arg, i32 %arg1) {
159 ; CHECK-LABEL: @f_var0(
160 ; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[ARG1:%.*]], 2
161 ; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG:%.*]], [[TMP1]]
162 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
163 ; CHECK-NEXT:    [[T5:%.*]] = zext i1 [[TMP3]] to i32
164 ; CHECK-NEXT:    ret i32 [[T5]]
166   %t = and i32 %arg, %arg1
167   %t2 = icmp eq i32 %t, 0
168   %t3 = lshr i32 %arg, 1
169   %t4 = and i32 %t3, 1
170   %t5 = select i1 %t2, i32 %t4, i32 1
171   ret i32 %t5
174 ; Should be exactly as the previous one
175 define i32 @f_var0_commutative_and(i32 %arg, i32 %arg1) {
176 ; CHECK-LABEL: @f_var0_commutative_and(
177 ; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[ARG1:%.*]], 2
178 ; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG:%.*]], [[TMP1]]
179 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
180 ; CHECK-NEXT:    [[T5:%.*]] = zext i1 [[TMP3]] to i32
181 ; CHECK-NEXT:    ret i32 [[T5]]
183   %t = and i32 %arg1, %arg ; in different order
184   %t2 = icmp eq i32 %t, 0
185   %t3 = lshr i32 %arg, 1
186   %t4 = and i32 %t3, 1
187   %t5 = select i1 %t2, i32 %t4, i32 1
188   ret i32 %t5
191 define <2 x i32> @f_var0_splatvec(<2 x i32> %arg, <2 x i32> %arg1) {
192 ; CHECK-LABEL: @f_var0_splatvec(
193 ; CHECK-NEXT:    [[TMP1:%.*]] = or <2 x i32> [[ARG1:%.*]], splat (i32 2)
194 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i32> [[ARG:%.*]], [[TMP1]]
195 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer
196 ; CHECK-NEXT:    [[T5:%.*]] = zext <2 x i1> [[TMP3]] to <2 x i32>
197 ; CHECK-NEXT:    ret <2 x i32> [[T5]]
199   %t = and <2 x i32> %arg, %arg1
200   %t2 = icmp eq <2 x i32> %t, zeroinitializer
201   %t3 = lshr <2 x i32> %arg, <i32 1, i32 1>
202   %t4 = and <2 x i32> %t3, <i32 1, i32 1>
203   %t5 = select <2 x i1> %t2, <2 x i32> %t4, <2 x i32> <i32 1, i32 1>
204   ret <2 x i32> %t5
207 define <2 x i32> @f_var0_vec(<2 x i32> %arg, <2 x i32> %arg1) {
208 ; CHECK-LABEL: @f_var0_vec(
209 ; CHECK-NEXT:    [[TMP1:%.*]] = or <2 x i32> [[ARG1:%.*]], <i32 2, i32 4>
210 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i32> [[ARG:%.*]], [[TMP1]]
211 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer
212 ; CHECK-NEXT:    [[T5:%.*]] = zext <2 x i1> [[TMP3]] to <2 x i32>
213 ; CHECK-NEXT:    ret <2 x i32> [[T5]]
215   %t = and <2 x i32> %arg, %arg1
216   %t2 = icmp eq <2 x i32> %t, zeroinitializer
217   %t3 = lshr <2 x i32> %arg, <i32 1, i32 2> ; shift is not splat
218   %t4 = and <2 x i32> %t3, <i32 1, i32 1>
219   %t5 = select <2 x i1> %t2, <2 x i32> %t4, <2 x i32> <i32 1, i32 1>
220   ret <2 x i32> %t5
223 define <3 x i32> @f_var0_vec_poison(<3 x i32> %arg, <3 x i32> %arg1) {
224 ; CHECK-LABEL: @f_var0_vec_poison(
225 ; CHECK-NEXT:    [[TMP1:%.*]] = or <3 x i32> [[ARG1:%.*]], <i32 2, i32 poison, i32 2>
226 ; CHECK-NEXT:    [[TMP2:%.*]] = and <3 x i32> [[ARG:%.*]], [[TMP1]]
227 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer
228 ; CHECK-NEXT:    [[T5:%.*]] = zext <3 x i1> [[TMP3]] to <3 x i32>
229 ; CHECK-NEXT:    ret <3 x i32> [[T5]]
231   %t = and <3 x i32> %arg, %arg1
232   %t2 = icmp eq <3 x i32> %t, <i32 0, i32 poison, i32 0>
233   %t3 = lshr <3 x i32> %arg, <i32 1, i32 poison, i32 1>
234   %t4 = and <3 x i32> %t3, <i32 1, i32 poison, i32 1>
235   ; The second element of %t5 is poison because it is (poison ? poison : poison).
236   %t5 = select <3 x i1> %t2, <3 x i32> %t4, <3 x i32> <i32 1, i32 poison, i32 1>
237   ret <3 x i32> %t5
240 define i32 @f_var1(i32 %arg, i32 %arg1) {
241 ; CHECK-LABEL: @f_var1(
242 ; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[ARG1:%.*]], 1
243 ; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG:%.*]], [[TMP1]]
244 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
245 ; CHECK-NEXT:    [[T4:%.*]] = zext i1 [[TMP3]] to i32
246 ; CHECK-NEXT:    ret i32 [[T4]]
248   %t = and i32 %arg, %arg1
249   %t2 = icmp eq i32 %t, 0
250   %t3 = and i32 %arg, 1
251   %t4 = select i1 %t2, i32 %t3, i32 1
252   ret i32 %t4
255 ; Should be exactly as the previous one
256 define i32 @f_var1_commutative_and(i32 %arg, i32 %arg1) {
257 ; CHECK-LABEL: @f_var1_commutative_and(
258 ; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[ARG1:%.*]], 1
259 ; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG:%.*]], [[TMP1]]
260 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
261 ; CHECK-NEXT:    [[T4:%.*]] = zext i1 [[TMP3]] to i32
262 ; CHECK-NEXT:    ret i32 [[T4]]
264   %t = and i32 %arg1, %arg ; in different order
265   %t2 = icmp eq i32 %t, 0
266   %t3 = and i32 %arg, 1
267   %t4 = select i1 %t2, i32 %t3, i32 1
268   ret i32 %t4
271 define <2 x i32> @f_var1_vec(<2 x i32> %arg, <2 x i32> %arg1) {
272 ; CHECK-LABEL: @f_var1_vec(
273 ; CHECK-NEXT:    [[TMP1:%.*]] = or <2 x i32> [[ARG1:%.*]], splat (i32 1)
274 ; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i32> [[ARG:%.*]], [[TMP1]]
275 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer
276 ; CHECK-NEXT:    [[T4:%.*]] = zext <2 x i1> [[TMP3]] to <2 x i32>
277 ; CHECK-NEXT:    ret <2 x i32> [[T4]]
279   %t = and <2 x i32> %arg, %arg1
280   %t2 = icmp eq <2 x i32> %t, zeroinitializer
281   %t3 = and <2 x i32> %arg, <i32 1, i32 1>
282   %t4 = select <2 x i1> %t2, <2 x i32> %t3, <2 x i32> <i32 1, i32 1>
283   ret <2 x i32> %t4
286 define <3 x i32> @f_var1_vec_poison(<3 x i32> %arg, <3 x i32> %arg1) {
287 ; CHECK-LABEL: @f_var1_vec_poison(
288 ; CHECK-NEXT:    [[TMP1:%.*]] = or <3 x i32> [[ARG1:%.*]], splat (i32 1)
289 ; CHECK-NEXT:    [[TMP2:%.*]] = and <3 x i32> [[ARG:%.*]], [[TMP1]]
290 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer
291 ; CHECK-NEXT:    [[T4:%.*]] = zext <3 x i1> [[TMP3]] to <3 x i32>
292 ; CHECK-NEXT:    ret <3 x i32> [[T4]]
294   %t = and <3 x i32> %arg, %arg1
295   %t2 = icmp eq <3 x i32> %t, <i32 0, i32 poison, i32 0>
296   %t3 = and <3 x i32> %arg, <i32 1, i32 poison, i32 1>
297   %t4 = select <3 x i1> %t2, <3 x i32> %t3, <3 x i32> <i32 1, i32 poison, i32 1>
298   ret <3 x i32> %t4
301 ; ============================================================================ ;
302 ; Shift can't be a variable in general.
303 ; ============================================================================ ;
305 define i32 @f_var2(i32 %arg, i32 %arg1) {
306 ; CHECK-LABEL: @f_var2(
307 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG:%.*]], 1
308 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T]], 0
309 ; CHECK-NEXT:    [[T3:%.*]] = lshr i32 [[ARG]], [[ARG1:%.*]]
310 ; CHECK-NEXT:    [[T4:%.*]] = and i32 [[T3]], 1
311 ; CHECK-NEXT:    [[T5:%.*]] = select i1 [[T2]], i32 [[T4]], i32 1
312 ; CHECK-NEXT:    ret i32 [[T5]]
314   %t = and i32 %arg, 1
315   %t2 = icmp eq i32 %t, 0
316   %t3 = lshr i32 %arg, %arg1
317   %t4 = and i32 %t3, 1
318   %t5 = select i1 %t2, i32 %t4, i32 1
319   ret i32 %t5
322 define <2 x i32> @f_var2_splatvec(<2 x i32> %arg, <2 x i32> %arg1) {
323 ; CHECK-LABEL: @f_var2_splatvec(
324 ; CHECK-NEXT:    [[T:%.*]] = and <2 x i32> [[ARG:%.*]], splat (i32 1)
325 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq <2 x i32> [[T]], zeroinitializer
326 ; CHECK-NEXT:    [[T3:%.*]] = lshr <2 x i32> [[ARG]], [[ARG1:%.*]]
327 ; CHECK-NEXT:    [[T4:%.*]] = and <2 x i32> [[T3]], splat (i32 1)
328 ; CHECK-NEXT:    [[T5:%.*]] = select <2 x i1> [[T2]], <2 x i32> [[T4]], <2 x i32> splat (i32 1)
329 ; CHECK-NEXT:    ret <2 x i32> [[T5]]
331   %t = and <2 x i32> %arg, <i32 1, i32 1>
332   %t2 = icmp eq <2 x i32> %t, zeroinitializer
333   %t3 = lshr <2 x i32> %arg, %arg1
334   %t4 = and <2 x i32> %t3, <i32 1, i32 1>
335   %t5 = select <2 x i1> %t2, <2 x i32> %t4, <2 x i32> <i32 1, i32 1>
336   ret <2 x i32> %t5
339 define <2 x i32> @f_var2_vec(<2 x i32> %arg, <2 x i32> %arg1) {
340 ; CHECK-LABEL: @f_var2_vec(
341 ; CHECK-NEXT:    [[T:%.*]] = and <2 x i32> [[ARG:%.*]], <i32 2, i32 1>
342 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq <2 x i32> [[T]], zeroinitializer
343 ; CHECK-NEXT:    [[T3:%.*]] = lshr <2 x i32> [[ARG]], [[ARG1:%.*]]
344 ; CHECK-NEXT:    [[T4:%.*]] = and <2 x i32> [[T3]], splat (i32 1)
345 ; CHECK-NEXT:    [[T5:%.*]] = select <2 x i1> [[T2]], <2 x i32> [[T4]], <2 x i32> splat (i32 1)
346 ; CHECK-NEXT:    ret <2 x i32> [[T5]]
348   %t = and <2 x i32> %arg, <i32 2, i32 1>; mask is not splat
349   %t2 = icmp eq <2 x i32> %t, zeroinitializer
350   %t3 = lshr <2 x i32> %arg, %arg1
351   %t4 = and <2 x i32> %t3, <i32 1, i32 1>
352   %t5 = select <2 x i1> %t2, <2 x i32> %t4, <2 x i32> <i32 1, i32 1>
353   ret <2 x i32> %t5
356 define <3 x i32> @f_var2_vec_poison(<3 x i32> %arg, <3 x i32> %arg1) {
357 ; CHECK-LABEL: @f_var2_vec_poison(
358 ; CHECK-NEXT:    [[T:%.*]] = and <3 x i32> [[ARG:%.*]], <i32 1, i32 poison, i32 1>
359 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq <3 x i32> [[T]], <i32 0, i32 poison, i32 0>
360 ; CHECK-NEXT:    [[T3:%.*]] = lshr <3 x i32> [[ARG]], [[ARG1:%.*]]
361 ; CHECK-NEXT:    [[T4:%.*]] = and <3 x i32> [[T3]], <i32 1, i32 poison, i32 1>
362 ; CHECK-NEXT:    [[T5:%.*]] = select <3 x i1> [[T2]], <3 x i32> [[T4]], <3 x i32> <i32 1, i32 poison, i32 1>
363 ; CHECK-NEXT:    ret <3 x i32> [[T5]]
365   %t = and <3 x i32> %arg, <i32 1, i32 poison, i32 1>
366   %t2 = icmp eq <3 x i32> %t, <i32 0, i32 poison, i32 0>
367   %t3 = lshr <3 x i32> %arg, %arg1
368   %t4 = and <3 x i32> %t3, <i32 1, i32 poison, i32 1>
369   %t5 = select <3 x i1> %t2, <3 x i32> %t4, <3 x i32> <i32 1, i32 poison, i32 1>
370   ret <3 x i32> %t5
373 ; ============================================================================ ;
374 ; The worst case: both Mask and Shift are variables
375 ; ============================================================================ ;
377 define i32 @f_var3(i32 %arg, i32 %arg1, i32 %arg2) {
378 ; CHECK-LABEL: @f_var3(
379 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG:%.*]], [[ARG1:%.*]]
380 ; CHECK-NEXT:    [[T3:%.*]] = icmp eq i32 [[T]], 0
381 ; CHECK-NEXT:    [[T4:%.*]] = lshr i32 [[ARG]], [[ARG2:%.*]]
382 ; CHECK-NEXT:    [[T5:%.*]] = and i32 [[T4]], 1
383 ; CHECK-NEXT:    [[T6:%.*]] = select i1 [[T3]], i32 [[T5]], i32 1
384 ; CHECK-NEXT:    ret i32 [[T6]]
386   %t = and i32 %arg, %arg1
387   %t3 = icmp eq i32 %t, 0
388   %t4 = lshr i32 %arg, %arg2
389   %t5 = and i32 %t4, 1
390   %t6 = select i1 %t3, i32 %t5, i32 1
391   ret i32 %t6
394 ; Should be exactly as the previous one
395 define i32 @f_var3_commutative_and(i32 %arg, i32 %arg1, i32 %arg2) {
396 ; CHECK-LABEL: @f_var3_commutative_and(
397 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG1:%.*]], [[ARG:%.*]]
398 ; CHECK-NEXT:    [[T3:%.*]] = icmp eq i32 [[T]], 0
399 ; CHECK-NEXT:    [[T4:%.*]] = lshr i32 [[ARG]], [[ARG2:%.*]]
400 ; CHECK-NEXT:    [[T5:%.*]] = and i32 [[T4]], 1
401 ; CHECK-NEXT:    [[T6:%.*]] = select i1 [[T3]], i32 [[T5]], i32 1
402 ; CHECK-NEXT:    ret i32 [[T6]]
404   %t = and i32 %arg1, %arg ; in different order
405   %t3 = icmp eq i32 %t, 0
406   %t4 = lshr i32 %arg, %arg2
407   %t5 = and i32 %t4, 1
408   %t6 = select i1 %t3, i32 %t5, i32 1
409   ret i32 %t6
412 define <2 x i32> @f_var3_splatvec(<2 x i32> %arg, <2 x i32> %arg1, <2 x i32> %arg2) {
413 ; CHECK-LABEL: @f_var3_splatvec(
414 ; CHECK-NEXT:    [[T:%.*]] = and <2 x i32> [[ARG:%.*]], [[ARG1:%.*]]
415 ; CHECK-NEXT:    [[T3:%.*]] = icmp eq <2 x i32> [[T]], zeroinitializer
416 ; CHECK-NEXT:    [[T4:%.*]] = lshr <2 x i32> [[ARG]], [[ARG2:%.*]]
417 ; CHECK-NEXT:    [[T5:%.*]] = and <2 x i32> [[T4]], splat (i32 1)
418 ; CHECK-NEXT:    [[T6:%.*]] = select <2 x i1> [[T3]], <2 x i32> [[T5]], <2 x i32> splat (i32 1)
419 ; CHECK-NEXT:    ret <2 x i32> [[T6]]
421   %t = and <2 x i32> %arg, %arg1
422   %t3 = icmp eq <2 x i32> %t, zeroinitializer
423   %t4 = lshr <2 x i32> %arg, %arg2
424   %t5 = and <2 x i32> %t4, <i32 1, i32 1>
425   %t6 = select <2 x i1> %t3, <2 x i32> %t5, <2 x i32> <i32 1, i32 1>
426   ret <2 x i32> %t6
429 define <3 x i32> @f_var3_vec_poison(<3 x i32> %arg, <3 x i32> %arg1, <3 x i32> %arg2) {
430 ; CHECK-LABEL: @f_var3_vec_poison(
431 ; CHECK-NEXT:    [[T:%.*]] = and <3 x i32> [[ARG:%.*]], [[ARG1:%.*]]
432 ; CHECK-NEXT:    [[T3:%.*]] = icmp eq <3 x i32> [[T]], <i32 0, i32 poison, i32 0>
433 ; CHECK-NEXT:    [[T4:%.*]] = lshr <3 x i32> [[ARG]], [[ARG2:%.*]]
434 ; CHECK-NEXT:    [[T5:%.*]] = and <3 x i32> [[T4]], <i32 1, i32 poison, i32 1>
435 ; CHECK-NEXT:    [[T6:%.*]] = select <3 x i1> [[T3]], <3 x i32> [[T5]], <3 x i32> <i32 1, i32 poison, i32 1>
436 ; CHECK-NEXT:    ret <3 x i32> [[T6]]
438   %t = and <3 x i32> %arg, %arg1
439   %t3 = icmp eq <3 x i32> %t, <i32 0, i32 poison, i32 0>
440   %t4 = lshr <3 x i32> %arg, %arg2
441   %t5 = and <3 x i32> %t4, <i32 1, i32 poison, i32 1>
442   %t6 = select <3 x i1> %t3, <3 x i32> %t5, <3 x i32> <i32 1, i32 poison, i32 1>
443   ret <3 x i32> %t6
446 ; ============================================================================ ;
447 ; Negative tests. Should not be folded.
448 ; ============================================================================ ;
450 ; One use only.
452 declare void @use32(i32)
454 declare void @use1(i1)
456 define i32 @n_var0_oneuse(i32 %arg, i32 %arg1, i32 %arg2) {
457 ; CHECK-LABEL: @n_var0_oneuse(
458 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG:%.*]], [[ARG1:%.*]]
459 ; CHECK-NEXT:    [[T3:%.*]] = icmp eq i32 [[T]], 0
460 ; CHECK-NEXT:    [[T4:%.*]] = lshr i32 [[ARG]], [[ARG2:%.*]]
461 ; CHECK-NEXT:    [[T5:%.*]] = and i32 [[T4]], 1
462 ; CHECK-NEXT:    [[T6:%.*]] = select i1 [[T3]], i32 [[T5]], i32 1
463 ; CHECK-NEXT:    call void @use32(i32 [[T]])
464 ; CHECK-NEXT:    call void @use1(i1 [[T3]])
465 ; CHECK-NEXT:    call void @use32(i32 [[T4]])
466 ; CHECK-NEXT:    call void @use32(i32 [[T5]])
467 ; CHECK-NEXT:    ret i32 [[T6]]
469   %t = and i32 %arg, %arg1
470   %t3 = icmp eq i32 %t, 0
471   %t4 = lshr i32 %arg, %arg2
472   %t5 = and i32 %t4, 1
473   %t6 = select i1 %t3, i32 %t5, i32 1
474   call void @use32(i32 %t)
475   call void @use1(i1 %t3)
476   call void @use32(i32 %t4)
477   call void @use32(i32 %t5)
478   ret i32 %t6
481 define i32 @n_var1_oneuse(i32 %arg, i32 %arg1) {
482 ; CHECK-LABEL: @n_var1_oneuse(
483 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG:%.*]], [[ARG1:%.*]]
484 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T]], 0
485 ; CHECK-NEXT:    [[T3:%.*]] = and i32 [[ARG]], 1
486 ; CHECK-NEXT:    [[T4:%.*]] = select i1 [[T2]], i32 [[T3]], i32 1
487 ; CHECK-NEXT:    call void @use32(i32 [[T]])
488 ; CHECK-NEXT:    call void @use1(i1 [[T2]])
489 ; CHECK-NEXT:    call void @use32(i32 [[T3]])
490 ; CHECK-NEXT:    ret i32 [[T4]]
492   %t = and i32 %arg, %arg1
493   %t2 = icmp eq i32 %t, 0
494   %t3 = and i32 %arg, 1
495   %t4 = select i1 %t2, i32 %t3, i32 1
496   call void @use32(i32 %t)
497   call void @use1(i1 %t2)
498   call void @use32(i32 %t3)
499   ret i32 %t4
502 ; Different variables are used
504 define i32 @n0(i32 %arg, i32 %arg1) {
505 ; CHECK-LABEL: @n0(
506 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG:%.*]], 1
507 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T]], 0
508 ; CHECK-NEXT:    [[T3:%.*]] = lshr i32 [[ARG1:%.*]], 1
509 ; CHECK-NEXT:    [[T4:%.*]] = and i32 [[T3]], 1
510 ; CHECK-NEXT:    [[T5:%.*]] = select i1 [[T2]], i32 [[T4]], i32 1
511 ; CHECK-NEXT:    ret i32 [[T5]]
513   %t = and i32 %arg, 1
514   %t2 = icmp eq i32 %t, 0
515   %t3 = lshr i32 %arg1, 1 ; works on %arg1 instead of %arg
516   %t4 = and i32 %t3, 1
517   %t5 = select i1 %t2, i32 %t4, i32 1
518   ret i32 %t5
521 define i32 @n1(i32 %arg, i32 %arg1) {
522 ; CHECK-LABEL: @n1(
523 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG:%.*]], 2
524 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T]], 0
525 ; CHECK-NEXT:    [[T3:%.*]] = and i32 [[ARG1:%.*]], 1
526 ; CHECK-NEXT:    [[T4:%.*]] = select i1 [[T2]], i32 [[T3]], i32 1
527 ; CHECK-NEXT:    ret i32 [[T4]]
529   %t = and i32 %arg, 2
530   %t2 = icmp eq i32 %t, 0
531   %t3 = and i32 %arg1, 1 ; works on %arg1 instead of %arg
532   %t4 = select i1 %t2, i32 %t3, i32 1
533   ret i32 %t4
536 ; False-value is not 1
538 define i32 @n2(i32 %arg) {
539 ; CHECK-LABEL: @n2(
540 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG:%.*]], 1
541 ; CHECK-NEXT:    [[T1:%.*]] = icmp eq i32 [[T]], 0
542 ; CHECK-NEXT:    [[T2:%.*]] = lshr i32 [[ARG]], 2
543 ; CHECK-NEXT:    [[T3:%.*]] = and i32 [[T2]], 1
544 ; CHECK-NEXT:    [[T4:%.*]] = select i1 [[T1]], i32 [[T3]], i32 0
545 ; CHECK-NEXT:    ret i32 [[T4]]
547   %t = and i32 %arg, 1
548   %t1 = icmp eq i32 %t, 0
549   %t2 = lshr i32 %arg, 2
550   %t3 = and i32 %t2, 1
551   %t4 = select i1 %t1, i32 %t3, i32 0 ; 0 instead of 1
552   ret i32 %t4
555 define i32 @n3(i32 %arg) {
556 ; CHECK-LABEL: @n3(
557 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG:%.*]], 2
558 ; CHECK-NEXT:    [[T1:%.*]] = icmp eq i32 [[T]], 0
559 ; CHECK-NEXT:    [[T2:%.*]] = and i32 [[ARG]], 1
560 ; CHECK-NEXT:    [[T3:%.*]] = select i1 [[T1]], i32 [[T2]], i32 0
561 ; CHECK-NEXT:    ret i32 [[T3]]
563   %t = and i32 %arg, 2
564   %t1 = icmp eq i32 %t, 0
565   %t2 = and i32 %arg, 1
566   %t3 = select i1 %t1, i32 %t2, i32 0 ; 0 instead of 1
567   ret i32 %t3
570 ; Mask of second and is not one
572 define i32 @n4(i32 %arg) {
573 ; CHECK-LABEL: @n4(
574 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG:%.*]], 1
575 ; CHECK-NEXT:    [[T1:%.*]] = icmp eq i32 [[T]], 0
576 ; CHECK-NEXT:    [[T2:%.*]] = lshr i32 [[ARG]], 2
577 ; CHECK-NEXT:    [[T3:%.*]] = and i32 [[T2]], 2
578 ; CHECK-NEXT:    [[T4:%.*]] = select i1 [[T1]], i32 [[T3]], i32 1
579 ; CHECK-NEXT:    ret i32 [[T4]]
581   %t = and i32 %arg, 1
582   %t1 = icmp eq i32 %t, 0
583   %t2 = lshr i32 %arg, 2
584   %t3 = and i32 %t2, 2 ; 2 instead of 1
585   %t4 = select i1 %t1, i32 %t3, i32 1
586   ret i32 %t4
589 define i32 @n5(i32 %arg) {
590 ; CHECK-LABEL: @n5(
591 ; CHECK-NEXT:    [[T:%.*]] = lshr i32 [[ARG:%.*]], 1
592 ; CHECK-NEXT:    [[T_LOBIT:%.*]] = and i32 [[T]], 1
593 ; CHECK-NEXT:    ret i32 [[T_LOBIT]]
595   %t = and i32 %arg, 2
596   %t1 = icmp eq i32 %t, 0
597   %t2 = and i32 %arg, 2 ; 2 instead of 1
598   %t3 = select i1 %t1, i32 %t2, i32 1
599   ret i32 %t3
602 ; Wrong icmp pred
604 define i32 @n6(i32 %arg) {
605 ; CHECK-LABEL: @n6(
606 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG:%.*]], 1
607 ; CHECK-NEXT:    [[T1_NOT:%.*]] = icmp eq i32 [[T]], 0
608 ; CHECK-NEXT:    [[T2:%.*]] = lshr i32 [[ARG]], 2
609 ; CHECK-NEXT:    [[T3:%.*]] = and i32 [[T2]], 1
610 ; CHECK-NEXT:    [[T4:%.*]] = select i1 [[T1_NOT]], i32 1, i32 [[T3]]
611 ; CHECK-NEXT:    ret i32 [[T4]]
613   %t = and i32 %arg, 1
614   %t1 = icmp ne i32 %t, 0 ; ne, not eq
615   %t2 = lshr i32 %arg, 2
616   %t3 = and i32 %t2, 1
617   %t4 = select i1 %t1, i32 %t3, i32 1
618   ret i32 %t4
621 define i32 @n7(i32 %arg) {
622 ; CHECK-LABEL: @n7(
623 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG:%.*]], 2
624 ; CHECK-NEXT:    [[T1_NOT:%.*]] = icmp eq i32 [[T]], 0
625 ; CHECK-NEXT:    [[T2:%.*]] = and i32 [[ARG]], 1
626 ; CHECK-NEXT:    [[T3:%.*]] = select i1 [[T1_NOT]], i32 1, i32 [[T2]]
627 ; CHECK-NEXT:    ret i32 [[T3]]
629   %t = and i32 %arg, 2
630   %t1 = icmp ne i32 %t, 0 ; ne, not eq
631   %t2 = and i32 %arg, 1
632   %t3 = select i1 %t1, i32 %t2, i32 1
633   ret i32 %t3
636 ; icmp second operand is not zero
638 define i32 @n8(i32 %arg) {
639 ; CHECK-LABEL: @n8(
640 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG:%.*]], 1
641 ; CHECK-NEXT:    [[T1_NOT:%.*]] = icmp eq i32 [[T]], 0
642 ; CHECK-NEXT:    [[T2:%.*]] = lshr i32 [[ARG]], 2
643 ; CHECK-NEXT:    [[T3:%.*]] = and i32 [[T2]], 1
644 ; CHECK-NEXT:    [[T4:%.*]] = select i1 [[T1_NOT]], i32 1, i32 [[T3]]
645 ; CHECK-NEXT:    ret i32 [[T4]]
647   %t = and i32 %arg, 1
648   %t1 = icmp eq i32 %t, 1
649   %t2 = lshr i32 %arg, 2
650   %t3 = and i32 %t2, 1
651   %t4 = select i1 %t1, i32 %t3, i32 1
652   ret i32 %t4