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.
9 ; We still can handle the case where there is a truncation between a shift
10 ; and an 'and', thought the legality check isn't obvious.
12 ;-------------------------------------------------------------------------------
14 ;-------------------------------------------------------------------------------
16 ; This fold can't be performed for fully variable %x and %y
17 define i1 @n0(i32 %x, i64 %y, i32 %len) {
19 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]
20 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[X:%.*]], [[T0]]
21 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -16
22 ; CHECK-NEXT: [[T2_WIDE:%.*]] = zext i32 [[T2]] to i64
23 ; CHECK-NEXT: [[T3:%.*]] = lshr i64 [[Y:%.*]], [[T2_WIDE]]
24 ; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc i64 [[T3]] to i32
25 ; CHECK-NEXT: [[T4:%.*]] = and i32 [[T1]], [[T3_TRUNC]]
26 ; CHECK-NEXT: [[T5:%.*]] = icmp ne i32 [[T4]], 0
27 ; CHECK-NEXT: ret i1 [[T5]]
29 %t0 = sub i32 32, %len
31 %t2 = add i32 %len, -16
32 %t2_wide = zext i32 %t2 to i64
33 %t3 = lshr i64 %y, %t2_wide
34 %t3_trunc = trunc i64 %t3 to i32
35 %t4 = and i32 %t1, %t3_trunc
36 %t5 = icmp ne i32 %t4, 0
40 ; However we can fold if %x/%y are constants that pass extra legality check.
42 ; New shift amount would be 16, %x has 16 leading zeros - can fold.
43 define i1 @t1(i64 %y, i32 %len) {
45 ; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[Y:%.*]], 4294901760
46 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i64 [[TMP1]], 0
47 ; CHECK-NEXT: ret i1 [[TMP2]]
49 %t0 = sub i32 32, %len
50 %t1 = shl i32 65535, %t0
51 %t2 = add i32 %len, -16
52 %t2_wide = zext i32 %t2 to i64
53 %t3 = lshr i64 %y, %t2_wide
54 %t3_trunc = trunc i64 %t3 to i32
55 %t4 = and i32 %t1, %t3_trunc
56 %t5 = icmp ne i32 %t4, 0
59 ; Note that we indeed look at leading zeros!
60 define i1 @t1_single_bit(i64 %y, i32 %len) {
61 ; CHECK-LABEL: @t1_single_bit(
62 ; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[Y:%.*]], 2147483648
63 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i64 [[TMP1]], 0
64 ; CHECK-NEXT: ret i1 [[TMP2]]
66 %t0 = sub i32 32, %len
67 %t1 = shl i32 32768, %t0
68 %t2 = add i32 %len, -16
69 %t2_wide = zext i32 %t2 to i64
70 %t3 = lshr i64 %y, %t2_wide
71 %t3_trunc = trunc i64 %t3 to i32
72 %t4 = and i32 %t1, %t3_trunc
73 %t5 = icmp ne i32 %t4, 0
76 ; New shift amount would be 16, %x has 15 leading zeros - can not fold.
77 define i1 @n2(i64 %y, i32 %len) {
79 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]
80 ; CHECK-NEXT: [[T1:%.*]] = shl i32 131071, [[T0]]
81 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -16
82 ; CHECK-NEXT: [[T2_WIDE:%.*]] = zext i32 [[T2]] to i64
83 ; CHECK-NEXT: [[T3:%.*]] = lshr i64 [[Y:%.*]], [[T2_WIDE]]
84 ; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc i64 [[T3]] to i32
85 ; CHECK-NEXT: [[T4:%.*]] = and i32 [[T1]], [[T3_TRUNC]]
86 ; CHECK-NEXT: [[T5:%.*]] = icmp ne i32 [[T4]], 0
87 ; CHECK-NEXT: ret i1 [[T5]]
89 %t0 = sub i32 32, %len
90 %t1 = shl i32 131071, %t0
91 %t2 = add i32 %len, -16
92 %t2_wide = zext i32 %t2 to i64
93 %t3 = lshr i64 %y, %t2_wide
94 %t3_trunc = trunc i64 %t3 to i32
95 %t4 = and i32 %t1, %t3_trunc
96 %t5 = icmp ne i32 %t4, 0
100 ; New shift amount would be 16, %y has 47 leading zeros - can fold.
101 define i1 @t3(i32 %x, i32 %len) {
103 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 1
104 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
105 ; CHECK-NEXT: ret i1 [[TMP2]]
107 %t0 = sub i32 32, %len
108 %t1 = shl i32 %x, %t0
109 %t2 = add i32 %len, -16
110 %t2_wide = zext i32 %t2 to i64
111 %t3 = lshr i64 131071, %t2_wide
112 %t3_trunc = trunc i64 %t3 to i32
113 %t4 = and i32 %t1, %t3_trunc
114 %t5 = icmp ne i32 %t4, 0
117 ; Note that we indeed look at leading zeros!
118 define i1 @t3_singlebit(i32 %x, i32 %len) {
119 ; CHECK-LABEL: @t3_singlebit(
120 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 1
121 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
122 ; CHECK-NEXT: ret i1 [[TMP2]]
124 %t0 = sub i32 32, %len
125 %t1 = shl i32 %x, %t0
126 %t2 = add i32 %len, -16
127 %t2_wide = zext i32 %t2 to i64
128 %t3 = lshr i64 65536, %t2_wide
129 %t3_trunc = trunc i64 %t3 to i32
130 %t4 = and i32 %t1, %t3_trunc
131 %t5 = icmp ne i32 %t4, 0
134 ; New shift amount would be 16, %y has 48 leading zeros - can not fold.
135 define i1 @n4(i32 %x, i32 %len) {
137 ; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]
138 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[X:%.*]], [[T0]]
139 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -16
140 ; CHECK-NEXT: [[T2_WIDE:%.*]] = zext i32 [[T2]] to i64
141 ; CHECK-NEXT: [[T3:%.*]] = lshr i64 262143, [[T2_WIDE]]
142 ; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc i64 [[T3]] to i32
143 ; CHECK-NEXT: [[T4:%.*]] = and i32 [[T1]], [[T3_TRUNC]]
144 ; CHECK-NEXT: [[T5:%.*]] = icmp ne i32 [[T4]], 0
145 ; CHECK-NEXT: ret i1 [[T5]]
147 %t0 = sub i32 32, %len
148 %t1 = shl i32 %x, %t0
149 %t2 = add i32 %len, -16
150 %t2_wide = zext i32 %t2 to i64
151 %t3 = lshr i64 262143, %t2_wide
152 %t3_trunc = trunc i64 %t3 to i32
153 %t4 = and i32 %t1, %t3_trunc
154 %t5 = icmp ne i32 %t4, 0
158 ; While we could still deal with arbitrary values if KnownBits can answer
159 ; the question, it isn't obvious it's worth it, so let's not for now.
161 ;-------------------------------------------------------------------------------
163 ;-------------------------------------------------------------------------------
165 ; New shift amount would be 16, minimal count of leading zeros in %x is 16. Ok.
166 define <2 x i1> @t5_vec(<2 x i64> %y, <2 x i32> %len) {
167 ; CHECK-LABEL: @t5_vec(
168 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i64> [[Y:%.*]], <i64 16, i64 16>
169 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i64> [[TMP1]], <i64 65535, i64 32767>
170 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i64> [[TMP2]], zeroinitializer
171 ; CHECK-NEXT: ret <2 x i1> [[TMP3]]
173 %t0 = sub <2 x i32> <i32 32, i32 32>, %len
174 %t1 = shl <2 x i32> <i32 65535, i32 32767>, %t0
175 %t2 = add <2 x i32> %len, <i32 -16, i32 -16>
176 %t2_wide = zext <2 x i32> %t2 to <2 x i64>
177 %t3 = lshr <2 x i64> %y, %t2_wide
178 %t3_trunc = trunc <2 x i64> %t3 to <2 x i32>
179 %t4 = and <2 x i32> %t1, %t3_trunc
180 %t5 = icmp ne <2 x i32> %t4, <i32 0, i32 0>
183 ; New shift amount would be 16, minimal count of leading zeros in %x is 15, not ok to fold.
184 define <2 x i1> @n6_vec(<2 x i64> %y, <2 x i32> %len) {
185 ; CHECK-LABEL: @n6_vec(
186 ; CHECK-NEXT: [[T0:%.*]] = sub <2 x i32> <i32 32, i32 32>, [[LEN:%.*]]
187 ; CHECK-NEXT: [[T1:%.*]] = shl <2 x i32> <i32 65535, i32 131071>, [[T0]]
188 ; CHECK-NEXT: [[T2:%.*]] = add <2 x i32> [[LEN]], <i32 -16, i32 -16>
189 ; CHECK-NEXT: [[T2_WIDE:%.*]] = zext <2 x i32> [[T2]] to <2 x i64>
190 ; CHECK-NEXT: [[T3:%.*]] = lshr <2 x i64> [[Y:%.*]], [[T2_WIDE]]
191 ; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc <2 x i64> [[T3]] to <2 x i32>
192 ; CHECK-NEXT: [[T4:%.*]] = and <2 x i32> [[T1]], [[T3_TRUNC]]
193 ; CHECK-NEXT: [[T5:%.*]] = icmp ne <2 x i32> [[T4]], zeroinitializer
194 ; CHECK-NEXT: ret <2 x i1> [[T5]]
196 %t0 = sub <2 x i32> <i32 32, i32 32>, %len
197 %t1 = shl <2 x i32> <i32 65535, i32 131071>, %t0
198 %t2 = add <2 x i32> %len, <i32 -16, i32 -16>
199 %t2_wide = zext <2 x i32> %t2 to <2 x i64>
200 %t3 = lshr <2 x i64> %y, %t2_wide
201 %t3_trunc = trunc <2 x i64> %t3 to <2 x i32>
202 %t4 = and <2 x i32> %t1, %t3_trunc
203 %t5 = icmp ne <2 x i32> %t4, <i32 0, i32 0>
207 ; New shift amount would be 16, minimal count of leading zeros in %x is 47. Ok.
208 define <2 x i1> @t7_vec(<2 x i32> %x, <2 x i32> %len) {
209 ; CHECK-LABEL: @t7_vec(
210 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 1, i32 0>
211 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer
212 ; CHECK-NEXT: ret <2 x i1> [[TMP2]]
214 %t0 = sub <2 x i32> <i32 32, i32 32>, %len
215 %t1 = shl <2 x i32> %x, %t0
216 %t2 = add <2 x i32> %len, <i32 -16, i32 -16>
217 %t2_wide = zext <2 x i32> %t2 to <2 x i64>
218 %t3 = lshr <2 x i64> <i64 131071, i64 65535>, %t2_wide
219 %t3_trunc = trunc <2 x i64> %t3 to <2 x i32>
220 %t4 = and <2 x i32> %t1, %t3_trunc
221 %t5 = icmp ne <2 x i32> %t4, <i32 0, i32 0>
224 ; New shift amount would be 16, minimal count of leading zeros in %x is 48, not ok to fold.
225 define <2 x i1> @n8_vec(<2 x i32> %x, <2 x i32> %len) {
226 ; CHECK-LABEL: @n8_vec(
227 ; CHECK-NEXT: [[T0:%.*]] = sub <2 x i32> <i32 32, i32 32>, [[LEN:%.*]]
228 ; CHECK-NEXT: [[T1:%.*]] = shl <2 x i32> [[X:%.*]], [[T0]]
229 ; CHECK-NEXT: [[T2:%.*]] = add <2 x i32> [[LEN]], <i32 -16, i32 -16>
230 ; CHECK-NEXT: [[T2_WIDE:%.*]] = zext <2 x i32> [[T2]] to <2 x i64>
231 ; CHECK-NEXT: [[T3:%.*]] = lshr <2 x i64> <i64 131071, i64 262143>, [[T2_WIDE]]
232 ; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc <2 x i64> [[T3]] to <2 x i32>
233 ; CHECK-NEXT: [[T4:%.*]] = and <2 x i32> [[T1]], [[T3_TRUNC]]
234 ; CHECK-NEXT: [[T5:%.*]] = icmp ne <2 x i32> [[T4]], zeroinitializer
235 ; CHECK-NEXT: ret <2 x i1> [[T5]]
237 %t0 = sub <2 x i32> <i32 32, i32 32>, %len
238 %t1 = shl <2 x i32> %x, %t0
239 %t2 = add <2 x i32> %len, <i32 -16, i32 -16>
240 %t2_wide = zext <2 x i32> %t2 to <2 x i64>
241 %t3 = lshr <2 x i64> <i64 131071, i64 262143>, %t2_wide
242 %t3_trunc = trunc <2 x i64> %t3 to <2 x i32>
243 %t4 = and <2 x i32> %t1, %t3_trunc
244 %t5 = icmp ne <2 x i32> %t4, <i32 0, i32 0>
248 ;-------------------------------------------------------------------------------
250 ; Ok if the final shift amount is exactly one less than widest bit width.
251 define i1 @t9_highest_bit(i32 %x, i64 %y, i32 %len) {
252 ; CHECK-LABEL: @t9_highest_bit(
253 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[X:%.*]] to i64
254 ; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[Y:%.*]], 63
255 ; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], [[TMP1]]
256 ; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i64 [[TMP3]], 0
257 ; CHECK-NEXT: ret i1 [[TMP4]]
259 %t0 = sub i32 64, %len
260 %t1 = shl i32 %x, %t0
261 %t2 = add i32 %len, -1
262 %t2_wide = zext i32 %t2 to i64
263 %t3 = lshr i64 %y, %t2_wide
264 %t3_trunc = trunc i64 %t3 to i32
265 %t4 = and i32 %t1, %t3_trunc
266 %t5 = icmp ne i32 %t4, 0
270 define i1 @t10_almost_highest_bit(i32 %x, i64 %y, i32 %len) {
271 ; CHECK-LABEL: @t10_almost_highest_bit(
272 ; CHECK-NEXT: [[T0:%.*]] = sub i32 64, [[LEN:%.*]]
273 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[X:%.*]], [[T0]]
274 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -2
275 ; CHECK-NEXT: [[T2_WIDE:%.*]] = zext i32 [[T2]] to i64
276 ; CHECK-NEXT: [[T3:%.*]] = lshr i64 [[Y:%.*]], [[T2_WIDE]]
277 ; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc i64 [[T3]] to i32
278 ; CHECK-NEXT: [[T4:%.*]] = and i32 [[T1]], [[T3_TRUNC]]
279 ; CHECK-NEXT: [[T5:%.*]] = icmp ne i32 [[T4]], 0
280 ; CHECK-NEXT: ret i1 [[T5]]
282 %t0 = sub i32 64, %len
283 %t1 = shl i32 %x, %t0
284 %t2 = add i32 %len, -2
285 %t2_wide = zext i32 %t2 to i64
286 %t3 = lshr i64 %y, %t2_wide
287 %t3_trunc = trunc i64 %t3 to i32
288 %t4 = and i32 %t1, %t3_trunc
289 %t5 = icmp ne i32 %t4, 0
293 ; Ok if the final shift amount is zero.
294 define i1 @t11_no_shift(i32 %x, i64 %y, i32 %len) {
295 ; CHECK-LABEL: @t11_no_shift(
296 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[X:%.*]] to i64
297 ; CHECK-NEXT: [[TMP2:%.*]] = and i64 [[TMP1]], [[Y:%.*]]
298 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i64 [[TMP2]], 0
299 ; CHECK-NEXT: ret i1 [[TMP3]]
301 %t0 = sub i32 64, %len
302 %t1 = shl i32 %x, %t0
303 %t2 = add i32 %len, -64
304 %t2_wide = zext i32 %t2 to i64
305 %t3 = lshr i64 %y, %t2_wide
306 %t3_trunc = trunc i64 %t3 to i32
307 %t4 = and i32 %t1, %t3_trunc
308 %t5 = icmp ne i32 %t4, 0
312 define i1 @t10_shift_by_one(i32 %x, i64 %y, i32 %len) {
313 ; CHECK-LABEL: @t10_shift_by_one(
314 ; CHECK-NEXT: [[T0:%.*]] = sub i32 64, [[LEN:%.*]]
315 ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[X:%.*]], [[T0]]
316 ; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -63
317 ; CHECK-NEXT: [[T2_WIDE:%.*]] = zext i32 [[T2]] to i64
318 ; CHECK-NEXT: [[T3:%.*]] = lshr i64 [[Y:%.*]], [[T2_WIDE]]
319 ; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc i64 [[T3]] to i32
320 ; CHECK-NEXT: [[T4:%.*]] = and i32 [[T1]], [[T3_TRUNC]]
321 ; CHECK-NEXT: [[T5:%.*]] = icmp ne i32 [[T4]], 0
322 ; CHECK-NEXT: ret i1 [[T5]]
324 %t0 = sub i32 64, %len
325 %t1 = shl i32 %x, %t0
326 %t2 = add i32 %len, -63
327 %t2_wide = zext i32 %t2 to i64
328 %t3 = lshr i64 %y, %t2_wide
329 %t3_trunc = trunc i64 %t3 to i32
330 %t4 = and i32 %t1, %t3_trunc
331 %t5 = icmp ne i32 %t4, 0
335 ; A mix of those conditions is ok.
336 define <2 x i1> @t11_zero_and_almost_bitwidth(<2 x i32> %x, <2 x i64> %y, <2 x i32> %len) {
337 ; CHECK-LABEL: @t11_zero_and_almost_bitwidth(
338 ; CHECK-NEXT: [[T0:%.*]] = sub <2 x i32> <i32 64, i32 64>, [[LEN:%.*]]
339 ; CHECK-NEXT: [[T1:%.*]] = shl <2 x i32> [[X:%.*]], [[T0]]
340 ; CHECK-NEXT: [[T2:%.*]] = add <2 x i32> [[LEN]], <i32 -1, i32 -64>
341 ; CHECK-NEXT: [[T2_WIDE:%.*]] = zext <2 x i32> [[T2]] to <2 x i64>
342 ; CHECK-NEXT: [[T3:%.*]] = lshr <2 x i64> [[Y:%.*]], [[T2_WIDE]]
343 ; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc <2 x i64> [[T3]] to <2 x i32>
344 ; CHECK-NEXT: [[T4:%.*]] = and <2 x i32> [[T1]], [[T3_TRUNC]]
345 ; CHECK-NEXT: [[T5:%.*]] = icmp ne <2 x i32> [[T4]], zeroinitializer
346 ; CHECK-NEXT: ret <2 x i1> [[T5]]
348 %t0 = sub <2 x i32> <i32 64, i32 64>, %len
349 %t1 = shl <2 x i32> %x, %t0
350 %t2 = add <2 x i32> %len, <i32 -1, i32 -64>
351 %t2_wide = zext <2 x i32> %t2 to <2 x i64>
352 %t3 = lshr <2 x i64> %y, %t2_wide
353 %t3_trunc = trunc <2 x i64> %t3 to <2 x i32>
354 %t4 = and <2 x i32> %t1, %t3_trunc
355 %t5 = icmp ne <2 x i32> %t4, <i32 0, i32 0>
358 define <2 x i1> @n12_bad(<2 x i32> %x, <2 x i64> %y, <2 x i32> %len) {
359 ; CHECK-LABEL: @n12_bad(
360 ; CHECK-NEXT: [[T0:%.*]] = sub <2 x i32> <i32 64, i32 64>, [[LEN:%.*]]
361 ; CHECK-NEXT: [[T1:%.*]] = shl <2 x i32> [[X:%.*]], [[T0]]
362 ; CHECK-NEXT: [[T2:%.*]] = add <2 x i32> [[LEN]], <i32 -2, i32 -64>
363 ; CHECK-NEXT: [[T2_WIDE:%.*]] = zext <2 x i32> [[T2]] to <2 x i64>
364 ; CHECK-NEXT: [[T3:%.*]] = lshr <2 x i64> [[Y:%.*]], [[T2_WIDE]]
365 ; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc <2 x i64> [[T3]] to <2 x i32>
366 ; CHECK-NEXT: [[T4:%.*]] = and <2 x i32> [[T1]], [[T3_TRUNC]]
367 ; CHECK-NEXT: [[T5:%.*]] = icmp ne <2 x i32> [[T4]], zeroinitializer
368 ; CHECK-NEXT: ret <2 x i1> [[T5]]
370 %t0 = sub <2 x i32> <i32 64, i32 64>, %len
371 %t1 = shl <2 x i32> %x, %t0
372 %t2 = add <2 x i32> %len, <i32 -2, i32 -64>
373 %t2_wide = zext <2 x i32> %t2 to <2 x i64>
374 %t3 = lshr <2 x i64> %y, %t2_wide
375 %t3_trunc = trunc <2 x i64> %t3 to <2 x i32>
376 %t4 = and <2 x i32> %t1, %t3_trunc
377 %t5 = icmp ne <2 x i32> %t4, <i32 0, i32 0>
381 ;------------------------------------------------------------------------------;
383 ; Ok if one of the values being shifted is 1
384 define i1 @t13_x_is_one(i64 %y, i32 %len) {
385 ; CHECK-LABEL: @t13_x_is_one(
386 ; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[Y:%.*]], 65536
387 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i64 [[TMP1]], 0
388 ; CHECK-NEXT: ret i1 [[TMP2]]
390 %t0 = sub i32 32, %len
392 %t2 = add i32 %len, -16
393 %t2_wide = zext i32 %t2 to i64
394 %t3 = lshr i64 %y, %t2_wide
395 %t3_trunc = trunc i64 %t3 to i32
396 %t4 = and i32 %t1, %t3_trunc
397 %t5 = icmp ne i32 %t4, 0
400 define i1 @t14_x_is_one(i32 %x, i32 %len) {
401 ; CHECK-LABEL: @t14_x_is_one(
402 ; CHECK-NEXT: ret i1 false
404 %t0 = sub i32 32, %len
405 %t1 = shl i32 %x, %t0
406 %t2 = add i32 %len, -16
407 %t2_wide = zext i32 %t2 to i64
408 %t3 = lshr i64 1, %t2_wide
409 %t3_trunc = trunc i64 %t3 to i32
410 %t4 = and i32 %t1, %t3_trunc
411 %t5 = icmp ne i32 %t4, 0
415 define <2 x i1> @t15_vec_x_is_one_or_zero(<2 x i64> %y, <2 x i32> %len) {
416 ; CHECK-LABEL: @t15_vec_x_is_one_or_zero(
417 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i64> [[Y:%.*]], <i64 48, i64 48>
418 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i64> [[TMP1]], <i64 1, i64 0>
419 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i64> [[TMP2]], zeroinitializer
420 ; CHECK-NEXT: ret <2 x i1> [[TMP3]]
422 %t0 = sub <2 x i32> <i32 64, i32 64>, %len
423 %t1 = shl <2 x i32> <i32 1, i32 0>, %t0
424 %t2 = add <2 x i32> %len, <i32 -16, i32 -16>
425 %t2_wide = zext <2 x i32> %t2 to <2 x i64>
426 %t3 = lshr <2 x i64> %y, %t2_wide
427 %t3_trunc = trunc <2 x i64> %t3 to <2 x i32>
428 %t4 = and <2 x i32> %t1, %t3_trunc
429 %t5 = icmp ne <2 x i32> %t4, <i32 0, i32 0>
432 define <2 x i1> @t16_vec_y_is_one_or_zero(<2 x i32> %x, <2 x i32> %len) {
433 ; CHECK-LABEL: @t16_vec_y_is_one_or_zero(
434 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
436 %t0 = sub <2 x i32> <i32 64, i32 64>, %len
437 %t1 = shl <2 x i32> %x, %t0
438 %t2 = add <2 x i32> %len, <i32 -16, i32 -16>
439 %t2_wide = zext <2 x i32> %t2 to <2 x i64>
440 %t3 = lshr <2 x i64> <i64 1, i64 0>, %t2_wide
441 %t3_trunc = trunc <2 x i64> %t3 to <2 x i32>
442 %t4 = and <2 x i32> %t1, %t3_trunc
443 %t5 = icmp ne <2 x i32> %t4, <i32 0, i32 0>
447 ;------------------------------------------------------------------------------;
449 ; All other tests - extra uses, etc are already covered in
450 ; shift-amount-reassociation-in-bittest-with-truncation-shl.ll and
451 ; shift-amount-reassociation-in-bittest.ll
453 ; And that's the main motivational pattern:
454 define i1 @rawspeed_signbit(i64 %storage, i32 %nbits) {
455 ; CHECK-LABEL: @rawspeed_signbit(
456 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[STORAGE:%.*]], -1
457 ; CHECK-NEXT: ret i1 [[TMP1]]
459 %skipnbits = sub nsw i32 64, %nbits
460 %skipnbitswide = zext i32 %skipnbits to i64
461 %datawide = lshr i64 %storage, %skipnbitswide
462 %data = trunc i64 %datawide to i32
463 %nbitsminusone = add nsw i32 %nbits, -1
464 %bitmask = shl i32 1, %nbitsminusone
465 %bitmasked = and i32 %bitmask, %data
466 %isbitunset = icmp eq i32 %bitmasked, 0