1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt %s -instcombine -S | FileCheck %s
5 ; icmp eq/ne (and ((x shift Q), (y oppositeshift K))), 0
6 ; we should move shifts to the same hand of 'and', i.e. e.g. rewrite as
7 ; icmp eq/ne (and (((x shift Q) shift K), y)), 0
8 ; We are only interested in opposite logical shifts here.
10 ; Basic scalar test with constants
12 define i1 @t0_const_lshr_shl_ne(i32 %x, i32 %y) {
13 ; CHECK-LABEL: @t0_const_lshr_shl_ne(
14 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2
15 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]]
16 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
17 ; CHECK-NEXT: ret i1 [[TMP3]]
21 %t2 = and i32 %t1, %t0
22 %t3 = icmp ne i32 %t2, 0
25 define i1 @t1_const_shl_lshr_ne(i32 %x, i32 %y) {
26 ; CHECK-LABEL: @t1_const_shl_lshr_ne(
27 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], 2
28 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]]
29 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
30 ; CHECK-NEXT: ret i1 [[TMP3]]
34 %t2 = and i32 %t1, %t0
35 %t3 = icmp ne i32 %t2, 0
39 ; We are ok with 'eq' predicate too.
40 define i1 @t2_const_lshr_shl_eq(i32 %x, i32 %y) {
41 ; CHECK-LABEL: @t2_const_lshr_shl_eq(
42 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2
43 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]]
44 ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0
45 ; CHECK-NEXT: ret i1 [[TMP3]]
49 %t2 = and i32 %t1, %t0
50 %t3 = icmp eq i32 %t2, 0
54 ; Basic scalar test with constants after folding
56 define i1 @t3_const_after_fold_lshr_shl_ne(i32 %x, i32 %y, i32 %len) {
57 ; CHECK-LABEL: @t3_const_after_fold_lshr_shl_ne(
58 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 31
59 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]]
60 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
61 ; CHECK-NEXT: ret i1 [[TMP3]]
63 %t0 = sub i32 32, %len
64 %t1 = lshr i32 %x, %t0
65 %t2 = add i32 %len, -1
67 %t4 = and i32 %t1, %t3
68 %t5 = icmp ne i32 %t4, 0
71 define i1 @t4_const_after_fold_lshr_shl_ne(i32 %x, i32 %y, i32 %len) {
72 ; CHECK-LABEL: @t4_const_after_fold_lshr_shl_ne(
73 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], 31
74 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]]
75 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
76 ; CHECK-NEXT: ret i1 [[TMP3]]
78 %t0 = sub i32 32, %len
80 %t2 = add i32 %len, -1
81 %t3 = lshr i32 %y, %t2
82 %t4 = and i32 %t1, %t3
83 %t5 = icmp ne i32 %t4, 0
87 ; Completely variable shift amounts
89 define i1 @t5_const_lshr_shl_ne(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {
90 ; CHECK-LABEL: @t5_const_lshr_shl_ne(
91 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]
92 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]
93 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]
94 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0
95 ; CHECK-NEXT: ret i1 [[T3]]
97 %t0 = lshr i32 %x, %shamt0
98 %t1 = shl i32 %y, %shamt1
99 %t2 = and i32 %t1, %t0
100 %t3 = icmp ne i32 %t2, 0
103 define i1 @t6_const_shl_lshr_ne(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {
104 ; CHECK-LABEL: @t6_const_shl_lshr_ne(
105 ; CHECK-NEXT: [[T0:%.*]] = shl i32 [[X:%.*]], [[SHAMT0:%.*]]
106 ; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[Y:%.*]], [[SHAMT1:%.*]]
107 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]
108 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0
109 ; CHECK-NEXT: ret i1 [[T3]]
111 %t0 = shl i32 %x, %shamt0
112 %t1 = lshr i32 %y, %shamt1
113 %t2 = and i32 %t1, %t0
114 %t3 = icmp ne i32 %t2, 0
118 ; Very basic vector tests
120 define <2 x i1> @t7_const_lshr_shl_ne_vec_splat(<2 x i32> %x, <2 x i32> %y) {
121 ; CHECK-LABEL: @t7_const_lshr_shl_ne_vec_splat(
122 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 2, i32 2>
123 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[Y:%.*]]
124 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer
125 ; CHECK-NEXT: ret <2 x i1> [[TMP3]]
127 %t0 = lshr <2 x i32> %x, <i32 1, i32 1>
128 %t1 = shl <2 x i32> %y, <i32 1, i32 1>
129 %t2 = and <2 x i32> %t1, %t0
130 %t3 = icmp ne <2 x i32> %t2, <i32 0, i32 0>
133 define <2 x i1> @t8_const_lshr_shl_ne_vec_nonsplat(<2 x i32> %x, <2 x i32> %y) {
134 ; CHECK-LABEL: @t8_const_lshr_shl_ne_vec_nonsplat(
135 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 4, i32 6>
136 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[Y:%.*]]
137 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer
138 ; CHECK-NEXT: ret <2 x i1> [[TMP3]]
140 %t0 = lshr <2 x i32> %x, <i32 1, i32 2>
141 %t1 = shl <2 x i32> %y, <i32 3, i32 4>
142 %t2 = and <2 x i32> %t1, %t0
143 %t3 = icmp ne <2 x i32> %t2, <i32 0, i32 0>
146 define <3 x i1> @t9_const_lshr_shl_ne_vec_undef0(<3 x i32> %x, <3 x i32> %y) {
147 ; CHECK-LABEL: @t9_const_lshr_shl_ne_vec_undef0(
148 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2>
149 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]]
150 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer
151 ; CHECK-NEXT: ret <3 x i1> [[TMP3]]
153 %t0 = lshr <3 x i32> %x, <i32 1, i32 undef, i32 1>
154 %t1 = shl <3 x i32> %y, <i32 1, i32 1, i32 1>
155 %t2 = and <3 x i32> %t1, %t0
156 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 0, i32 0>
159 define <3 x i1> @t10_const_lshr_shl_ne_vec_undef1(<3 x i32> %x, <3 x i32> %y) {
160 ; CHECK-LABEL: @t10_const_lshr_shl_ne_vec_undef1(
161 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2>
162 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]]
163 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer
164 ; CHECK-NEXT: ret <3 x i1> [[TMP3]]
166 %t0 = lshr <3 x i32> %x, <i32 1, i32 1, i32 1>
167 %t1 = shl <3 x i32> %y, <i32 1, i32 undef, i32 1>
168 %t2 = and <3 x i32> %t1, %t0
169 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 0, i32 0>
172 define <3 x i1> @t11_const_lshr_shl_ne_vec_undef2(<3 x i32> %x, <3 x i32> %y) {
173 ; CHECK-LABEL: @t11_const_lshr_shl_ne_vec_undef2(
174 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 2, i32 2>
175 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]]
176 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer
177 ; CHECK-NEXT: ret <3 x i1> [[TMP3]]
179 %t0 = lshr <3 x i32> %x, <i32 1, i32 1, i32 1>
180 %t1 = shl <3 x i32> %y, <i32 1, i32 1, i32 1>
181 %t2 = and <3 x i32> %t1, %t0
182 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 undef, i32 0>
185 define <3 x i1> @t12_const_lshr_shl_ne_vec_undef3(<3 x i32> %x, <3 x i32> %y) {
186 ; CHECK-LABEL: @t12_const_lshr_shl_ne_vec_undef3(
187 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2>
188 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]]
189 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer
190 ; CHECK-NEXT: ret <3 x i1> [[TMP3]]
192 %t0 = lshr <3 x i32> %x, <i32 1, i32 undef, i32 1>
193 %t1 = shl <3 x i32> %y, <i32 1, i32 undef, i32 1>
194 %t2 = and <3 x i32> %t1, %t0
195 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 0, i32 0>
198 define <3 x i1> @t13_const_lshr_shl_ne_vec_undef4(<3 x i32> %x, <3 x i32> %y) {
199 ; CHECK-LABEL: @t13_const_lshr_shl_ne_vec_undef4(
200 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2>
201 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]]
202 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer
203 ; CHECK-NEXT: ret <3 x i1> [[TMP3]]
205 %t0 = lshr <3 x i32> %x, <i32 1, i32 1, i32 1>
206 %t1 = shl <3 x i32> %y, <i32 1, i32 undef, i32 1>
207 %t2 = and <3 x i32> %t1, %t0
208 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 undef, i32 0>
211 define <3 x i1> @t14_const_lshr_shl_ne_vec_undef5(<3 x i32> %x, <3 x i32> %y) {
212 ; CHECK-LABEL: @t14_const_lshr_shl_ne_vec_undef5(
213 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2>
214 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]]
215 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer
216 ; CHECK-NEXT: ret <3 x i1> [[TMP3]]
218 %t0 = lshr <3 x i32> %x, <i32 1, i32 undef, i32 1>
219 %t1 = shl <3 x i32> %y, <i32 1, i32 1, i32 1>
220 %t2 = and <3 x i32> %t1, %t0
221 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 undef, i32 0>
224 define <3 x i1> @t15_const_lshr_shl_ne_vec_undef6(<3 x i32> %x, <3 x i32> %y) {
225 ; CHECK-LABEL: @t15_const_lshr_shl_ne_vec_undef6(
226 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 undef, i32 2>
227 ; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]]
228 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer
229 ; CHECK-NEXT: ret <3 x i1> [[TMP3]]
231 %t0 = lshr <3 x i32> %x, <i32 1, i32 undef, i32 1>
232 %t1 = shl <3 x i32> %y, <i32 1, i32 undef, i32 1>
233 %t2 = and <3 x i32> %t1, %t0
234 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 undef, i32 0>
238 ; Commutativity tests
242 define i1 @t16_commutativity0(i32 %x) {
243 ; CHECK-LABEL: @t16_commutativity0(
244 ; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32()
245 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2
246 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]]
247 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
248 ; CHECK-NEXT: ret i1 [[TMP3]]
250 %y = call i32 @gen32()
253 %t2 = and i32 %t1, %t0
254 %t3 = icmp ne i32 %t2, 0
258 define i1 @t17_commutativity1(i32 %y) {
259 ; CHECK-LABEL: @t17_commutativity1(
260 ; CHECK-NEXT: [[X:%.*]] = call i32 @gen32()
261 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2
262 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]]
263 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
264 ; CHECK-NEXT: ret i1 [[TMP3]]
266 %x = call i32 @gen32()
269 %t2 = and i32 %t0, %t1 ; "swapped"
270 %t3 = icmp ne i32 %t2, 0
276 declare void @use32(i32)
278 define i1 @t18_const_oneuse0(i32 %x, i32 %y) {
279 ; CHECK-LABEL: @t18_const_oneuse0(
280 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1
281 ; CHECK-NEXT: call void @use32(i32 [[T0]])
282 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2
283 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]]
284 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
285 ; CHECK-NEXT: ret i1 [[TMP3]]
288 call void @use32(i32 %t0)
290 %t2 = and i32 %t1, %t0
291 %t3 = icmp ne i32 %t2, 0
294 define i1 @t19_const_oneuse1(i32 %x, i32 %y) {
295 ; CHECK-LABEL: @t19_const_oneuse1(
296 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1
297 ; CHECK-NEXT: call void @use32(i32 [[T1]])
298 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2
299 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]]
300 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
301 ; CHECK-NEXT: ret i1 [[TMP3]]
305 call void @use32(i32 %t1)
306 %t2 = and i32 %t1, %t0
307 %t3 = icmp ne i32 %t2, 0
310 define i1 @t20_const_oneuse2(i32 %x, i32 %y) {
311 ; CHECK-LABEL: @t20_const_oneuse2(
312 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1
313 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1
314 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]
315 ; CHECK-NEXT: call void @use32(i32 [[T2]])
316 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0
317 ; CHECK-NEXT: ret i1 [[T3]]
321 %t2 = and i32 %t1, %t0
322 call void @use32(i32 %t2)
323 %t3 = icmp ne i32 %t2, 0
326 define i1 @t21_const_oneuse3(i32 %x, i32 %y) {
327 ; CHECK-LABEL: @t21_const_oneuse3(
328 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1
329 ; CHECK-NEXT: call void @use32(i32 [[T0]])
330 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1
331 ; CHECK-NEXT: call void @use32(i32 [[T1]])
332 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]
333 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0
334 ; CHECK-NEXT: ret i1 [[T3]]
337 call void @use32(i32 %t0)
339 call void @use32(i32 %t1)
340 %t2 = and i32 %t1, %t0
341 %t3 = icmp ne i32 %t2, 0
344 define i1 @t22_const_oneuse4(i32 %x, i32 %y) {
345 ; CHECK-LABEL: @t22_const_oneuse4(
346 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1
347 ; CHECK-NEXT: call void @use32(i32 [[T0]])
348 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1
349 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]
350 ; CHECK-NEXT: call void @use32(i32 [[T2]])
351 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0
352 ; CHECK-NEXT: ret i1 [[T3]]
355 call void @use32(i32 %t0)
357 %t2 = and i32 %t1, %t0
358 call void @use32(i32 %t2)
359 %t3 = icmp ne i32 %t2, 0
362 define i1 @t23_const_oneuse5(i32 %x, i32 %y) {
363 ; CHECK-LABEL: @t23_const_oneuse5(
364 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1
365 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1
366 ; CHECK-NEXT: call void @use32(i32 [[T1]])
367 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]
368 ; CHECK-NEXT: call void @use32(i32 [[T2]])
369 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0
370 ; CHECK-NEXT: ret i1 [[T3]]
374 call void @use32(i32 %t1)
375 %t2 = and i32 %t1, %t0
376 call void @use32(i32 %t2)
377 %t3 = icmp ne i32 %t2, 0
380 define i1 @t24_const_oneuse6(i32 %x, i32 %y) {
381 ; CHECK-LABEL: @t24_const_oneuse6(
382 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1
383 ; CHECK-NEXT: call void @use32(i32 [[T0]])
384 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1
385 ; CHECK-NEXT: call void @use32(i32 [[T1]])
386 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]
387 ; CHECK-NEXT: call void @use32(i32 [[T2]])
388 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0
389 ; CHECK-NEXT: ret i1 [[T3]]
392 call void @use32(i32 %t0)
394 call void @use32(i32 %t1)
395 %t2 = and i32 %t1, %t0
396 call void @use32(i32 %t2)
397 %t3 = icmp ne i32 %t2, 0
401 define i1 @t25_var_oneuse0(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {
402 ; CHECK-LABEL: @t25_var_oneuse0(
403 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]
404 ; CHECK-NEXT: call void @use32(i32 [[T0]])
405 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]
406 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]
407 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0
408 ; CHECK-NEXT: ret i1 [[T3]]
410 %t0 = lshr i32 %x, %shamt0
411 call void @use32(i32 %t0)
412 %t1 = shl i32 %y, %shamt1
413 %t2 = and i32 %t1, %t0
414 %t3 = icmp ne i32 %t2, 0
417 define i1 @t26_var_oneuse1(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {
418 ; CHECK-LABEL: @t26_var_oneuse1(
419 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]
420 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]
421 ; CHECK-NEXT: call void @use32(i32 [[T1]])
422 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]
423 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0
424 ; CHECK-NEXT: ret i1 [[T3]]
426 %t0 = lshr i32 %x, %shamt0
427 %t1 = shl i32 %y, %shamt1
428 call void @use32(i32 %t1)
429 %t2 = and i32 %t1, %t0
430 %t3 = icmp ne i32 %t2, 0
433 define i1 @t27_var_oneuse2(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {
434 ; CHECK-LABEL: @t27_var_oneuse2(
435 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]
436 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]
437 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]
438 ; CHECK-NEXT: call void @use32(i32 [[T2]])
439 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0
440 ; CHECK-NEXT: ret i1 [[T3]]
442 %t0 = lshr i32 %x, %shamt0
443 %t1 = shl i32 %y, %shamt1
444 %t2 = and i32 %t1, %t0
445 call void @use32(i32 %t2)
446 %t3 = icmp ne i32 %t2, 0
449 define i1 @t28_var_oneuse3(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {
450 ; CHECK-LABEL: @t28_var_oneuse3(
451 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]
452 ; CHECK-NEXT: call void @use32(i32 [[T0]])
453 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]
454 ; CHECK-NEXT: call void @use32(i32 [[T1]])
455 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]
456 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0
457 ; CHECK-NEXT: ret i1 [[T3]]
459 %t0 = lshr i32 %x, %shamt0
460 call void @use32(i32 %t0)
461 %t1 = shl i32 %y, %shamt1
462 call void @use32(i32 %t1)
463 %t2 = and i32 %t1, %t0
464 %t3 = icmp ne i32 %t2, 0
467 define i1 @t29_var_oneuse4(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {
468 ; CHECK-LABEL: @t29_var_oneuse4(
469 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]
470 ; CHECK-NEXT: call void @use32(i32 [[T0]])
471 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]
472 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]
473 ; CHECK-NEXT: call void @use32(i32 [[T2]])
474 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0
475 ; CHECK-NEXT: ret i1 [[T3]]
477 %t0 = lshr i32 %x, %shamt0
478 call void @use32(i32 %t0)
479 %t1 = shl i32 %y, %shamt1
480 %t2 = and i32 %t1, %t0
481 call void @use32(i32 %t2)
482 %t3 = icmp ne i32 %t2, 0
485 define i1 @t30_var_oneuse5(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {
486 ; CHECK-LABEL: @t30_var_oneuse5(
487 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]
488 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]
489 ; CHECK-NEXT: call void @use32(i32 [[T1]])
490 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]
491 ; CHECK-NEXT: call void @use32(i32 [[T2]])
492 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0
493 ; CHECK-NEXT: ret i1 [[T3]]
495 %t0 = lshr i32 %x, %shamt0
496 %t1 = shl i32 %y, %shamt1
497 call void @use32(i32 %t1)
498 %t2 = and i32 %t1, %t0
499 call void @use32(i32 %t2)
500 %t3 = icmp ne i32 %t2, 0
503 define i1 @t31_var_oneuse6(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {
504 ; CHECK-LABEL: @t31_var_oneuse6(
505 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]
506 ; CHECK-NEXT: call void @use32(i32 [[T0]])
507 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]
508 ; CHECK-NEXT: call void @use32(i32 [[T1]])
509 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]
510 ; CHECK-NEXT: call void @use32(i32 [[T2]])
511 ; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0
512 ; CHECK-NEXT: ret i1 [[T3]]
514 %t0 = lshr i32 %x, %shamt0
515 call void @use32(i32 %t0)
516 %t1 = shl i32 %y, %shamt1
517 call void @use32(i32 %t1)
518 %t2 = and i32 %t1, %t0
519 call void @use32(i32 %t2)
520 %t3 = icmp ne i32 %t2, 0
526 ; Ok, non-truncated shift is of constant;
527 define i1 @t32_shift_of_const_oneuse0(i32 %x, i32 %y, i32 %len) {
528 ; CHECK-LABEL: @t32_shift_of_const_oneuse0(
529 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]
530 ; CHECK-NEXT: call void @use32(i32 [[T0]])
531 ; CHECK-NEXT: [[T1:%.*]] = lshr i32 -52543054, [[T0]]
532 ; CHECK-NEXT: call void @use32(i32 [[T1]])
533 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1
534 ; CHECK-NEXT: call void @use32(i32 [[T2]])
535 ; CHECK-NEXT: [[T3:%.*]] = shl i32 [[Y:%.*]], [[T2]]
536 ; CHECK-NEXT: call void @use32(i32 [[T3]])
537 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[Y]], 1
538 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
539 ; CHECK-NEXT: ret i1 [[TMP2]]
541 %t0 = sub i32 32, %len
542 call void @use32(i32 %t0)
543 %t1 = lshr i32 4242424242, %t0 ; shift-of-constant
544 call void @use32(i32 %t1)
545 %t2 = add i32 %len, -1
546 call void @use32(i32 %t2)
547 %t3 = shl i32 %y, %t2
548 call void @use32(i32 %t3)
549 %t4 = and i32 %t1, %t3 ; no extra uses
550 %t5 = icmp ne i32 %t4, 0
553 ; Ok, truncated shift is of constant;
554 define i1 @t33_shift_of_const_oneuse1(i32 %x, i32 %y, i32 %len) {
555 ; CHECK-LABEL: @t33_shift_of_const_oneuse1(
556 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]
557 ; CHECK-NEXT: call void @use32(i32 [[T0]])
558 ; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]
559 ; CHECK-NEXT: call void @use32(i32 [[T1]])
560 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1
561 ; CHECK-NEXT: call void @use32(i32 [[T2]])
562 ; CHECK-NEXT: [[T3:%.*]] = shl i32 -52543054, [[T2]]
563 ; CHECK-NEXT: call void @use32(i32 [[T3]])
564 ; CHECK-NEXT: ret i1 false
566 %t0 = sub i32 32, %len
567 call void @use32(i32 %t0)
568 %t1 = lshr i32 %x, %t0 ; shift-of-constant
569 call void @use32(i32 %t1)
570 %t2 = add i32 %len, -1
571 call void @use32(i32 %t2)
572 %t3 = shl i32 4242424242, %t2
573 call void @use32(i32 %t3)
574 %t4 = and i32 %t1, %t3 ; no extra uses
575 %t5 = icmp ne i32 %t4, 0
579 ; Commutativity with extra uses
581 define i1 @t34_commutativity0_oneuse0(i32 %x) {
582 ; CHECK-LABEL: @t34_commutativity0_oneuse0(
583 ; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32()
584 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1
585 ; CHECK-NEXT: call void @use32(i32 [[T0]])
586 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2
587 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]]
588 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
589 ; CHECK-NEXT: ret i1 [[TMP3]]
591 %y = call i32 @gen32()
593 call void @use32(i32 %t0)
595 %t2 = and i32 %t1, %t0
596 %t3 = icmp ne i32 %t2, 0
599 define i1 @t35_commutativity0_oneuse1(i32 %x) {
600 ; CHECK-LABEL: @t35_commutativity0_oneuse1(
601 ; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32()
602 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y]], 1
603 ; CHECK-NEXT: call void @use32(i32 [[T1]])
604 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2
605 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]]
606 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
607 ; CHECK-NEXT: ret i1 [[TMP3]]
609 %y = call i32 @gen32()
612 call void @use32(i32 %t1)
613 %t2 = and i32 %t1, %t0
614 %t3 = icmp ne i32 %t2, 0
618 define i1 @t36_commutativity1_oneuse0(i32 %y) {
619 ; CHECK-LABEL: @t36_commutativity1_oneuse0(
620 ; CHECK-NEXT: [[X:%.*]] = call i32 @gen32()
621 ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X]], 1
622 ; CHECK-NEXT: call void @use32(i32 [[T0]])
623 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2
624 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]]
625 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
626 ; CHECK-NEXT: ret i1 [[TMP3]]
628 %x = call i32 @gen32()
630 call void @use32(i32 %t0)
632 %t2 = and i32 %t0, %t1 ; "swapped"
633 %t3 = icmp ne i32 %t2, 0
636 define i1 @t37_commutativity1_oneuse1(i32 %y) {
637 ; CHECK-LABEL: @t37_commutativity1_oneuse1(
638 ; CHECK-NEXT: [[X:%.*]] = call i32 @gen32()
639 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1
640 ; CHECK-NEXT: call void @use32(i32 [[T1]])
641 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2
642 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]]
643 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
644 ; CHECK-NEXT: ret i1 [[TMP3]]
646 %x = call i32 @gen32()
649 call void @use32(i32 %t1)
650 %t2 = and i32 %t0, %t1 ; "swapped"
651 %t3 = icmp ne i32 %t2, 0
656 define <2 x i1> @n38_overshift(<2 x i32> %x, <2 x i32> %y) {
657 ; CHECK-LABEL: @n38_overshift(
658 ; CHECK-NEXT: [[T0:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 15, i32 1>
659 ; CHECK-NEXT: [[T1:%.*]] = shl <2 x i32> [[Y:%.*]], <i32 17, i32 1>
660 ; CHECK-NEXT: [[T2:%.*]] = and <2 x i32> [[T1]], [[T0]]
661 ; CHECK-NEXT: [[T3:%.*]] = icmp ne <2 x i32> [[T2]], zeroinitializer
662 ; CHECK-NEXT: ret <2 x i1> [[T3]]
664 %t0 = lshr <2 x i32> %x, <i32 15, i32 1>
665 %t1 = shl <2 x i32> %y, <i32 17, i32 1>
666 %t2 = and <2 x i32> %t1, %t0
667 %t3 = icmp ne <2 x i32> %t2, <i32 0, i32 0>
671 ; As usual, don't crash given constantexpr's :/
672 @f.a = internal global i16 0
673 define i1 @constantexpr() {
674 ; CHECK-LABEL: @constantexpr(
676 ; CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @f.a, align 2
677 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i16 [[TMP0]], 1
678 ; CHECK-NEXT: [[TMP2:%.*]] = and i16 [[TMP1]], shl (i16 1, i16 zext (i1 icmp ne (i16 ptrtoint (i16* @f.a to i16), i16 1) to i16))
679 ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i16 [[TMP2]], 0
680 ; CHECK-NEXT: ret i1 [[TOBOOL]]
683 %0 = load i16, i16* @f.a
684 %shr = ashr i16 %0, 1
685 %shr1 = ashr i16 %shr, zext (i1 icmp ne (i16 ptrtoint (i16* @f.a to i16), i16 1) to i16)
686 %and = and i16 %shr1, 1
687 %tobool = icmp ne i16 %and, 0