[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / signed-truncation-check.ll
blob105e77284b93b70f3dd7b66e3529a5f41d4f821b
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 ; General pattern:
5 ;   X & Y
7 ; Where Y is checking that all the high bits (covered by a mask 4294967168)
8 ; are uniform, i.e.  %arg & 4294967168  can be either  4294967168  or  0
9 ; Pattern can be one of:
10 ;   %t = add        i32 %arg,    128
11 ;   %r = icmp   ult i32 %t,      256
12 ; Or
13 ;   %t0 = shl       i32 %arg,    24
14 ;   %t1 = ashr      i32 %t0,     24
15 ;   %r  = icmp  eq  i32 %t1,     %arg
16 ; Or
17 ;   %t0 = trunc     i32 %arg  to i8
18 ;   %t1 = sext      i8  %t0   to i32
19 ;   %r  = icmp  eq  i32 %t1,     %arg
20 ; This pattern is a signed truncation check.
22 ; And X is checking that some bit in that same mask is zero.
23 ; I.e. can be one of:
24 ;   %r = icmp sgt i32   %arg,    -1
25 ; Or
26 ;   %t = and      i32   %arg,    2147483648
27 ;   %r = icmp eq  i32   %t,      0
29 ; Since we are checking that all the bits in that mask are the same,
30 ; and a particular bit is zero, what we are really checking is that all the
31 ; masked bits are zero.
32 ; So this should be transformed to:
33 ;   %r = icmp ult i32 %arg, 128
35 ; ============================================================================ ;
36 ; Basic positive test
37 ; ============================================================================ ;
39 define i1 @positive_with_signbit(i32 %arg) {
40 ; CHECK-LABEL: @positive_with_signbit(
41 ; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG:%.*]], 128
42 ; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
44   %t1 = icmp sgt i32 %arg, -1
45   %t2 = add i32 %arg, 128
46   %t3 = icmp ult i32 %t2, 256
47   %t4 = and i1 %t1, %t3
48   ret i1 %t4
51 define i1 @positive_with_signbit_logical(i32 %arg) {
52 ; CHECK-LABEL: @positive_with_signbit_logical(
53 ; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG:%.*]], 128
54 ; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
56   %t1 = icmp sgt i32 %arg, -1
57   %t2 = add i32 %arg, 128
58   %t3 = icmp ult i32 %t2, 256
59   %t4 = select i1 %t1, i1 %t3, i1 false
60   ret i1 %t4
63 define i1 @positive_with_mask(i32 %arg) {
64 ; CHECK-LABEL: @positive_with_mask(
65 ; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG:%.*]], 128
66 ; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]
68   %t1 = and i32 %arg, 1107296256
69   %t2 = icmp eq i32 %t1, 0
70   %t3 = add i32 %arg, 128
71   %t4 = icmp ult i32 %t3, 256
72   %t5 = and i1 %t2, %t4
73   ret i1 %t5
76 define i1 @positive_with_mask_logical(i32 %arg) {
77 ; CHECK-LABEL: @positive_with_mask_logical(
78 ; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG:%.*]], 128
79 ; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]
81   %t1 = and i32 %arg, 1107296256
82   %t2 = icmp eq i32 %t1, 0
83   %t3 = add i32 %arg, 128
84   %t4 = icmp ult i32 %t3, 256
85   %t5 = select i1 %t2, i1 %t4, i1 false
86   ret i1 %t5
89 define i1 @positive_with_icmp(i32 %arg) {
90 ; CHECK-LABEL: @positive_with_icmp(
91 ; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG:%.*]], 128
92 ; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
94   %t1 = icmp ult i32 %arg, 512
95   %t2 = add i32 %arg, 128
96   %t3 = icmp ult i32 %t2, 256
97   %t4 = and i1 %t1, %t3
98   ret i1 %t4
101 define i1 @positive_with_icmp_logical(i32 %arg) {
102 ; CHECK-LABEL: @positive_with_icmp_logical(
103 ; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG:%.*]], 128
104 ; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
106   %t1 = icmp ult i32 %arg, 512
107   %t2 = add i32 %arg, 128
108   %t3 = icmp ult i32 %t2, 256
109   %t4 = select i1 %t1, i1 %t3, i1 false
110   ret i1 %t4
113 ; Still the same
114 define i1 @positive_with_aggressive_icmp(i32 %arg) {
115 ; CHECK-LABEL: @positive_with_aggressive_icmp(
116 ; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG:%.*]], 128
117 ; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
119   %t1 = icmp ult i32 %arg, 128
120   %t2 = add i32 %arg, 256
121   %t3 = icmp ult i32 %t2, 512
122   %t4 = and i1 %t1, %t3
123   ret i1 %t4
126 define i1 @positive_with_aggressive_icmp_logical(i32 %arg) {
127 ; CHECK-LABEL: @positive_with_aggressive_icmp_logical(
128 ; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG:%.*]], 128
129 ; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
131   %t1 = icmp ult i32 %arg, 128
132   %t2 = add i32 %arg, 256
133   %t3 = icmp ult i32 %t2, 512
134   %t4 = select i1 %t1, i1 %t3, i1 false
135   ret i1 %t4
138 ; I'm sure there is a bunch more patterns possible :/
140 ; This used to trigger an assert, because the icmp's are not direct
141 ; operands of the and.
142 define i1 @positive_with_extra_and(i32 %arg, i1 %z) {
143 ; CHECK-LABEL: @positive_with_extra_and(
144 ; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG:%.*]], 128
145 ; CHECK-NEXT:    [[TMP1:%.*]] = and i1 [[T5_SIMPLIFIED]], [[Z:%.*]]
146 ; CHECK-NEXT:    ret i1 [[TMP1]]
148   %t1 = icmp sgt i32 %arg, -1
149   %t2 = add i32 %arg, 128
150   %t3 = icmp ult i32 %t2, 256
151   %t4 = and i1 %t1, %z
152   %t5 = and i1 %t3, %t4
153   ret i1 %t5
156 define i1 @positive_with_extra_and_logical(i32 %arg, i1 %z) {
157 ; CHECK-LABEL: @positive_with_extra_and_logical(
158 ; CHECK-NEXT:    [[DOTSIMPLIFIED:%.*]] = icmp ult i32 [[ARG:%.*]], 128
159 ; CHECK-NEXT:    [[T5:%.*]] = select i1 [[DOTSIMPLIFIED]], i1 [[Z:%.*]], i1 false
160 ; CHECK-NEXT:    ret i1 [[T5]]
162   %t1 = icmp sgt i32 %arg, -1
163   %t2 = add i32 %arg, 128
164   %t3 = icmp ult i32 %t2, 256
165   %t4 = select i1 %t1, i1 %z, i1 false
166   %t5 = select i1 %t3, i1 %t4, i1 false
167   ret i1 %t5
170 ; ============================================================================ ;
171 ; Vector tests
172 ; ============================================================================ ;
174 define <2 x i1> @positive_vec_splat(<2 x i32> %arg) {
175 ; CHECK-LABEL: @positive_vec_splat(
176 ; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult <2 x i32> [[ARG:%.*]], <i32 128, i32 128>
177 ; CHECK-NEXT:    ret <2 x i1> [[T4_SIMPLIFIED]]
179   %t1 = icmp sgt <2 x i32> %arg, <i32 -1, i32 -1>
180   %t2 = add <2 x i32> %arg, <i32 128, i32 128>
181   %t3 = icmp ult <2 x i32> %t2, <i32 256, i32 256>
182   %t4 = and <2 x i1> %t1, %t3
183   ret <2 x i1> %t4
186 define <2 x i1> @positive_vec_nonsplat(<2 x i32> %arg) {
187 ; CHECK-LABEL: @positive_vec_nonsplat(
188 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt <2 x i32> [[ARG:%.*]], <i32 -1, i32 -1>
189 ; CHECK-NEXT:    [[T2:%.*]] = add <2 x i32> [[ARG]], <i32 128, i32 256>
190 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult <2 x i32> [[T2]], <i32 256, i32 512>
191 ; CHECK-NEXT:    [[T4:%.*]] = and <2 x i1> [[T1]], [[T3]]
192 ; CHECK-NEXT:    ret <2 x i1> [[T4]]
194   %t1 = icmp sgt <2 x i32> %arg, <i32 -1, i32 -1>
195   %t2 = add <2 x i32> %arg, <i32 128, i32 256>
196   %t3 = icmp ult <2 x i32> %t2, <i32 256, i32 512>
197   %t4 = and <2 x i1> %t1, %t3
198   ret <2 x i1> %t4
201 define <3 x i1> @positive_vec_undef0(<3 x i32> %arg) {
202 ; CHECK-LABEL: @positive_vec_undef0(
203 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt <3 x i32> [[ARG:%.*]], <i32 -1, i32 undef, i32 -1>
204 ; CHECK-NEXT:    [[T2:%.*]] = add <3 x i32> [[ARG]], <i32 128, i32 128, i32 128>
205 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult <3 x i32> [[T2]], <i32 256, i32 256, i32 256>
206 ; CHECK-NEXT:    [[T4:%.*]] = and <3 x i1> [[T1]], [[T3]]
207 ; CHECK-NEXT:    ret <3 x i1> [[T4]]
209   %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 undef, i32 -1>
210   %t2 = add <3 x i32> %arg, <i32 128, i32 128, i32 128>
211   %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 256, i32 256>
212   %t4 = and <3 x i1> %t1, %t3
213   ret <3 x i1> %t4
216 define <3 x i1> @positive_vec_undef1(<3 x i32> %arg) {
217 ; CHECK-LABEL: @positive_vec_undef1(
218 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt <3 x i32> [[ARG:%.*]], <i32 -1, i32 -1, i32 -1>
219 ; CHECK-NEXT:    [[T2:%.*]] = add <3 x i32> [[ARG]], <i32 128, i32 undef, i32 128>
220 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult <3 x i32> [[T2]], <i32 256, i32 256, i32 256>
221 ; CHECK-NEXT:    [[T4:%.*]] = and <3 x i1> [[T1]], [[T3]]
222 ; CHECK-NEXT:    ret <3 x i1> [[T4]]
224   %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 -1, i32 -1>
225   %t2 = add <3 x i32> %arg, <i32 128, i32 undef, i32 128>
226   %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 256, i32 256>
227   %t4 = and <3 x i1> %t1, %t3
228   ret <3 x i1> %t4
231 define <3 x i1> @positive_vec_undef2(<3 x i32> %arg) {
232 ; CHECK-LABEL: @positive_vec_undef2(
233 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt <3 x i32> [[ARG:%.*]], <i32 -1, i32 -1, i32 -1>
234 ; CHECK-NEXT:    [[T2:%.*]] = add <3 x i32> [[ARG]], <i32 128, i32 128, i32 128>
235 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult <3 x i32> [[T2]], <i32 256, i32 undef, i32 256>
236 ; CHECK-NEXT:    [[T4:%.*]] = and <3 x i1> [[T1]], [[T3]]
237 ; CHECK-NEXT:    ret <3 x i1> [[T4]]
239   %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 -1, i32 -1>
240   %t2 = add <3 x i32> %arg, <i32 128, i32 128, i32 128>
241   %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 undef, i32 256>
242   %t4 = and <3 x i1> %t1, %t3
243   ret <3 x i1> %t4
246 define <3 x i1> @positive_vec_undef3(<3 x i32> %arg) {
247 ; CHECK-LABEL: @positive_vec_undef3(
248 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt <3 x i32> [[ARG:%.*]], <i32 -1, i32 undef, i32 -1>
249 ; CHECK-NEXT:    [[T2:%.*]] = add <3 x i32> [[ARG]], <i32 128, i32 undef, i32 128>
250 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult <3 x i32> [[T2]], <i32 256, i32 256, i32 256>
251 ; CHECK-NEXT:    [[T4:%.*]] = and <3 x i1> [[T1]], [[T3]]
252 ; CHECK-NEXT:    ret <3 x i1> [[T4]]
254   %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 undef, i32 -1>
255   %t2 = add <3 x i32> %arg, <i32 128, i32 undef, i32 128>
256   %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 256, i32 256>
257   %t4 = and <3 x i1> %t1, %t3
258   ret <3 x i1> %t4
261 define <3 x i1> @positive_vec_undef4(<3 x i32> %arg) {
262 ; CHECK-LABEL: @positive_vec_undef4(
263 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt <3 x i32> [[ARG:%.*]], <i32 -1, i32 undef, i32 -1>
264 ; CHECK-NEXT:    [[T2:%.*]] = add <3 x i32> [[ARG]], <i32 128, i32 128, i32 128>
265 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult <3 x i32> [[T2]], <i32 256, i32 undef, i32 256>
266 ; CHECK-NEXT:    [[T4:%.*]] = and <3 x i1> [[T1]], [[T3]]
267 ; CHECK-NEXT:    ret <3 x i1> [[T4]]
269   %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 undef, i32 -1>
270   %t2 = add <3 x i32> %arg, <i32 128, i32 128, i32 128>
271   %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 undef, i32 256>
272   %t4 = and <3 x i1> %t1, %t3
273   ret <3 x i1> %t4
276 define <3 x i1> @positive_vec_undef5(<3 x i32> %arg) {
277 ; CHECK-LABEL: @positive_vec_undef5(
278 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt <3 x i32> [[ARG:%.*]], <i32 -1, i32 -1, i32 -1>
279 ; CHECK-NEXT:    [[T2:%.*]] = add <3 x i32> [[ARG]], <i32 128, i32 undef, i32 128>
280 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult <3 x i32> [[T2]], <i32 256, i32 undef, i32 256>
281 ; CHECK-NEXT:    [[T4:%.*]] = and <3 x i1> [[T1]], [[T3]]
282 ; CHECK-NEXT:    ret <3 x i1> [[T4]]
284   %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 -1, i32 -1>
285   %t2 = add <3 x i32> %arg, <i32 128, i32 undef, i32 128>
286   %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 undef, i32 256>
287   %t4 = and <3 x i1> %t1, %t3
288   ret <3 x i1> %t4
291 define <3 x i1> @positive_vec_undef6(<3 x i32> %arg) {
292 ; CHECK-LABEL: @positive_vec_undef6(
293 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt <3 x i32> [[ARG:%.*]], <i32 -1, i32 undef, i32 -1>
294 ; CHECK-NEXT:    [[T2:%.*]] = add <3 x i32> [[ARG]], <i32 128, i32 undef, i32 128>
295 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult <3 x i32> [[T2]], <i32 256, i32 undef, i32 256>
296 ; CHECK-NEXT:    [[T4:%.*]] = and <3 x i1> [[T1]], [[T3]]
297 ; CHECK-NEXT:    ret <3 x i1> [[T4]]
299   %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 undef, i32 -1>
300   %t2 = add <3 x i32> %arg, <i32 128, i32 undef, i32 128>
301   %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 undef, i32 256>
302   %t4 = and <3 x i1> %t1, %t3
303   ret <3 x i1> %t4
306 ; ============================================================================ ;
307 ; Commutativity tests.
308 ; ============================================================================ ;
310 declare i32 @gen32()
312 define i1 @commutative() {
313 ; CHECK-LABEL: @commutative(
314 ; CHECK-NEXT:    [[ARG:%.*]] = call i32 @gen32()
315 ; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
316 ; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
318   %arg = call i32 @gen32()
319   %t1 = icmp sgt i32 %arg, -1
320   %t2 = add i32 %arg, 128
321   %t3 = icmp ult i32 %t2, 256
322   %t4 = and i1 %t3, %t1 ; swapped order
323   ret i1 %t4
326 define i1 @commutative_logical() {
327 ; CHECK-LABEL: @commutative_logical(
328 ; CHECK-NEXT:    [[ARG:%.*]] = call i32 @gen32()
329 ; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
330 ; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
332   %arg = call i32 @gen32()
333   %t1 = icmp sgt i32 %arg, -1
334   %t2 = add i32 %arg, 128
335   %t3 = icmp ult i32 %t2, 256
336   %t4 = select i1 %t3, i1 %t1, i1 false ; swapped order
337   ret i1 %t4
340 define i1 @commutative_with_icmp() {
341 ; CHECK-LABEL: @commutative_with_icmp(
342 ; CHECK-NEXT:    [[ARG:%.*]] = call i32 @gen32()
343 ; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
344 ; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
346   %arg = call i32 @gen32()
347   %t1 = icmp ult i32 %arg, 512
348   %t2 = add i32 %arg, 128
349   %t3 = icmp ult i32 %t2, 256
350   %t4 = and i1 %t3, %t1 ; swapped order
351   ret i1 %t4
354 define i1 @commutative_with_icmp_logical() {
355 ; CHECK-LABEL: @commutative_with_icmp_logical(
356 ; CHECK-NEXT:    [[ARG:%.*]] = call i32 @gen32()
357 ; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
358 ; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
360   %arg = call i32 @gen32()
361   %t1 = icmp ult i32 %arg, 512
362   %t2 = add i32 %arg, 128
363   %t3 = icmp ult i32 %t2, 256
364   %t4 = select i1 %t3, i1 %t1, i1 false ; swapped order
365   ret i1 %t4
368 ; ============================================================================ ;
369 ; Truncations.
370 ; ============================================================================ ;
372 define i1 @positive_trunc_signbit(i32 %arg) {
373 ; CHECK-LABEL: @positive_trunc_signbit(
374 ; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG:%.*]], 128
375 ; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]
377   %t1 = trunc i32 %arg to i8
378   %t2 = icmp sgt i8 %t1, -1
379   %t3 = add i32 %arg, 128
380   %t4 = icmp ult i32 %t3, 256
381   %t5 = and i1 %t2, %t4
382   ret i1 %t5
385 define i1 @positive_trunc_signbit_logical(i32 %arg) {
386 ; CHECK-LABEL: @positive_trunc_signbit_logical(
387 ; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG:%.*]], 128
388 ; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]
390   %t1 = trunc i32 %arg to i8
391   %t2 = icmp sgt i8 %t1, -1
392   %t3 = add i32 %arg, 128
393   %t4 = icmp ult i32 %t3, 256
394   %t5 = select i1 %t2, i1 %t4, i1 false
395   ret i1 %t5
398 define i1 @positive_trunc_base(i32 %arg) {
399 ; CHECK-LABEL: @positive_trunc_base(
400 ; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i16
401 ; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i16 [[T1]], 128
402 ; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]
404   %t1 = trunc i32 %arg to i16
405   %t2 = icmp sgt i16 %t1, -1
406   %t3 = add i16 %t1, 128
407   %t4 = icmp ult i16 %t3, 256
408   %t5 = and i1 %t2, %t4
409   ret i1 %t5
412 define i1 @positive_trunc_base_logical(i32 %arg) {
413 ; CHECK-LABEL: @positive_trunc_base_logical(
414 ; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i16
415 ; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i16 [[T1]], 128
416 ; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]
418   %t1 = trunc i32 %arg to i16
419   %t2 = icmp sgt i16 %t1, -1
420   %t3 = add i16 %t1, 128
421   %t4 = icmp ult i16 %t3, 256
422   %t5 = select i1 %t2, i1 %t4, i1 false
423   ret i1 %t5
426 define i1 @positive_different_trunc_both(i32 %arg) {
427 ; CHECK-LABEL: @positive_different_trunc_both(
428 ; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i15
429 ; CHECK-NEXT:    [[T2:%.*]] = icmp sgt i15 [[T1]], -1
430 ; CHECK-NEXT:    [[T3:%.*]] = trunc i32 [[ARG]] to i16
431 ; CHECK-NEXT:    [[T4:%.*]] = add i16 [[T3]], 128
432 ; CHECK-NEXT:    [[T5:%.*]] = icmp ult i16 [[T4]], 256
433 ; CHECK-NEXT:    [[T6:%.*]] = and i1 [[T2]], [[T5]]
434 ; CHECK-NEXT:    ret i1 [[T6]]
436   %t1 = trunc i32 %arg to i15
437   %t2 = icmp sgt i15 %t1, -1
438   %t3 = trunc i32 %arg to i16
439   %t4 = add i16 %t3, 128
440   %t5 = icmp ult i16 %t4, 256
441   %t6 = and i1 %t2, %t5
442   ret i1 %t6
445 define i1 @positive_different_trunc_both_logical(i32 %arg) {
446 ; CHECK-LABEL: @positive_different_trunc_both_logical(
447 ; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i15
448 ; CHECK-NEXT:    [[T2:%.*]] = icmp sgt i15 [[T1]], -1
449 ; CHECK-NEXT:    [[T3:%.*]] = trunc i32 [[ARG]] to i16
450 ; CHECK-NEXT:    [[T4:%.*]] = add i16 [[T3]], 128
451 ; CHECK-NEXT:    [[T5:%.*]] = icmp ult i16 [[T4]], 256
452 ; CHECK-NEXT:    [[T6:%.*]] = select i1 [[T2]], i1 [[T5]], i1 false
453 ; CHECK-NEXT:    ret i1 [[T6]]
455   %t1 = trunc i32 %arg to i15
456   %t2 = icmp sgt i15 %t1, -1
457   %t3 = trunc i32 %arg to i16
458   %t4 = add i16 %t3, 128
459   %t5 = icmp ult i16 %t4, 256
460   %t6 = select i1 %t2, i1 %t5, i1 false
461   ret i1 %t6
464 ; ============================================================================ ;
465 ; One-use tests.
467 ; We will only produce one instruction, so we do not care about one-use.
468 ; But, we *could* handle more patterns that we weren't able to canonicalize
469 ; because of extra-uses.
470 ; ============================================================================ ;
472 declare void @use32(i32)
473 declare void @use8(i8)
474 declare void @use1(i1)
476 define i1 @oneuse_with_signbit(i32 %arg) {
477 ; CHECK-LABEL: @oneuse_with_signbit(
478 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
479 ; CHECK-NEXT:    call void @use1(i1 [[T1]])
480 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[ARG]], 128
481 ; CHECK-NEXT:    call void @use32(i32 [[T2]])
482 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 256
483 ; CHECK-NEXT:    call void @use1(i1 [[T3]])
484 ; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
485 ; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
487   %t1 = icmp sgt i32 %arg, -1
488   call void @use1(i1 %t1)
489   %t2 = add i32 %arg, 128
490   call void @use32(i32 %t2)
491   %t3 = icmp ult i32 %t2, 256
492   call void @use1(i1 %t3)
493   %t4 = and i1 %t1, %t3
494   ret i1 %t4
497 define i1 @oneuse_with_signbit_logical(i32 %arg) {
498 ; CHECK-LABEL: @oneuse_with_signbit_logical(
499 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
500 ; CHECK-NEXT:    call void @use1(i1 [[T1]])
501 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[ARG]], 128
502 ; CHECK-NEXT:    call void @use32(i32 [[T2]])
503 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 256
504 ; CHECK-NEXT:    call void @use1(i1 [[T3]])
505 ; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
506 ; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
508   %t1 = icmp sgt i32 %arg, -1
509   call void @use1(i1 %t1)
510   %t2 = add i32 %arg, 128
511   call void @use32(i32 %t2)
512   %t3 = icmp ult i32 %t2, 256
513   call void @use1(i1 %t3)
514   %t4 = select i1 %t1, i1 %t3, i1 false
515   ret i1 %t4
518 define i1 @oneuse_with_mask(i32 %arg) {
519 ; CHECK-LABEL: @oneuse_with_mask(
520 ; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 603979776
521 ; CHECK-NEXT:    call void @use32(i32 [[T1]])
522 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
523 ; CHECK-NEXT:    call void @use1(i1 [[T2]])
524 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
525 ; CHECK-NEXT:    call void @use32(i32 [[T3]])
526 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
527 ; CHECK-NEXT:    call void @use1(i1 [[T4]])
528 ; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
529 ; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]
531   %t1 = and i32 %arg, 603979776 ; some bit within the target 4294967168 mask.
532   call void @use32(i32 %t1)
533   %t2 = icmp eq i32 %t1, 0
534   call void @use1(i1 %t2)
535   %t3 = add i32 %arg, 128
536   call void @use32(i32 %t3)
537   %t4 = icmp ult i32 %t3, 256
538   call void @use1(i1 %t4)
539   %t5 = and i1 %t2, %t4
540   ret i1 %t5
543 define i1 @oneuse_with_mask_logical(i32 %arg) {
544 ; CHECK-LABEL: @oneuse_with_mask_logical(
545 ; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 603979776
546 ; CHECK-NEXT:    call void @use32(i32 [[T1]])
547 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
548 ; CHECK-NEXT:    call void @use1(i1 [[T2]])
549 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
550 ; CHECK-NEXT:    call void @use32(i32 [[T3]])
551 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
552 ; CHECK-NEXT:    call void @use1(i1 [[T4]])
553 ; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
554 ; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]
556   %t1 = and i32 %arg, 603979776 ; some bit within the target 4294967168 mask.
557   call void @use32(i32 %t1)
558   %t2 = icmp eq i32 %t1, 0
559   call void @use1(i1 %t2)
560   %t3 = add i32 %arg, 128
561   call void @use32(i32 %t3)
562   %t4 = icmp ult i32 %t3, 256
563   call void @use1(i1 %t4)
564   %t5 = select i1 %t2, i1 %t4, i1 false
565   ret i1 %t5
568 define i1 @oneuse_shl_ashr(i32 %arg) {
569 ; CHECK-LABEL: @oneuse_shl_ashr(
570 ; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i8
571 ; CHECK-NEXT:    call void @use8(i8 [[T1]])
572 ; CHECK-NEXT:    [[T2:%.*]] = icmp sgt i8 [[T1]], -1
573 ; CHECK-NEXT:    call void @use1(i1 [[T2]])
574 ; CHECK-NEXT:    [[T3:%.*]] = shl i32 [[ARG]], 24
575 ; CHECK-NEXT:    call void @use32(i32 [[T3]])
576 ; CHECK-NEXT:    [[T4:%.*]] = ashr exact i32 [[T3]], 24
577 ; CHECK-NEXT:    call void @use32(i32 [[T4]])
578 ; CHECK-NEXT:    [[T5:%.*]] = icmp eq i32 [[T4]], [[ARG]]
579 ; CHECK-NEXT:    call void @use1(i1 [[T5]])
580 ; CHECK-NEXT:    [[T6:%.*]] = and i1 [[T2]], [[T5]]
581 ; CHECK-NEXT:    ret i1 [[T6]]
583   %t1 = trunc i32 %arg to i8
584   call void @use8(i8 %t1)
585   %t2 = icmp sgt i8 %t1, -1
586   call void @use1(i1 %t2)
587   %t3 = shl i32 %arg, 24
588   call void @use32(i32 %t3)
589   %t4 = ashr i32 %t3, 24
590   call void @use32(i32 %t4)
591   %t5 = icmp eq i32 %t4, %arg
592   call void @use1(i1 %t5)
593   %t6 = and i1 %t2, %t5
594   ret i1 %t6
597 define i1 @oneuse_shl_ashr_logical(i32 %arg) {
598 ; CHECK-LABEL: @oneuse_shl_ashr_logical(
599 ; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i8
600 ; CHECK-NEXT:    call void @use8(i8 [[T1]])
601 ; CHECK-NEXT:    [[T2:%.*]] = icmp sgt i8 [[T1]], -1
602 ; CHECK-NEXT:    call void @use1(i1 [[T2]])
603 ; CHECK-NEXT:    [[T3:%.*]] = shl i32 [[ARG]], 24
604 ; CHECK-NEXT:    call void @use32(i32 [[T3]])
605 ; CHECK-NEXT:    [[T4:%.*]] = ashr exact i32 [[T3]], 24
606 ; CHECK-NEXT:    call void @use32(i32 [[T4]])
607 ; CHECK-NEXT:    [[T5:%.*]] = icmp eq i32 [[T4]], [[ARG]]
608 ; CHECK-NEXT:    call void @use1(i1 [[T5]])
609 ; CHECK-NEXT:    [[T6:%.*]] = select i1 [[T2]], i1 [[T5]], i1 false
610 ; CHECK-NEXT:    ret i1 [[T6]]
612   %t1 = trunc i32 %arg to i8
613   call void @use8(i8 %t1)
614   %t2 = icmp sgt i8 %t1, -1
615   call void @use1(i1 %t2)
616   %t3 = shl i32 %arg, 24
617   call void @use32(i32 %t3)
618   %t4 = ashr i32 %t3, 24
619   call void @use32(i32 %t4)
620   %t5 = icmp eq i32 %t4, %arg
621   call void @use1(i1 %t5)
622   %t6 = select i1 %t2, i1 %t5, i1 false
623   ret i1 %t6
626 define zeroext i1 @oneuse_trunc_sext(i32 %arg) {
627 ; CHECK-LABEL: @oneuse_trunc_sext(
628 ; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i8
629 ; CHECK-NEXT:    call void @use8(i8 [[T1]])
630 ; CHECK-NEXT:    [[T2:%.*]] = icmp sgt i8 [[T1]], -1
631 ; CHECK-NEXT:    call void @use1(i1 [[T2]])
632 ; CHECK-NEXT:    [[T3:%.*]] = trunc i32 [[ARG]] to i8
633 ; CHECK-NEXT:    call void @use8(i8 [[T3]])
634 ; CHECK-NEXT:    [[T4:%.*]] = sext i8 [[T3]] to i32
635 ; CHECK-NEXT:    call void @use32(i32 [[T4]])
636 ; CHECK-NEXT:    [[T5:%.*]] = icmp eq i32 [[T4]], [[ARG]]
637 ; CHECK-NEXT:    call void @use1(i1 [[T5]])
638 ; CHECK-NEXT:    [[T6:%.*]] = and i1 [[T2]], [[T5]]
639 ; CHECK-NEXT:    ret i1 [[T6]]
641   %t1 = trunc i32 %arg to i8
642   call void @use8(i8 %t1)
643   %t2 = icmp sgt i8 %t1, -1
644   call void @use1(i1 %t2)
645   %t3 = trunc i32 %arg to i8
646   call void @use8(i8 %t3)
647   %t4 = sext i8 %t3 to i32
648   call void @use32(i32 %t4)
649   %t5 = icmp eq i32 %t4, %arg
650   call void @use1(i1 %t5)
651   %t6 = and i1 %t2, %t5
652   ret i1 %t6
655 define zeroext i1 @oneuse_trunc_sext_logical(i32 %arg) {
656 ; CHECK-LABEL: @oneuse_trunc_sext_logical(
657 ; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i8
658 ; CHECK-NEXT:    call void @use8(i8 [[T1]])
659 ; CHECK-NEXT:    [[T2:%.*]] = icmp sgt i8 [[T1]], -1
660 ; CHECK-NEXT:    call void @use1(i1 [[T2]])
661 ; CHECK-NEXT:    [[T3:%.*]] = trunc i32 [[ARG]] to i8
662 ; CHECK-NEXT:    call void @use8(i8 [[T3]])
663 ; CHECK-NEXT:    [[T4:%.*]] = sext i8 [[T3]] to i32
664 ; CHECK-NEXT:    call void @use32(i32 [[T4]])
665 ; CHECK-NEXT:    [[T5:%.*]] = icmp eq i32 [[T4]], [[ARG]]
666 ; CHECK-NEXT:    call void @use1(i1 [[T5]])
667 ; CHECK-NEXT:    [[T6:%.*]] = select i1 [[T2]], i1 [[T5]], i1 false
668 ; CHECK-NEXT:    ret i1 [[T6]]
670   %t1 = trunc i32 %arg to i8
671   call void @use8(i8 %t1)
672   %t2 = icmp sgt i8 %t1, -1
673   call void @use1(i1 %t2)
674   %t3 = trunc i32 %arg to i8
675   call void @use8(i8 %t3)
676   %t4 = sext i8 %t3 to i32
677   call void @use32(i32 %t4)
678   %t5 = icmp eq i32 %t4, %arg
679   call void @use1(i1 %t5)
680   %t6 = select i1 %t2, i1 %t5, i1 false
681   ret i1 %t6
684 ; ============================================================================ ;
685 ; Negative tests
686 ; ============================================================================ ;
688 define i1 @negative_not_arg(i32 %arg, i32 %arg2) {
689 ; CHECK-LABEL: @negative_not_arg(
690 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
691 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[ARG2:%.*]], 128
692 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 256
693 ; CHECK-NEXT:    [[T4:%.*]] = and i1 [[T1]], [[T3]]
694 ; CHECK-NEXT:    ret i1 [[T4]]
696   %t1 = icmp sgt i32 %arg, -1
697   %t2 = add i32 %arg2, 128 ; not %arg
698   %t3 = icmp ult i32 %t2, 256
699   %t4 = and i1 %t1, %t3
700   ret i1 %t4
703 define i1 @negative_not_arg_logical(i32 %arg, i32 %arg2) {
704 ; CHECK-LABEL: @negative_not_arg_logical(
705 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
706 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[ARG2:%.*]], 128
707 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 256
708 ; CHECK-NEXT:    [[T4:%.*]] = select i1 [[T1]], i1 [[T3]], i1 false
709 ; CHECK-NEXT:    ret i1 [[T4]]
711   %t1 = icmp sgt i32 %arg, -1
712   %t2 = add i32 %arg2, 128 ; not %arg
713   %t3 = icmp ult i32 %t2, 256
714   %t4 = select i1 %t1, i1 %t3, i1 false
715   ret i1 %t4
718 define i1 @negative_trunc_not_arg(i32 %arg, i32 %arg2) {
719 ; CHECK-LABEL: @negative_trunc_not_arg(
720 ; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i8
721 ; CHECK-NEXT:    [[T2:%.*]] = icmp sgt i8 [[T1]], -1
722 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG2:%.*]], 128
723 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
724 ; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
725 ; CHECK-NEXT:    ret i1 [[T5]]
727   %t1 = trunc i32 %arg to i8
728   %t2 = icmp sgt i8 %t1, -1
729   %t3 = add i32 %arg2, 128 ; not %arg
730   %t4 = icmp ult i32 %t3, 256
731   %t5 = and i1 %t2, %t4
732   ret i1 %t5
735 define i1 @negative_trunc_not_arg_logical(i32 %arg, i32 %arg2) {
736 ; CHECK-LABEL: @negative_trunc_not_arg_logical(
737 ; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i8
738 ; CHECK-NEXT:    [[T2:%.*]] = icmp sgt i8 [[T1]], -1
739 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG2:%.*]], 128
740 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
741 ; CHECK-NEXT:    [[T5:%.*]] = select i1 [[T2]], i1 [[T4]], i1 false
742 ; CHECK-NEXT:    ret i1 [[T5]]
744   %t1 = trunc i32 %arg to i8
745   %t2 = icmp sgt i8 %t1, -1
746   %t3 = add i32 %arg2, 128 ; not %arg
747   %t4 = icmp ult i32 %t3, 256
748   %t5 = select i1 %t2, i1 %t4, i1 false
749   ret i1 %t5
752 define i1 @positive_with_mask_not_arg(i32 %arg, i32 %arg2) {
753 ; CHECK-LABEL: @positive_with_mask_not_arg(
754 ; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 1140850688
755 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
756 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG2:%.*]], 128
757 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
758 ; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
759 ; CHECK-NEXT:    ret i1 [[T5]]
761   %t1 = and i32 %arg, 1140850688
762   %t2 = icmp eq i32 %t1, 0
763   %t3 = add i32 %arg2, 128 ; not %arg
764   %t4 = icmp ult i32 %t3, 256
765   %t5 = and i1 %t2, %t4
766   ret i1 %t5
769 define i1 @positive_with_mask_not_arg_logical(i32 %arg, i32 %arg2) {
770 ; CHECK-LABEL: @positive_with_mask_not_arg_logical(
771 ; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 1140850688
772 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
773 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG2:%.*]], 128
774 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
775 ; CHECK-NEXT:    [[T5:%.*]] = select i1 [[T2]], i1 [[T4]], i1 false
776 ; CHECK-NEXT:    ret i1 [[T5]]
778   %t1 = and i32 %arg, 1140850688
779   %t2 = icmp eq i32 %t1, 0
780   %t3 = add i32 %arg2, 128 ; not %arg
781   %t4 = icmp ult i32 %t3, 256
782   %t5 = select i1 %t2, i1 %t4, i1 false
783   ret i1 %t5
786 define i1 @negative_with_nonuniform_bad_mask(i32 %arg) {
787 ; CHECK-LABEL: @negative_with_nonuniform_bad_mask(
788 ; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 1711276033
789 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
790 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
791 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
792 ; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
793 ; CHECK-NEXT:    ret i1 [[T5]]
795   %t1 = and i32 %arg, 1711276033 ; lowest bit is set
796   %t2 = icmp eq i32 %t1, 0
797   %t3 = add i32 %arg, 128
798   %t4 = icmp ult i32 %t3, 256
799   %t5 = and i1 %t2, %t4
800   ret i1 %t5
803 define i1 @negative_with_nonuniform_bad_mask_logical(i32 %arg) {
804 ; CHECK-LABEL: @negative_with_nonuniform_bad_mask_logical(
805 ; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 1711276033
806 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
807 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
808 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
809 ; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
810 ; CHECK-NEXT:    ret i1 [[T5]]
812   %t1 = and i32 %arg, 1711276033 ; lowest bit is set
813   %t2 = icmp eq i32 %t1, 0
814   %t3 = add i32 %arg, 128
815   %t4 = icmp ult i32 %t3, 256
816   %t5 = select i1 %t2, i1 %t4, i1 false
817   ret i1 %t5
820 define i1 @negative_with_uniform_bad_mask(i32 %arg) {
821 ; CHECK-LABEL: @negative_with_uniform_bad_mask(
822 ; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], -16777152
823 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
824 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
825 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
826 ; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
827 ; CHECK-NEXT:    ret i1 [[T5]]
829   %t1 = and i32 %arg, 4278190144 ; 7'th bit is set
830   %t2 = icmp eq i32 %t1, 0
831   %t3 = add i32 %arg, 128
832   %t4 = icmp ult i32 %t3, 256
833   %t5 = and i1 %t2, %t4
834   ret i1 %t5
837 define i1 @negative_with_uniform_bad_mask_logical(i32 %arg) {
838 ; CHECK-LABEL: @negative_with_uniform_bad_mask_logical(
839 ; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], -16777152
840 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
841 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
842 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
843 ; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
844 ; CHECK-NEXT:    ret i1 [[T5]]
846   %t1 = and i32 %arg, 4278190144 ; 7'th bit is set
847   %t2 = icmp eq i32 %t1, 0
848   %t3 = add i32 %arg, 128
849   %t4 = icmp ult i32 %t3, 256
850   %t5 = select i1 %t2, i1 %t4, i1 false
851   ret i1 %t5
854 define i1 @negative_with_wrong_mask(i32 %arg) {
855 ; CHECK-LABEL: @negative_with_wrong_mask(
856 ; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 1
857 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
858 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
859 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
860 ; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
861 ; CHECK-NEXT:    ret i1 [[T5]]
863   %t1 = and i32 %arg, 1 ; not even checking the right mask
864   %t2 = icmp eq i32 %t1, 0
865   %t3 = add i32 %arg, 128
866   %t4 = icmp ult i32 %t3, 256
867   %t5 = and i1 %t2, %t4
868   ret i1 %t5
871 define i1 @negative_with_wrong_mask_logical(i32 %arg) {
872 ; CHECK-LABEL: @negative_with_wrong_mask_logical(
873 ; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 1
874 ; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
875 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
876 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
877 ; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
878 ; CHECK-NEXT:    ret i1 [[T5]]
880   %t1 = and i32 %arg, 1 ; not even checking the right mask
881   %t2 = icmp eq i32 %t1, 0
882   %t3 = add i32 %arg, 128
883   %t4 = icmp ult i32 %t3, 256
884   %t5 = select i1 %t2, i1 %t4, i1 false
885   ret i1 %t5
888 define i1 @negative_not_less_than(i32 %arg) {
889 ; CHECK-LABEL: @negative_not_less_than(
890 ; CHECK-NEXT:    ret i1 false
892   %t1 = icmp sgt i32 %arg, -1
893   %t2 = add i32 %arg, 256 ; should be less than 256
894   %t3 = icmp ult i32 %t2, 256
895   %t4 = and i1 %t1, %t3
896   ret i1 %t4
899 define i1 @negative_not_less_than_logical(i32 %arg) {
900 ; CHECK-LABEL: @negative_not_less_than_logical(
901 ; CHECK-NEXT:    ret i1 false
903   %t1 = icmp sgt i32 %arg, -1
904   %t2 = add i32 %arg, 256 ; should be less than 256
905   %t3 = icmp ult i32 %t2, 256
906   %t4 = select i1 %t1, i1 %t3, i1 false
907   ret i1 %t4
910 define i1 @negative_not_power_of_two(i32 %arg) {
911 ; CHECK-LABEL: @negative_not_power_of_two(
912 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
913 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[ARG]], 255
914 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 256
915 ; CHECK-NEXT:    [[T4:%.*]] = and i1 [[T1]], [[T3]]
916 ; CHECK-NEXT:    ret i1 [[T4]]
918   %t1 = icmp sgt i32 %arg, -1
919   %t2 = add i32 %arg, 255 ; should be power of two
920   %t3 = icmp ult i32 %t2, 256
921   %t4 = and i1 %t1, %t3
922   ret i1 %t4
925 define i1 @negative_not_power_of_two_logical(i32 %arg) {
926 ; CHECK-LABEL: @negative_not_power_of_two_logical(
927 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
928 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[ARG]], 255
929 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 256
930 ; CHECK-NEXT:    [[T4:%.*]] = and i1 [[T1]], [[T3]]
931 ; CHECK-NEXT:    ret i1 [[T4]]
933   %t1 = icmp sgt i32 %arg, -1
934   %t2 = add i32 %arg, 255 ; should be power of two
935   %t3 = icmp ult i32 %t2, 256
936   %t4 = select i1 %t1, i1 %t3, i1 false
937   ret i1 %t4
940 define i1 @negative_not_next_power_of_two(i32 %arg) {
941 ; CHECK-LABEL: @negative_not_next_power_of_two(
942 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
943 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[ARG]], 64
944 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 256
945 ; CHECK-NEXT:    [[T4:%.*]] = and i1 [[T1]], [[T3]]
946 ; CHECK-NEXT:    ret i1 [[T4]]
948   %t1 = icmp sgt i32 %arg, -1
949   %t2 = add i32 %arg, 64 ; should be 256 >> 1
950   %t3 = icmp ult i32 %t2, 256
951   %t4 = and i1 %t1, %t3
952   ret i1 %t4
955 define i1 @negative_not_next_power_of_two_logical(i32 %arg) {
956 ; CHECK-LABEL: @negative_not_next_power_of_two_logical(
957 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
958 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[ARG]], 64
959 ; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 256
960 ; CHECK-NEXT:    [[T4:%.*]] = and i1 [[T1]], [[T3]]
961 ; CHECK-NEXT:    ret i1 [[T4]]
963   %t1 = icmp sgt i32 %arg, -1
964   %t2 = add i32 %arg, 64 ; should be 256 >> 1
965   %t3 = icmp ult i32 %t2, 256
966   %t4 = select i1 %t1, i1 %t3, i1 false
967   ret i1 %t4
970 ; I don't think this can be folded, at least not into single instruction.
971 define i1 @two_signed_truncation_checks(i32 %arg) {
972 ; CHECK-LABEL: @two_signed_truncation_checks(
973 ; CHECK-NEXT:    [[T1:%.*]] = add i32 [[ARG:%.*]], 512
974 ; CHECK-NEXT:    [[T2:%.*]] = icmp ult i32 [[T1]], 1024
975 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
976 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
977 ; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
978 ; CHECK-NEXT:    ret i1 [[T5]]
980   %t1 = add i32 %arg, 512
981   %t2 = icmp ult i32 %t1, 1024
982   %t3 = add i32 %arg, 128
983   %t4 = icmp ult i32 %t3, 256
984   %t5 = and i1 %t2, %t4
985   ret i1 %t5
988 define i1 @two_signed_truncation_checks_logical(i32 %arg) {
989 ; CHECK-LABEL: @two_signed_truncation_checks_logical(
990 ; CHECK-NEXT:    [[T1:%.*]] = add i32 [[ARG:%.*]], 512
991 ; CHECK-NEXT:    [[T2:%.*]] = icmp ult i32 [[T1]], 1024
992 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
993 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
994 ; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
995 ; CHECK-NEXT:    ret i1 [[T5]]
997   %t1 = add i32 %arg, 512
998   %t2 = icmp ult i32 %t1, 1024
999   %t3 = add i32 %arg, 128
1000   %t4 = icmp ult i32 %t3, 256
1001   %t5 = select i1 %t2, i1 %t4, i1 false
1002   ret i1 %t5
1005 define i1 @bad_trunc_stc(i32 %arg) {
1006 ; CHECK-LABEL: @bad_trunc_stc(
1007 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
1008 ; CHECK-NEXT:    [[T2:%.*]] = trunc i32 [[ARG]] to i16
1009 ; CHECK-NEXT:    [[T3:%.*]] = add i16 [[T2]], 128
1010 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i16 [[T3]], 256
1011 ; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T1]], [[T4]]
1012 ; CHECK-NEXT:    ret i1 [[T5]]
1014   %t1 = icmp sgt i32 %arg, -1 ; checks a bit outside of the i16
1015   %t2 = trunc i32 %arg to i16
1016   %t3 = add i16 %t2, 128
1017   %t4 = icmp ult i16 %t3, 256
1018   %t5 = and i1 %t1, %t4
1019   ret i1 %t5
1022 define i1 @bad_trunc_stc_logical(i32 %arg) {
1023 ; CHECK-LABEL: @bad_trunc_stc_logical(
1024 ; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
1025 ; CHECK-NEXT:    [[T2:%.*]] = trunc i32 [[ARG]] to i16
1026 ; CHECK-NEXT:    [[T3:%.*]] = add i16 [[T2]], 128
1027 ; CHECK-NEXT:    [[T4:%.*]] = icmp ult i16 [[T3]], 256
1028 ; CHECK-NEXT:    [[T5:%.*]] = select i1 [[T1]], i1 [[T4]], i1 false
1029 ; CHECK-NEXT:    ret i1 [[T5]]
1031   %t1 = icmp sgt i32 %arg, -1 ; checks a bit outside of the i16
1032   %t2 = trunc i32 %arg to i16
1033   %t3 = add i16 %t2, 128
1034   %t4 = icmp ult i16 %t3, 256
1035   %t5 = select i1 %t1, i1 %t4, i1 false
1036   ret i1 %t5