[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / InstCombine / shift-amount-reassociation-in-bittest-with-truncation-lshr.ll
blob118186f98a9e1964321d0cb8374375f357813059
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt %s -instcombine -S | FileCheck %s
4 ; Given pattern:
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 ;-------------------------------------------------------------------------------
13 ; Basic scalar tests
14 ;-------------------------------------------------------------------------------
16 ; This fold can't be performed for fully variable %x and %y
17 define i1 @n0(i32 %x, i64 %y, i32 %len) {
18 ; CHECK-LABEL: @n0(
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
30   %t1 = shl i32 %x, %t0
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
37   ret i1 %t5
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) {
44 ; CHECK-LABEL: @t1(
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
57   ret i1 %t5
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
74   ret i1 %t5
76 ; New shift amount would be 16, %x has 15 leading zeros - can not fold.
77 define i1 @n2(i64 %y, i32 %len) {
78 ; CHECK-LABEL: @n2(
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
97   ret i1 %t5
100 ; New shift amount would be 16, %y has 47 leading zeros - can fold.
101 define i1 @t3(i32 %x, i32 %len) {
102 ; CHECK-LABEL: @t3(
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
115   ret i1 %t5
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
132   ret i1 %t5
134 ; New shift amount would be 16, %y has 48 leading zeros - can not fold.
135 define i1 @n4(i32 %x, i32 %len) {
136 ; CHECK-LABEL: @n4(
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
155   ret i1 %t5
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 ;-------------------------------------------------------------------------------
162 ; Vector tests
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>
181   ret <2 x i1> %t5
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>
204   ret <2 x i1> %t5
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>
222   ret <2 x i1> %t5
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>
245   ret <2 x i1> %t5
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
267   ret i1 %t5
269 ; Not highest bit.
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
290   ret i1 %t5
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
309   ret i1 %t5
311 ; Not zero-shift.
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
332   ret i1 %t5
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>
356   ret <2 x i1> %t5
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>
378   ret <2 x i1> %t5
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
391   %t1 = shl i32 1, %t0
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
398   ret i1 %t5
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
412   ret i1 %t5
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>
430   ret <2 x i1> %t5
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>
444   ret <2 x i1> %t5
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
467   ret i1 %isbitunset