xref: /llvm-project/llvm/test/Transforms/InstCombine/signed-truncation-check.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4; General pattern:
5;   X & Y
6;
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.
21;
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
28;
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
34
35; ============================================================================ ;
36; Basic positive test
37; ============================================================================ ;
38
39define 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]]
43;
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
49}
50
51define 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]]
55;
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
61}
62
63define 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]]
67;
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
74}
75
76define 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]]
80;
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
87}
88
89define 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]]
93;
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
99}
100
101define 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]]
105;
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
111}
112
113; Still the same
114define 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]]
118;
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
124}
125
126define 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]]
130;
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
136}
137
138; I'm sure there is a bunch more patterns possible :/
139
140; This used to trigger an assert, because the icmp's are not direct
141; operands of the and.
142define 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:    [[T5:%.*]] = and i1 [[T5_SIMPLIFIED]], [[Z:%.*]]
146; CHECK-NEXT:    ret i1 [[T5]]
147;
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
154}
155
156define 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]]
161;
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
168}
169
170; ============================================================================ ;
171; Vector tests
172; ============================================================================ ;
173
174define <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:%.*]], splat (i32 128)
177; CHECK-NEXT:    ret <2 x i1> [[T4_SIMPLIFIED]]
178;
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
184}
185
186define <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:%.*]], splat (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]]
193;
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
199}
200
201define <3 x i1> @positive_vec_poison0(<3 x i32> %arg) {
202; CHECK-LABEL: @positive_vec_poison0(
203; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult <3 x i32> [[ARG:%.*]], splat (i32 128)
204; CHECK-NEXT:    ret <3 x i1> [[T4_SIMPLIFIED]]
205;
206  %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 poison, i32 -1>
207  %t2 = add <3 x i32> %arg, <i32 128, i32 128, i32 128>
208  %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 256, i32 256>
209  %t4 = and <3 x i1> %t1, %t3
210  ret <3 x i1> %t4
211}
212
213define <3 x i1> @positive_vec_poison1(<3 x i32> %arg) {
214; CHECK-LABEL: @positive_vec_poison1(
215; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult <3 x i32> [[ARG:%.*]], splat (i32 128)
216; CHECK-NEXT:    ret <3 x i1> [[T4_SIMPLIFIED]]
217;
218  %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 -1, i32 -1>
219  %t2 = add <3 x i32> %arg, <i32 128, i32 poison, i32 128>
220  %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 256, i32 256>
221  %t4 = and <3 x i1> %t1, %t3
222  ret <3 x i1> %t4
223}
224
225define <3 x i1> @positive_vec_poison2(<3 x i32> %arg) {
226; CHECK-LABEL: @positive_vec_poison2(
227; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult <3 x i32> [[ARG:%.*]], splat (i32 128)
228; CHECK-NEXT:    ret <3 x i1> [[T4_SIMPLIFIED]]
229;
230  %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 -1, i32 -1>
231  %t2 = add <3 x i32> %arg, <i32 128, i32 128, i32 128>
232  %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 poison, i32 256>
233  %t4 = and <3 x i1> %t1, %t3
234  ret <3 x i1> %t4
235}
236
237define <3 x i1> @positive_vec_poison3(<3 x i32> %arg) {
238; CHECK-LABEL: @positive_vec_poison3(
239; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult <3 x i32> [[ARG:%.*]], splat (i32 128)
240; CHECK-NEXT:    ret <3 x i1> [[T4_SIMPLIFIED]]
241;
242  %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 poison, i32 -1>
243  %t2 = add <3 x i32> %arg, <i32 128, i32 poison, i32 128>
244  %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 256, i32 256>
245  %t4 = and <3 x i1> %t1, %t3
246  ret <3 x i1> %t4
247}
248
249define <3 x i1> @positive_vec_poison4(<3 x i32> %arg) {
250; CHECK-LABEL: @positive_vec_poison4(
251; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult <3 x i32> [[ARG:%.*]], splat (i32 128)
252; CHECK-NEXT:    ret <3 x i1> [[T4_SIMPLIFIED]]
253;
254  %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 poison, i32 -1>
255  %t2 = add <3 x i32> %arg, <i32 128, i32 128, i32 128>
256  %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 poison, i32 256>
257  %t4 = and <3 x i1> %t1, %t3
258  ret <3 x i1> %t4
259}
260
261define <3 x i1> @positive_vec_poison5(<3 x i32> %arg) {
262; CHECK-LABEL: @positive_vec_poison5(
263; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult <3 x i32> [[ARG:%.*]], splat (i32 128)
264; CHECK-NEXT:    ret <3 x i1> [[T4_SIMPLIFIED]]
265;
266  %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 -1, i32 -1>
267  %t2 = add <3 x i32> %arg, <i32 128, i32 poison, i32 128>
268  %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 poison, i32 256>
269  %t4 = and <3 x i1> %t1, %t3
270  ret <3 x i1> %t4
271}
272
273define <3 x i1> @positive_vec_poison6(<3 x i32> %arg) {
274; CHECK-LABEL: @positive_vec_poison6(
275; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult <3 x i32> [[ARG:%.*]], splat (i32 128)
276; CHECK-NEXT:    ret <3 x i1> [[T4_SIMPLIFIED]]
277;
278  %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 poison, i32 -1>
279  %t2 = add <3 x i32> %arg, <i32 128, i32 poison, i32 128>
280  %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 poison, i32 256>
281  %t4 = and <3 x i1> %t1, %t3
282  ret <3 x i1> %t4
283}
284
285; ============================================================================ ;
286; Commutativity tests.
287; ============================================================================ ;
288
289declare i32 @gen32()
290
291define i1 @commutative() {
292; CHECK-LABEL: @commutative(
293; CHECK-NEXT:    [[ARG:%.*]] = call i32 @gen32()
294; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
295; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
296;
297  %arg = call i32 @gen32()
298  %t1 = icmp sgt i32 %arg, -1
299  %t2 = add i32 %arg, 128
300  %t3 = icmp ult i32 %t2, 256
301  %t4 = and i1 %t3, %t1 ; swapped order
302  ret i1 %t4
303}
304
305define i1 @commutative_logical() {
306; CHECK-LABEL: @commutative_logical(
307; CHECK-NEXT:    [[ARG:%.*]] = call i32 @gen32()
308; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
309; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
310;
311  %arg = call i32 @gen32()
312  %t1 = icmp sgt i32 %arg, -1
313  %t2 = add i32 %arg, 128
314  %t3 = icmp ult i32 %t2, 256
315  %t4 = select i1 %t3, i1 %t1, i1 false ; swapped order
316  ret i1 %t4
317}
318
319define i1 @commutative_with_icmp() {
320; CHECK-LABEL: @commutative_with_icmp(
321; CHECK-NEXT:    [[ARG:%.*]] = call i32 @gen32()
322; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
323; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
324;
325  %arg = call i32 @gen32()
326  %t1 = icmp ult i32 %arg, 512
327  %t2 = add i32 %arg, 128
328  %t3 = icmp ult i32 %t2, 256
329  %t4 = and i1 %t3, %t1 ; swapped order
330  ret i1 %t4
331}
332
333define i1 @commutative_with_icmp_logical() {
334; CHECK-LABEL: @commutative_with_icmp_logical(
335; CHECK-NEXT:    [[ARG:%.*]] = call i32 @gen32()
336; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
337; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
338;
339  %arg = call i32 @gen32()
340  %t1 = icmp ult i32 %arg, 512
341  %t2 = add i32 %arg, 128
342  %t3 = icmp ult i32 %t2, 256
343  %t4 = select i1 %t3, i1 %t1, i1 false ; swapped order
344  ret i1 %t4
345}
346
347; ============================================================================ ;
348; Truncations.
349; ============================================================================ ;
350
351define i1 @positive_trunc_signbit(i32 %arg) {
352; CHECK-LABEL: @positive_trunc_signbit(
353; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG:%.*]], 128
354; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]
355;
356  %t1 = trunc i32 %arg to i8
357  %t2 = icmp sgt i8 %t1, -1
358  %t3 = add i32 %arg, 128
359  %t4 = icmp ult i32 %t3, 256
360  %t5 = and i1 %t2, %t4
361  ret i1 %t5
362}
363
364define i1 @positive_trunc_signbit_logical(i32 %arg) {
365; CHECK-LABEL: @positive_trunc_signbit_logical(
366; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG:%.*]], 128
367; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]
368;
369  %t1 = trunc i32 %arg to i8
370  %t2 = icmp sgt i8 %t1, -1
371  %t3 = add i32 %arg, 128
372  %t4 = icmp ult i32 %t3, 256
373  %t5 = select i1 %t2, i1 %t4, i1 false
374  ret i1 %t5
375}
376
377define i1 @positive_trunc_base(i32 %arg) {
378; CHECK-LABEL: @positive_trunc_base(
379; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARG:%.*]], 65408
380; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp eq i32 [[TMP1]], 0
381; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]
382;
383  %t1 = trunc i32 %arg to i16
384  %t2 = icmp sgt i16 %t1, -1
385  %t3 = add i16 %t1, 128
386  %t4 = icmp ult i16 %t3, 256
387  %t5 = and i1 %t2, %t4
388  ret i1 %t5
389}
390
391define i1 @positive_trunc_base_logical(i32 %arg) {
392; CHECK-LABEL: @positive_trunc_base_logical(
393; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARG:%.*]], 65408
394; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp eq i32 [[TMP1]], 0
395; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]
396;
397  %t1 = trunc i32 %arg to i16
398  %t2 = icmp sgt i16 %t1, -1
399  %t3 = add i16 %t1, 128
400  %t4 = icmp ult i16 %t3, 256
401  %t5 = select i1 %t2, i1 %t4, i1 false
402  ret i1 %t5
403}
404
405define i1 @positive_different_trunc_both(i32 %arg) {
406; CHECK-LABEL: @positive_different_trunc_both(
407; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARG:%.*]], 16384
408; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[TMP1]], 0
409; CHECK-NEXT:    [[T3:%.*]] = trunc i32 [[ARG]] to i16
410; CHECK-NEXT:    [[T4:%.*]] = add i16 [[T3]], 128
411; CHECK-NEXT:    [[T5:%.*]] = icmp ult i16 [[T4]], 256
412; CHECK-NEXT:    [[T6:%.*]] = and i1 [[T2]], [[T5]]
413; CHECK-NEXT:    ret i1 [[T6]]
414;
415  %t1 = trunc i32 %arg to i15
416  %t2 = icmp sgt i15 %t1, -1
417  %t3 = trunc i32 %arg to i16
418  %t4 = add i16 %t3, 128
419  %t5 = icmp ult i16 %t4, 256
420  %t6 = and i1 %t2, %t5
421  ret i1 %t6
422}
423
424define i1 @positive_different_trunc_both_logical(i32 %arg) {
425; CHECK-LABEL: @positive_different_trunc_both_logical(
426; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARG:%.*]], 16384
427; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[TMP1]], 0
428; CHECK-NEXT:    [[T3:%.*]] = trunc i32 [[ARG]] to i16
429; CHECK-NEXT:    [[T4:%.*]] = add i16 [[T3]], 128
430; CHECK-NEXT:    [[T5:%.*]] = icmp ult i16 [[T4]], 256
431; CHECK-NEXT:    [[T6:%.*]] = select i1 [[T2]], i1 [[T5]], i1 false
432; CHECK-NEXT:    ret i1 [[T6]]
433;
434  %t1 = trunc i32 %arg to i15
435  %t2 = icmp sgt i15 %t1, -1
436  %t3 = trunc i32 %arg to i16
437  %t4 = add i16 %t3, 128
438  %t5 = icmp ult i16 %t4, 256
439  %t6 = select i1 %t2, i1 %t5, i1 false
440  ret i1 %t6
441}
442
443; ============================================================================ ;
444; One-use tests.
445;
446; We will only produce one instruction, so we do not care about one-use.
447; But, we *could* handle more patterns that we weren't able to canonicalize
448; because of extra-uses.
449; ============================================================================ ;
450
451declare void @use32(i32)
452declare void @use8(i8)
453declare void @use1(i1)
454
455define i1 @oneuse_with_signbit(i32 %arg) {
456; CHECK-LABEL: @oneuse_with_signbit(
457; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
458; CHECK-NEXT:    call void @use1(i1 [[T1]])
459; CHECK-NEXT:    [[T2:%.*]] = add i32 [[ARG]], 128
460; CHECK-NEXT:    call void @use32(i32 [[T2]])
461; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 256
462; CHECK-NEXT:    call void @use1(i1 [[T3]])
463; CHECK-NEXT:    [[T4_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
464; CHECK-NEXT:    ret i1 [[T4_SIMPLIFIED]]
465;
466  %t1 = icmp sgt i32 %arg, -1
467  call void @use1(i1 %t1)
468  %t2 = add i32 %arg, 128
469  call void @use32(i32 %t2)
470  %t3 = icmp ult i32 %t2, 256
471  call void @use1(i1 %t3)
472  %t4 = and i1 %t1, %t3
473  ret i1 %t4
474}
475
476define i1 @oneuse_with_signbit_logical(i32 %arg) {
477; CHECK-LABEL: @oneuse_with_signbit_logical(
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]]
486;
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 = select i1 %t1, i1 %t3, i1 false
494  ret i1 %t4
495}
496
497define i1 @oneuse_with_mask(i32 %arg) {
498; CHECK-LABEL: @oneuse_with_mask(
499; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 603979776
500; CHECK-NEXT:    call void @use32(i32 [[T1]])
501; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
502; CHECK-NEXT:    call void @use1(i1 [[T2]])
503; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
504; CHECK-NEXT:    call void @use32(i32 [[T3]])
505; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
506; CHECK-NEXT:    call void @use1(i1 [[T4]])
507; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
508; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]
509;
510  %t1 = and i32 %arg, 603979776 ; some bit within the target 4294967168 mask.
511  call void @use32(i32 %t1)
512  %t2 = icmp eq i32 %t1, 0
513  call void @use1(i1 %t2)
514  %t3 = add i32 %arg, 128
515  call void @use32(i32 %t3)
516  %t4 = icmp ult i32 %t3, 256
517  call void @use1(i1 %t4)
518  %t5 = and i1 %t2, %t4
519  ret i1 %t5
520}
521
522define i1 @oneuse_with_mask_logical(i32 %arg) {
523; CHECK-LABEL: @oneuse_with_mask_logical(
524; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 603979776
525; CHECK-NEXT:    call void @use32(i32 [[T1]])
526; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
527; CHECK-NEXT:    call void @use1(i1 [[T2]])
528; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
529; CHECK-NEXT:    call void @use32(i32 [[T3]])
530; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
531; CHECK-NEXT:    call void @use1(i1 [[T4]])
532; CHECK-NEXT:    [[T5_SIMPLIFIED:%.*]] = icmp ult i32 [[ARG]], 128
533; CHECK-NEXT:    ret i1 [[T5_SIMPLIFIED]]
534;
535  %t1 = and i32 %arg, 603979776 ; some bit within the target 4294967168 mask.
536  call void @use32(i32 %t1)
537  %t2 = icmp eq i32 %t1, 0
538  call void @use1(i1 %t2)
539  %t3 = add i32 %arg, 128
540  call void @use32(i32 %t3)
541  %t4 = icmp ult i32 %t3, 256
542  call void @use1(i1 %t4)
543  %t5 = select i1 %t2, i1 %t4, i1 false
544  ret i1 %t5
545}
546
547define i1 @oneuse_shl_ashr(i32 %arg) {
548; CHECK-LABEL: @oneuse_shl_ashr(
549; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i8
550; CHECK-NEXT:    call void @use8(i8 [[T1]])
551; CHECK-NEXT:    [[T2:%.*]] = icmp sgt i8 [[T1]], -1
552; CHECK-NEXT:    call void @use1(i1 [[T2]])
553; CHECK-NEXT:    [[T3:%.*]] = shl i32 [[ARG]], 24
554; CHECK-NEXT:    call void @use32(i32 [[T3]])
555; CHECK-NEXT:    [[T4:%.*]] = ashr exact i32 [[T3]], 24
556; CHECK-NEXT:    call void @use32(i32 [[T4]])
557; CHECK-NEXT:    [[T5:%.*]] = icmp eq i32 [[T4]], [[ARG]]
558; CHECK-NEXT:    call void @use1(i1 [[T5]])
559; CHECK-NEXT:    [[T6:%.*]] = and i1 [[T2]], [[T5]]
560; CHECK-NEXT:    ret i1 [[T6]]
561;
562  %t1 = trunc i32 %arg to i8
563  call void @use8(i8 %t1)
564  %t2 = icmp sgt i8 %t1, -1
565  call void @use1(i1 %t2)
566  %t3 = shl i32 %arg, 24
567  call void @use32(i32 %t3)
568  %t4 = ashr i32 %t3, 24
569  call void @use32(i32 %t4)
570  %t5 = icmp eq i32 %t4, %arg
571  call void @use1(i1 %t5)
572  %t6 = and i1 %t2, %t5
573  ret i1 %t6
574}
575
576define i1 @oneuse_shl_ashr_logical(i32 %arg) {
577; CHECK-LABEL: @oneuse_shl_ashr_logical(
578; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i8
579; CHECK-NEXT:    call void @use8(i8 [[T1]])
580; CHECK-NEXT:    [[T2:%.*]] = icmp sgt i8 [[T1]], -1
581; CHECK-NEXT:    call void @use1(i1 [[T2]])
582; CHECK-NEXT:    [[T3:%.*]] = shl i32 [[ARG]], 24
583; CHECK-NEXT:    call void @use32(i32 [[T3]])
584; CHECK-NEXT:    [[T4:%.*]] = ashr exact i32 [[T3]], 24
585; CHECK-NEXT:    call void @use32(i32 [[T4]])
586; CHECK-NEXT:    [[T5:%.*]] = icmp eq i32 [[T4]], [[ARG]]
587; CHECK-NEXT:    call void @use1(i1 [[T5]])
588; CHECK-NEXT:    [[T6:%.*]] = select i1 [[T2]], i1 [[T5]], i1 false
589; CHECK-NEXT:    ret i1 [[T6]]
590;
591  %t1 = trunc i32 %arg to i8
592  call void @use8(i8 %t1)
593  %t2 = icmp sgt i8 %t1, -1
594  call void @use1(i1 %t2)
595  %t3 = shl i32 %arg, 24
596  call void @use32(i32 %t3)
597  %t4 = ashr i32 %t3, 24
598  call void @use32(i32 %t4)
599  %t5 = icmp eq i32 %t4, %arg
600  call void @use1(i1 %t5)
601  %t6 = select i1 %t2, i1 %t5, i1 false
602  ret i1 %t6
603}
604
605define zeroext i1 @oneuse_trunc_sext(i32 %arg) {
606; CHECK-LABEL: @oneuse_trunc_sext(
607; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i8
608; CHECK-NEXT:    call void @use8(i8 [[T1]])
609; CHECK-NEXT:    [[T2:%.*]] = icmp sgt i8 [[T1]], -1
610; CHECK-NEXT:    call void @use1(i1 [[T2]])
611; CHECK-NEXT:    [[T3:%.*]] = trunc i32 [[ARG]] to i8
612; CHECK-NEXT:    call void @use8(i8 [[T3]])
613; CHECK-NEXT:    [[T4:%.*]] = sext i8 [[T3]] to i32
614; CHECK-NEXT:    call void @use32(i32 [[T4]])
615; CHECK-NEXT:    [[T5:%.*]] = icmp eq i32 [[ARG]], [[T4]]
616; CHECK-NEXT:    call void @use1(i1 [[T5]])
617; CHECK-NEXT:    [[T6:%.*]] = and i1 [[T2]], [[T5]]
618; CHECK-NEXT:    ret i1 [[T6]]
619;
620  %t1 = trunc i32 %arg to i8
621  call void @use8(i8 %t1)
622  %t2 = icmp sgt i8 %t1, -1
623  call void @use1(i1 %t2)
624  %t3 = trunc i32 %arg to i8
625  call void @use8(i8 %t3)
626  %t4 = sext i8 %t3 to i32
627  call void @use32(i32 %t4)
628  %t5 = icmp eq i32 %t4, %arg
629  call void @use1(i1 %t5)
630  %t6 = and i1 %t2, %t5
631  ret i1 %t6
632}
633
634define zeroext i1 @oneuse_trunc_sext_logical(i32 %arg) {
635; CHECK-LABEL: @oneuse_trunc_sext_logical(
636; CHECK-NEXT:    [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i8
637; CHECK-NEXT:    call void @use8(i8 [[T1]])
638; CHECK-NEXT:    [[T2:%.*]] = icmp sgt i8 [[T1]], -1
639; CHECK-NEXT:    call void @use1(i1 [[T2]])
640; CHECK-NEXT:    [[T3:%.*]] = trunc i32 [[ARG]] to i8
641; CHECK-NEXT:    call void @use8(i8 [[T3]])
642; CHECK-NEXT:    [[T4:%.*]] = sext i8 [[T3]] to i32
643; CHECK-NEXT:    call void @use32(i32 [[T4]])
644; CHECK-NEXT:    [[T5:%.*]] = icmp eq i32 [[ARG]], [[T4]]
645; CHECK-NEXT:    call void @use1(i1 [[T5]])
646; CHECK-NEXT:    [[T6:%.*]] = select i1 [[T2]], i1 [[T5]], i1 false
647; CHECK-NEXT:    ret i1 [[T6]]
648;
649  %t1 = trunc i32 %arg to i8
650  call void @use8(i8 %t1)
651  %t2 = icmp sgt i8 %t1, -1
652  call void @use1(i1 %t2)
653  %t3 = trunc i32 %arg to i8
654  call void @use8(i8 %t3)
655  %t4 = sext i8 %t3 to i32
656  call void @use32(i32 %t4)
657  %t5 = icmp eq i32 %t4, %arg
658  call void @use1(i1 %t5)
659  %t6 = select i1 %t2, i1 %t5, i1 false
660  ret i1 %t6
661}
662
663; ============================================================================ ;
664; Negative tests
665; ============================================================================ ;
666
667define i1 @negative_not_arg(i32 %arg, i32 %arg2) {
668; CHECK-LABEL: @negative_not_arg(
669; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
670; CHECK-NEXT:    [[T2:%.*]] = add i32 [[ARG2:%.*]], 128
671; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 256
672; CHECK-NEXT:    [[T4:%.*]] = and i1 [[T1]], [[T3]]
673; CHECK-NEXT:    ret i1 [[T4]]
674;
675  %t1 = icmp sgt i32 %arg, -1
676  %t2 = add i32 %arg2, 128 ; not %arg
677  %t3 = icmp ult i32 %t2, 256
678  %t4 = and i1 %t1, %t3
679  ret i1 %t4
680}
681
682define i1 @negative_not_arg_logical(i32 %arg, i32 %arg2) {
683; CHECK-LABEL: @negative_not_arg_logical(
684; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
685; CHECK-NEXT:    [[T2:%.*]] = add i32 [[ARG2:%.*]], 128
686; CHECK-NEXT:    [[T3:%.*]] = icmp ult i32 [[T2]], 256
687; CHECK-NEXT:    [[T4:%.*]] = select i1 [[T1]], i1 [[T3]], i1 false
688; CHECK-NEXT:    ret i1 [[T4]]
689;
690  %t1 = icmp sgt i32 %arg, -1
691  %t2 = add i32 %arg2, 128 ; not %arg
692  %t3 = icmp ult i32 %t2, 256
693  %t4 = select i1 %t1, i1 %t3, i1 false
694  ret i1 %t4
695}
696
697define i1 @negative_trunc_not_arg(i32 %arg, i32 %arg2) {
698; CHECK-LABEL: @negative_trunc_not_arg(
699; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARG:%.*]], 128
700; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[TMP1]], 0
701; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG2:%.*]], 128
702; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
703; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
704; CHECK-NEXT:    ret i1 [[T5]]
705;
706  %t1 = trunc i32 %arg to i8
707  %t2 = icmp sgt i8 %t1, -1
708  %t3 = add i32 %arg2, 128 ; not %arg
709  %t4 = icmp ult i32 %t3, 256
710  %t5 = and i1 %t2, %t4
711  ret i1 %t5
712}
713
714define i1 @negative_trunc_not_arg_logical(i32 %arg, i32 %arg2) {
715; CHECK-LABEL: @negative_trunc_not_arg_logical(
716; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARG:%.*]], 128
717; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[TMP1]], 0
718; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG2:%.*]], 128
719; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
720; CHECK-NEXT:    [[T5:%.*]] = select i1 [[T2]], i1 [[T4]], i1 false
721; CHECK-NEXT:    ret i1 [[T5]]
722;
723  %t1 = trunc i32 %arg to i8
724  %t2 = icmp sgt i8 %t1, -1
725  %t3 = add i32 %arg2, 128 ; not %arg
726  %t4 = icmp ult i32 %t3, 256
727  %t5 = select i1 %t2, i1 %t4, i1 false
728  ret i1 %t5
729}
730
731define i1 @positive_with_mask_not_arg(i32 %arg, i32 %arg2) {
732; CHECK-LABEL: @positive_with_mask_not_arg(
733; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 1140850688
734; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
735; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG2:%.*]], 128
736; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
737; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
738; CHECK-NEXT:    ret i1 [[T5]]
739;
740  %t1 = and i32 %arg, 1140850688
741  %t2 = icmp eq i32 %t1, 0
742  %t3 = add i32 %arg2, 128 ; not %arg
743  %t4 = icmp ult i32 %t3, 256
744  %t5 = and i1 %t2, %t4
745  ret i1 %t5
746}
747
748define i1 @positive_with_mask_not_arg_logical(i32 %arg, i32 %arg2) {
749; CHECK-LABEL: @positive_with_mask_not_arg_logical(
750; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 1140850688
751; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
752; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG2:%.*]], 128
753; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
754; CHECK-NEXT:    [[T5:%.*]] = select i1 [[T2]], i1 [[T4]], i1 false
755; CHECK-NEXT:    ret i1 [[T5]]
756;
757  %t1 = and i32 %arg, 1140850688
758  %t2 = icmp eq i32 %t1, 0
759  %t3 = add i32 %arg2, 128 ; not %arg
760  %t4 = icmp ult i32 %t3, 256
761  %t5 = select i1 %t2, i1 %t4, i1 false
762  ret i1 %t5
763}
764
765define i1 @negative_with_nonuniform_bad_mask(i32 %arg) {
766; CHECK-LABEL: @negative_with_nonuniform_bad_mask(
767; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 1711276033
768; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
769; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
770; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
771; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
772; CHECK-NEXT:    ret i1 [[T5]]
773;
774  %t1 = and i32 %arg, 1711276033 ; lowest bit is set
775  %t2 = icmp eq i32 %t1, 0
776  %t3 = add i32 %arg, 128
777  %t4 = icmp ult i32 %t3, 256
778  %t5 = and i1 %t2, %t4
779  ret i1 %t5
780}
781
782define i1 @negative_with_nonuniform_bad_mask_logical(i32 %arg) {
783; CHECK-LABEL: @negative_with_nonuniform_bad_mask_logical(
784; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 1711276033
785; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
786; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
787; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
788; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
789; CHECK-NEXT:    ret i1 [[T5]]
790;
791  %t1 = and i32 %arg, 1711276033 ; lowest bit is set
792  %t2 = icmp eq i32 %t1, 0
793  %t3 = add i32 %arg, 128
794  %t4 = icmp ult i32 %t3, 256
795  %t5 = select i1 %t2, i1 %t4, i1 false
796  ret i1 %t5
797}
798
799define i1 @negative_with_uniform_bad_mask(i32 %arg) {
800; CHECK-LABEL: @negative_with_uniform_bad_mask(
801; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], -16777152
802; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
803; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
804; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
805; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
806; CHECK-NEXT:    ret i1 [[T5]]
807;
808  %t1 = and i32 %arg, 4278190144 ; 7'th bit is set
809  %t2 = icmp eq i32 %t1, 0
810  %t3 = add i32 %arg, 128
811  %t4 = icmp ult i32 %t3, 256
812  %t5 = and i1 %t2, %t4
813  ret i1 %t5
814}
815
816define i1 @negative_with_uniform_bad_mask_logical(i32 %arg) {
817; CHECK-LABEL: @negative_with_uniform_bad_mask_logical(
818; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], -16777152
819; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
820; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
821; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
822; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
823; CHECK-NEXT:    ret i1 [[T5]]
824;
825  %t1 = and i32 %arg, 4278190144 ; 7'th bit is set
826  %t2 = icmp eq i32 %t1, 0
827  %t3 = add i32 %arg, 128
828  %t4 = icmp ult i32 %t3, 256
829  %t5 = select i1 %t2, i1 %t4, i1 false
830  ret i1 %t5
831}
832
833define i1 @negative_with_wrong_mask(i32 %arg) {
834; CHECK-LABEL: @negative_with_wrong_mask(
835; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 1
836; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
837; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
838; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
839; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
840; CHECK-NEXT:    ret i1 [[T5]]
841;
842  %t1 = and i32 %arg, 1 ; not even checking the right mask
843  %t2 = icmp eq i32 %t1, 0
844  %t3 = add i32 %arg, 128
845  %t4 = icmp ult i32 %t3, 256
846  %t5 = and i1 %t2, %t4
847  ret i1 %t5
848}
849
850define i1 @negative_with_wrong_mask_logical(i32 %arg) {
851; CHECK-LABEL: @negative_with_wrong_mask_logical(
852; CHECK-NEXT:    [[T1:%.*]] = and i32 [[ARG:%.*]], 1
853; CHECK-NEXT:    [[T2:%.*]] = icmp eq i32 [[T1]], 0
854; CHECK-NEXT:    [[T3:%.*]] = add i32 [[ARG]], 128
855; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[T3]], 256
856; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T2]], [[T4]]
857; CHECK-NEXT:    ret i1 [[T5]]
858;
859  %t1 = and i32 %arg, 1 ; not even checking the right mask
860  %t2 = icmp eq i32 %t1, 0
861  %t3 = add i32 %arg, 128
862  %t4 = icmp ult i32 %t3, 256
863  %t5 = select i1 %t2, i1 %t4, i1 false
864  ret i1 %t5
865}
866
867define i1 @negative_not_less_than(i32 %arg) {
868; CHECK-LABEL: @negative_not_less_than(
869; CHECK-NEXT:    ret i1 false
870;
871  %t1 = icmp sgt i32 %arg, -1
872  %t2 = add i32 %arg, 256 ; should be less than 256
873  %t3 = icmp ult i32 %t2, 256
874  %t4 = and i1 %t1, %t3
875  ret i1 %t4
876}
877
878define i1 @negative_not_less_than_logical(i32 %arg) {
879; CHECK-LABEL: @negative_not_less_than_logical(
880; CHECK-NEXT:    ret i1 false
881;
882  %t1 = icmp sgt i32 %arg, -1
883  %t2 = add i32 %arg, 256 ; should be less than 256
884  %t3 = icmp ult i32 %t2, 256
885  %t4 = select i1 %t1, i1 %t3, i1 false
886  ret i1 %t4
887}
888
889define i1 @negative_not_power_of_two(i32 %arg) {
890; CHECK-LABEL: @negative_not_power_of_two(
891; CHECK-NEXT:    [[T4:%.*]] = icmp eq i32 [[ARG:%.*]], 0
892; CHECK-NEXT:    ret i1 [[T4]]
893;
894  %t1 = icmp sgt i32 %arg, -1
895  %t2 = add i32 %arg, 255 ; should be power of two
896  %t3 = icmp ult i32 %t2, 256
897  %t4 = and i1 %t1, %t3
898  ret i1 %t4
899}
900
901define i1 @negative_not_power_of_two_logical(i32 %arg) {
902; CHECK-LABEL: @negative_not_power_of_two_logical(
903; CHECK-NEXT:    [[T4:%.*]] = icmp eq i32 [[ARG:%.*]], 0
904; CHECK-NEXT:    ret i1 [[T4]]
905;
906  %t1 = icmp sgt i32 %arg, -1
907  %t2 = add i32 %arg, 255 ; should be power of two
908  %t3 = icmp ult i32 %t2, 256
909  %t4 = select i1 %t1, i1 %t3, i1 false
910  ret i1 %t4
911}
912
913define i1 @negative_not_next_power_of_two(i32 %arg) {
914; CHECK-LABEL: @negative_not_next_power_of_two(
915; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[ARG:%.*]], 192
916; CHECK-NEXT:    ret i1 [[T4]]
917;
918  %t1 = icmp sgt i32 %arg, -1
919  %t2 = add i32 %arg, 64 ; should be 256 >> 1
920  %t3 = icmp ult i32 %t2, 256
921  %t4 = and i1 %t1, %t3
922  ret i1 %t4
923}
924
925define i1 @negative_not_next_power_of_two_logical(i32 %arg) {
926; CHECK-LABEL: @negative_not_next_power_of_two_logical(
927; CHECK-NEXT:    [[T4:%.*]] = icmp ult i32 [[ARG:%.*]], 192
928; CHECK-NEXT:    ret i1 [[T4]]
929;
930  %t1 = icmp sgt i32 %arg, -1
931  %t2 = add i32 %arg, 64 ; should be 256 >> 1
932  %t3 = icmp ult i32 %t2, 256
933  %t4 = select i1 %t1, i1 %t3, i1 false
934  ret i1 %t4
935}
936
937define i1 @two_signed_truncation_checks(i32 %arg) {
938; CHECK-LABEL: @two_signed_truncation_checks(
939; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[ARG:%.*]], 128
940; CHECK-NEXT:    [[T5:%.*]] = icmp ult i32 [[TMP1]], 256
941; CHECK-NEXT:    ret i1 [[T5]]
942;
943  %t1 = add i32 %arg, 512
944  %t2 = icmp ult i32 %t1, 1024
945  %t3 = add i32 %arg, 128
946  %t4 = icmp ult i32 %t3, 256
947  %t5 = and i1 %t2, %t4
948  ret i1 %t5
949}
950
951define i1 @two_signed_truncation_checks_logical(i32 %arg) {
952; CHECK-LABEL: @two_signed_truncation_checks_logical(
953; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[ARG:%.*]], 128
954; CHECK-NEXT:    [[T5:%.*]] = icmp ult i32 [[TMP1]], 256
955; CHECK-NEXT:    ret i1 [[T5]]
956;
957  %t1 = add i32 %arg, 512
958  %t2 = icmp ult i32 %t1, 1024
959  %t3 = add i32 %arg, 128
960  %t4 = icmp ult i32 %t3, 256
961  %t5 = select i1 %t2, i1 %t4, i1 false
962  ret i1 %t5
963}
964
965define i1 @bad_trunc_stc(i32 %arg) {
966; CHECK-LABEL: @bad_trunc_stc(
967; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
968; CHECK-NEXT:    [[T2:%.*]] = trunc i32 [[ARG]] to i16
969; CHECK-NEXT:    [[T3:%.*]] = add i16 [[T2]], 128
970; CHECK-NEXT:    [[T4:%.*]] = icmp ult i16 [[T3]], 256
971; CHECK-NEXT:    [[T5:%.*]] = and i1 [[T1]], [[T4]]
972; CHECK-NEXT:    ret i1 [[T5]]
973;
974  %t1 = icmp sgt i32 %arg, -1 ; checks a bit outside of the i16
975  %t2 = trunc i32 %arg to i16
976  %t3 = add i16 %t2, 128
977  %t4 = icmp ult i16 %t3, 256
978  %t5 = and i1 %t1, %t4
979  ret i1 %t5
980}
981
982define i1 @bad_trunc_stc_logical(i32 %arg) {
983; CHECK-LABEL: @bad_trunc_stc_logical(
984; CHECK-NEXT:    [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
985; CHECK-NEXT:    [[T2:%.*]] = trunc i32 [[ARG]] to i16
986; CHECK-NEXT:    [[T3:%.*]] = add i16 [[T2]], 128
987; CHECK-NEXT:    [[T4:%.*]] = icmp ult i16 [[T3]], 256
988; CHECK-NEXT:    [[T5:%.*]] = select i1 [[T1]], i1 [[T4]], i1 false
989; CHECK-NEXT:    ret i1 [[T5]]
990;
991  %t1 = icmp sgt i32 %arg, -1 ; checks a bit outside of the i16
992  %t2 = trunc i32 %arg to i16
993  %t3 = add i16 %t2, 128
994  %t4 = icmp ult i16 %t3, 256
995  %t5 = select i1 %t1, i1 %t4, i1 false
996  ret i1 %t5
997}
998