blob: 66f04d5e61e4d8ebc142fce463a3910bb496ddfd [file] [log] [blame]
Roman Lebedev2da1ef52018-08-13 18:51:09 +00001; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -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: [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
42; CHECK-NEXT: [[T2:%.*]] = add i32 [[ARG]], 128
43; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 256
44; CHECK-NEXT: [[T4:%.*]] = and i1 [[T1]], [[T3]]
45; CHECK-NEXT: ret i1 [[T4]]
46;
47 %t1 = icmp sgt i32 %arg, -1
48 %t2 = add i32 %arg, 128
49 %t3 = icmp ult i32 %t2, 256
50 %t4 = and i1 %t1, %t3
51 ret i1 %t4
52}
53
54define i1 @positive_with_mask(i32 %arg) {
55; CHECK-LABEL: @positive_with_mask(
56; CHECK-NEXT: [[T1:%.*]] = and i32 [[ARG:%.*]], 1107296256
57; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
58; CHECK-NEXT: [[T3:%.*]] = add i32 [[ARG]], 128
59; CHECK-NEXT: [[T4:%.*]] = icmp ult i32 [[T3]], 256
60; CHECK-NEXT: [[T5:%.*]] = and i1 [[T2]], [[T4]]
61; CHECK-NEXT: ret i1 [[T5]]
62;
63 %t1 = and i32 %arg, 1107296256
64 %t2 = icmp eq i32 %t1, 0
65 %t3 = add i32 %arg, 128
66 %t4 = icmp ult i32 %t3, 256
67 %t5 = and i1 %t2, %t4
68 ret i1 %t5
69}
70
71define i1 @positive_with_icmp(i32 %arg) {
72; CHECK-LABEL: @positive_with_icmp(
73; CHECK-NEXT: [[T1:%.*]] = icmp ult i32 [[ARG:%.*]], 512
74; CHECK-NEXT: [[T2:%.*]] = add i32 [[ARG]], 128
75; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 256
76; CHECK-NEXT: [[T4:%.*]] = and i1 [[T1]], [[T3]]
77; CHECK-NEXT: ret i1 [[T4]]
78;
79 %t1 = icmp ult i32 %arg, 512
80 %t2 = add i32 %arg, 128
81 %t3 = icmp ult i32 %t2, 256
82 %t4 = and i1 %t1, %t3
83 ret i1 %t4
84}
85
86; Still the same
87define i1 @positive_with_aggressive_icmp(i32 %arg) {
88; CHECK-LABEL: @positive_with_aggressive_icmp(
89; CHECK-NEXT: [[T1:%.*]] = icmp ult i32 [[ARG:%.*]], 128
90; CHECK-NEXT: [[T2:%.*]] = add i32 [[ARG]], 256
91; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 512
92; CHECK-NEXT: [[T4:%.*]] = and i1 [[T1]], [[T3]]
93; CHECK-NEXT: ret i1 [[T4]]
94;
95 %t1 = icmp ult i32 %arg, 128
96 %t2 = add i32 %arg, 256
97 %t3 = icmp ult i32 %t2, 512
98 %t4 = and i1 %t1, %t3
99 ret i1 %t4
100}
101
102; I'm sure there is a bunch more patterns possible :/
103
104; ============================================================================ ;
105; Vector tests
106; ============================================================================ ;
107
108define <2 x i1> @positive_vec_splat(<2 x i32> %arg) {
109; CHECK-LABEL: @positive_vec_splat(
110; CHECK-NEXT: [[T1:%.*]] = icmp sgt <2 x i32> [[ARG:%.*]], <i32 -1, i32 -1>
111; CHECK-NEXT: [[T2:%.*]] = add <2 x i32> [[ARG]], <i32 128, i32 128>
112; CHECK-NEXT: [[T3:%.*]] = icmp ult <2 x i32> [[T2]], <i32 256, i32 256>
113; CHECK-NEXT: [[T4:%.*]] = and <2 x i1> [[T1]], [[T3]]
114; CHECK-NEXT: ret <2 x i1> [[T4]]
115;
116 %t1 = icmp sgt <2 x i32> %arg, <i32 -1, i32 -1>
117 %t2 = add <2 x i32> %arg, <i32 128, i32 128>
118 %t3 = icmp ult <2 x i32> %t2, <i32 256, i32 256>
119 %t4 = and <2 x i1> %t1, %t3
120 ret <2 x i1> %t4
121}
122
123define <2 x i1> @positive_vec_nonsplat(<2 x i32> %arg) {
124; CHECK-LABEL: @positive_vec_nonsplat(
125; CHECK-NEXT: [[T1:%.*]] = icmp sgt <2 x i32> [[ARG:%.*]], <i32 -1, i32 -1>
126; CHECK-NEXT: [[T2:%.*]] = add <2 x i32> [[ARG]], <i32 128, i32 256>
127; CHECK-NEXT: [[T3:%.*]] = icmp ult <2 x i32> [[T2]], <i32 256, i32 512>
128; CHECK-NEXT: [[T4:%.*]] = and <2 x i1> [[T1]], [[T3]]
129; CHECK-NEXT: ret <2 x i1> [[T4]]
130;
131 %t1 = icmp sgt <2 x i32> %arg, <i32 -1, i32 -1>
132 %t2 = add <2 x i32> %arg, <i32 128, i32 256>
133 %t3 = icmp ult <2 x i32> %t2, <i32 256, i32 512>
134 %t4 = and <2 x i1> %t1, %t3
135 ret <2 x i1> %t4
136}
137
138define <3 x i1> @positive_vec_undef0(<3 x i32> %arg) {
139; CHECK-LABEL: @positive_vec_undef0(
140; CHECK-NEXT: [[T1:%.*]] = icmp sgt <3 x i32> [[ARG:%.*]], <i32 -1, i32 undef, i32 -1>
141; CHECK-NEXT: [[T2:%.*]] = add <3 x i32> [[ARG]], <i32 128, i32 128, i32 128>
142; CHECK-NEXT: [[T3:%.*]] = icmp ult <3 x i32> [[T2]], <i32 256, i32 256, i32 256>
143; CHECK-NEXT: [[T4:%.*]] = and <3 x i1> [[T1]], [[T3]]
144; CHECK-NEXT: ret <3 x i1> [[T4]]
145;
146 %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 undef, i32 -1>
147 %t2 = add <3 x i32> %arg, <i32 128, i32 128, i32 128>
148 %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 256, i32 256>
149 %t4 = and <3 x i1> %t1, %t3
150 ret <3 x i1> %t4
151}
152
153define <3 x i1> @positive_vec_undef1(<3 x i32> %arg) {
154; CHECK-LABEL: @positive_vec_undef1(
155; CHECK-NEXT: [[T1:%.*]] = icmp sgt <3 x i32> [[ARG:%.*]], <i32 -1, i32 -1, i32 -1>
156; CHECK-NEXT: [[T2:%.*]] = add <3 x i32> [[ARG]], <i32 128, i32 undef, i32 128>
157; CHECK-NEXT: [[T3:%.*]] = icmp ult <3 x i32> [[T2]], <i32 256, i32 256, i32 256>
158; CHECK-NEXT: [[T4:%.*]] = and <3 x i1> [[T1]], [[T3]]
159; CHECK-NEXT: ret <3 x i1> [[T4]]
160;
161 %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 -1, i32 -1>
162 %t2 = add <3 x i32> %arg, <i32 128, i32 undef, i32 128>
163 %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 256, i32 256>
164 %t4 = and <3 x i1> %t1, %t3
165 ret <3 x i1> %t4
166}
167
168define <3 x i1> @positive_vec_undef2(<3 x i32> %arg) {
169; CHECK-LABEL: @positive_vec_undef2(
170; CHECK-NEXT: [[T1:%.*]] = icmp sgt <3 x i32> [[ARG:%.*]], <i32 -1, i32 -1, i32 -1>
171; CHECK-NEXT: [[T2:%.*]] = add <3 x i32> [[ARG]], <i32 128, i32 128, i32 128>
172; CHECK-NEXT: [[T3:%.*]] = icmp ult <3 x i32> [[T2]], <i32 256, i32 undef, i32 256>
173; CHECK-NEXT: [[T4:%.*]] = and <3 x i1> [[T1]], [[T3]]
174; CHECK-NEXT: ret <3 x i1> [[T4]]
175;
176 %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 -1, i32 -1>
177 %t2 = add <3 x i32> %arg, <i32 128, i32 128, i32 128>
178 %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 undef, i32 256>
179 %t4 = and <3 x i1> %t1, %t3
180 ret <3 x i1> %t4
181}
182
183define <3 x i1> @positive_vec_undef3(<3 x i32> %arg) {
184; CHECK-LABEL: @positive_vec_undef3(
185; CHECK-NEXT: [[T1:%.*]] = icmp sgt <3 x i32> [[ARG:%.*]], <i32 -1, i32 undef, i32 -1>
186; CHECK-NEXT: [[T2:%.*]] = add <3 x i32> [[ARG]], <i32 128, i32 undef, i32 128>
187; CHECK-NEXT: [[T3:%.*]] = icmp ult <3 x i32> [[T2]], <i32 256, i32 256, i32 256>
188; CHECK-NEXT: [[T4:%.*]] = and <3 x i1> [[T1]], [[T3]]
189; CHECK-NEXT: ret <3 x i1> [[T4]]
190;
191 %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 undef, i32 -1>
192 %t2 = add <3 x i32> %arg, <i32 128, i32 undef, i32 128>
193 %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 256, i32 256>
194 %t4 = and <3 x i1> %t1, %t3
195 ret <3 x i1> %t4
196}
197
198define <3 x i1> @positive_vec_undef4(<3 x i32> %arg) {
199; CHECK-LABEL: @positive_vec_undef4(
200; CHECK-NEXT: [[T1:%.*]] = icmp sgt <3 x i32> [[ARG:%.*]], <i32 -1, i32 undef, i32 -1>
201; CHECK-NEXT: [[T2:%.*]] = add <3 x i32> [[ARG]], <i32 128, i32 128, i32 128>
202; CHECK-NEXT: [[T3:%.*]] = icmp ult <3 x i32> [[T2]], <i32 256, i32 undef, i32 256>
203; CHECK-NEXT: [[T4:%.*]] = and <3 x i1> [[T1]], [[T3]]
204; CHECK-NEXT: ret <3 x i1> [[T4]]
205;
206 %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 undef, 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 undef, i32 256>
209 %t4 = and <3 x i1> %t1, %t3
210 ret <3 x i1> %t4
211}
212
213define <3 x i1> @positive_vec_undef5(<3 x i32> %arg) {
214; CHECK-LABEL: @positive_vec_undef5(
215; CHECK-NEXT: [[T1:%.*]] = icmp sgt <3 x i32> [[ARG:%.*]], <i32 -1, i32 -1, i32 -1>
216; CHECK-NEXT: [[T2:%.*]] = add <3 x i32> [[ARG]], <i32 128, i32 undef, i32 128>
217; CHECK-NEXT: [[T3:%.*]] = icmp ult <3 x i32> [[T2]], <i32 256, i32 undef, i32 256>
218; CHECK-NEXT: [[T4:%.*]] = and <3 x i1> [[T1]], [[T3]]
219; CHECK-NEXT: ret <3 x i1> [[T4]]
220;
221 %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 -1, i32 -1>
222 %t2 = add <3 x i32> %arg, <i32 128, i32 undef, i32 128>
223 %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 undef, i32 256>
224 %t4 = and <3 x i1> %t1, %t3
225 ret <3 x i1> %t4
226}
227
228define <3 x i1> @positive_vec_undef6(<3 x i32> %arg) {
229; CHECK-LABEL: @positive_vec_undef6(
230; CHECK-NEXT: [[T1:%.*]] = icmp sgt <3 x i32> [[ARG:%.*]], <i32 -1, i32 undef, i32 -1>
231; CHECK-NEXT: [[T2:%.*]] = add <3 x i32> [[ARG]], <i32 128, i32 undef, i32 128>
232; CHECK-NEXT: [[T3:%.*]] = icmp ult <3 x i32> [[T2]], <i32 256, i32 undef, i32 256>
233; CHECK-NEXT: [[T4:%.*]] = and <3 x i1> [[T1]], [[T3]]
234; CHECK-NEXT: ret <3 x i1> [[T4]]
235;
236 %t1 = icmp sgt <3 x i32> %arg, <i32 -1, i32 undef, i32 -1>
237 %t2 = add <3 x i32> %arg, <i32 128, i32 undef, i32 128>
238 %t3 = icmp ult <3 x i32> %t2, <i32 256, i32 undef, i32 256>
239 %t4 = and <3 x i1> %t1, %t3
240 ret <3 x i1> %t4
241}
242
243; ============================================================================ ;
244; Commutativity tests.
245; ============================================================================ ;
246
247declare i32 @gen32()
248
249define i1 @commutative() {
250; CHECK-LABEL: @commutative(
251; CHECK-NEXT: [[ARG:%.*]] = call i32 @gen32()
252; CHECK-NEXT: [[T1:%.*]] = icmp sgt i32 [[ARG]], -1
253; CHECK-NEXT: [[T2:%.*]] = add i32 [[ARG]], 128
254; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 256
255; CHECK-NEXT: [[T4:%.*]] = and i1 [[T3]], [[T1]]
256; CHECK-NEXT: ret i1 [[T4]]
257;
258 %arg = call i32 @gen32()
259 %t1 = icmp sgt i32 %arg, -1
260 %t2 = add i32 %arg, 128
261 %t3 = icmp ult i32 %t2, 256
262 %t4 = and i1 %t3, %t1 ; swapped order
263 ret i1 %t4
264}
265
266define i1 @commutative_with_icmp() {
267; CHECK-LABEL: @commutative_with_icmp(
268; CHECK-NEXT: [[ARG:%.*]] = call i32 @gen32()
269; CHECK-NEXT: [[T1:%.*]] = icmp ult i32 [[ARG]], 512
270; CHECK-NEXT: [[T2:%.*]] = add i32 [[ARG]], 128
271; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 256
272; CHECK-NEXT: [[T4:%.*]] = and i1 [[T3]], [[T1]]
273; CHECK-NEXT: ret i1 [[T4]]
274;
275 %arg = call i32 @gen32()
276 %t1 = icmp ult i32 %arg, 512
277 %t2 = add i32 %arg, 128
278 %t3 = icmp ult i32 %t2, 256
279 %t4 = and i1 %t3, %t1 ; swapped order
280 ret i1 %t4
281}
282
283; ============================================================================ ;
284; Truncations.
285; ============================================================================ ;
286
287define i1 @positive_trunc_signbit(i32 %arg) {
288; CHECK-LABEL: @positive_trunc_signbit(
289; CHECK-NEXT: [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i8
290; CHECK-NEXT: [[T2:%.*]] = icmp sgt i8 [[T1]], -1
291; CHECK-NEXT: [[T3:%.*]] = add i32 [[ARG]], 128
292; CHECK-NEXT: [[T4:%.*]] = icmp ult i32 [[T3]], 256
293; CHECK-NEXT: [[T5:%.*]] = and i1 [[T2]], [[T4]]
294; CHECK-NEXT: ret i1 [[T5]]
295;
296 %t1 = trunc i32 %arg to i8
297 %t2 = icmp sgt i8 %t1, -1
298 %t3 = add i32 %arg, 128
299 %t4 = icmp ult i32 %t3, 256
300 %t5 = and i1 %t2, %t4
301 ret i1 %t5
302}
303
304define i1 @positive_trunc_base(i32 %arg) {
305; CHECK-LABEL: @positive_trunc_base(
306; CHECK-NEXT: [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i16
307; CHECK-NEXT: [[T2:%.*]] = icmp sgt i16 [[T1]], -1
308; CHECK-NEXT: [[T3:%.*]] = add i16 [[T1]], 128
309; CHECK-NEXT: [[T4:%.*]] = icmp ult i16 [[T3]], 256
310; CHECK-NEXT: [[T5:%.*]] = and i1 [[T2]], [[T4]]
311; CHECK-NEXT: ret i1 [[T5]]
312;
313 %t1 = trunc i32 %arg to i16
314 %t2 = icmp sgt i16 %t1, -1
315 %t3 = add i16 %t1, 128
316 %t4 = icmp ult i16 %t3, 256
317 %t5 = and i1 %t2, %t4
318 ret i1 %t5
319}
320
321define i1 @positive_different_trunc_both(i32 %arg) {
322; CHECK-LABEL: @positive_different_trunc_both(
323; CHECK-NEXT: [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i15
324; CHECK-NEXT: [[T2:%.*]] = icmp sgt i15 [[T1]], -1
325; CHECK-NEXT: [[T3:%.*]] = trunc i32 [[ARG]] to i16
326; CHECK-NEXT: [[T4:%.*]] = add i16 [[T3]], 128
327; CHECK-NEXT: [[T5:%.*]] = icmp ult i16 [[T4]], 256
328; CHECK-NEXT: [[T6:%.*]] = and i1 [[T2]], [[T5]]
329; CHECK-NEXT: ret i1 [[T6]]
330;
331 %t1 = trunc i32 %arg to i15
332 %t2 = icmp sgt i15 %t1, -1
333 %t3 = trunc i32 %arg to i16
334 %t4 = add i16 %t3, 128
335 %t5 = icmp ult i16 %t4, 256
336 %t6 = and i1 %t2, %t5
337 ret i1 %t6
338}
339
340; ============================================================================ ;
341; One-use tests.
342;
343; We will only produce one instruction, so we do not care about one-use.
344; But, we *could* handle more patterns that we weren't able to canonicalize
345; because of extra-uses.
346; ============================================================================ ;
347
348declare void @use32(i32)
349declare void @use8(i8)
350declare void @use1(i1)
351
352define i1 @oneuse_with_signbit(i32 %arg) {
353; CHECK-LABEL: @oneuse_with_signbit(
354; CHECK-NEXT: [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
355; CHECK-NEXT: call void @use1(i1 [[T1]])
356; CHECK-NEXT: [[T2:%.*]] = add i32 [[ARG]], 128
357; CHECK-NEXT: call void @use32(i32 [[T2]])
358; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 256
359; CHECK-NEXT: call void @use1(i1 [[T3]])
360; CHECK-NEXT: [[T4:%.*]] = and i1 [[T1]], [[T3]]
361; CHECK-NEXT: ret i1 [[T4]]
362;
363 %t1 = icmp sgt i32 %arg, -1
364 call void @use1(i1 %t1)
365 %t2 = add i32 %arg, 128
366 call void @use32(i32 %t2)
367 %t3 = icmp ult i32 %t2, 256
368 call void @use1(i1 %t3)
369 %t4 = and i1 %t1, %t3
370 ret i1 %t4
371}
372
373define i1 @oneuse_with_mask(i32 %arg) {
374; CHECK-LABEL: @oneuse_with_mask(
375; CHECK-NEXT: [[T1:%.*]] = and i32 [[ARG:%.*]], 603979776
376; CHECK-NEXT: call void @use32(i32 [[T1]])
377; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
378; CHECK-NEXT: call void @use1(i1 [[T2]])
379; CHECK-NEXT: [[T3:%.*]] = add i32 [[ARG]], 128
380; CHECK-NEXT: call void @use32(i32 [[T3]])
381; CHECK-NEXT: [[T4:%.*]] = icmp ult i32 [[T3]], 256
382; CHECK-NEXT: call void @use1(i1 [[T4]])
383; CHECK-NEXT: [[T5:%.*]] = and i1 [[T2]], [[T4]]
384; CHECK-NEXT: ret i1 [[T5]]
385;
386 %t1 = and i32 %arg, 603979776 ; some bit within the target 4294967168 mask.
387 call void @use32(i32 %t1)
388 %t2 = icmp eq i32 %t1, 0
389 call void @use1(i1 %t2)
390 %t3 = add i32 %arg, 128
391 call void @use32(i32 %t3)
392 %t4 = icmp ult i32 %t3, 256
393 call void @use1(i1 %t4)
394 %t5 = and i1 %t2, %t4
395 ret i1 %t5
396}
397
398define i1 @oneuse_shl_ashr(i32 %arg) {
399; CHECK-LABEL: @oneuse_shl_ashr(
400; CHECK-NEXT: [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i8
401; CHECK-NEXT: call void @use8(i8 [[T1]])
402; CHECK-NEXT: [[T2:%.*]] = icmp sgt i8 [[T1]], -1
403; CHECK-NEXT: call void @use1(i1 [[T2]])
404; CHECK-NEXT: [[T3:%.*]] = shl i32 [[ARG]], 24
405; CHECK-NEXT: call void @use32(i32 [[T3]])
406; CHECK-NEXT: [[T4:%.*]] = ashr exact i32 [[T3]], 24
407; CHECK-NEXT: call void @use32(i32 [[T4]])
408; CHECK-NEXT: [[T5:%.*]] = icmp eq i32 [[T4]], [[ARG]]
409; CHECK-NEXT: call void @use1(i1 [[T5]])
410; CHECK-NEXT: [[T6:%.*]] = and i1 [[T2]], [[T5]]
411; CHECK-NEXT: ret i1 [[T6]]
412;
413 %t1 = trunc i32 %arg to i8
414 call void @use8(i8 %t1)
415 %t2 = icmp sgt i8 %t1, -1
416 call void @use1(i1 %t2)
417 %t3 = shl i32 %arg, 24
418 call void @use32(i32 %t3)
419 %t4 = ashr i32 %t3, 24
420 call void @use32(i32 %t4)
421 %t5 = icmp eq i32 %t4, %arg
422 call void @use1(i1 %t5)
423 %t6 = and i1 %t2, %t5
424 ret i1 %t6
425}
426
427define zeroext i1 @oneuse_trunc_sext(i32 %arg) {
428; CHECK-LABEL: @oneuse_trunc_sext(
429; CHECK-NEXT: [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i8
430; CHECK-NEXT: call void @use8(i8 [[T1]])
431; CHECK-NEXT: [[T2:%.*]] = icmp sgt i8 [[T1]], -1
432; CHECK-NEXT: call void @use1(i1 [[T2]])
433; CHECK-NEXT: [[T3:%.*]] = trunc i32 [[ARG]] to i8
434; CHECK-NEXT: call void @use8(i8 [[T3]])
435; CHECK-NEXT: [[T4:%.*]] = sext i8 [[T3]] to i32
436; CHECK-NEXT: call void @use32(i32 [[T4]])
437; CHECK-NEXT: [[T5:%.*]] = icmp eq i32 [[T4]], [[ARG]]
438; CHECK-NEXT: call void @use1(i1 [[T5]])
439; CHECK-NEXT: [[T6:%.*]] = and i1 [[T2]], [[T5]]
440; CHECK-NEXT: ret i1 [[T6]]
441;
442 %t1 = trunc i32 %arg to i8
443 call void @use8(i8 %t1)
444 %t2 = icmp sgt i8 %t1, -1
445 call void @use1(i1 %t2)
446 %t3 = trunc i32 %arg to i8
447 call void @use8(i8 %t3)
448 %t4 = sext i8 %t3 to i32
449 call void @use32(i32 %t4)
450 %t5 = icmp eq i32 %t4, %arg
451 call void @use1(i1 %t5)
452 %t6 = and i1 %t2, %t5
453 ret i1 %t6
454}
455
456; ============================================================================ ;
457; Negative tests
458; ============================================================================ ;
459
460define i1 @negative_not_arg(i32 %arg, i32 %arg2) {
461; CHECK-LABEL: @negative_not_arg(
462; CHECK-NEXT: [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
463; CHECK-NEXT: [[T2:%.*]] = add i32 [[ARG2:%.*]], 128
464; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 256
465; CHECK-NEXT: [[T4:%.*]] = and i1 [[T1]], [[T3]]
466; CHECK-NEXT: ret i1 [[T4]]
467;
468 %t1 = icmp sgt i32 %arg, -1
469 %t2 = add i32 %arg2, 128 ; not %arg
470 %t3 = icmp ult i32 %t2, 256
471 %t4 = and i1 %t1, %t3
472 ret i1 %t4
473}
474
475define i1 @negative_trunc_not_arg(i32 %arg, i32 %arg2) {
476; CHECK-LABEL: @negative_trunc_not_arg(
477; CHECK-NEXT: [[T1:%.*]] = trunc i32 [[ARG:%.*]] to i8
478; CHECK-NEXT: [[T2:%.*]] = icmp sgt i8 [[T1]], -1
479; CHECK-NEXT: [[T3:%.*]] = add i32 [[ARG2:%.*]], 128
480; CHECK-NEXT: [[T4:%.*]] = icmp ult i32 [[T3]], 256
481; CHECK-NEXT: [[T5:%.*]] = and i1 [[T2]], [[T4]]
482; CHECK-NEXT: ret i1 [[T5]]
483;
484 %t1 = trunc i32 %arg to i8
485 %t2 = icmp sgt i8 %t1, -1
486 %t3 = add i32 %arg2, 128 ; not %arg
487 %t4 = icmp ult i32 %t3, 256
488 %t5 = and i1 %t2, %t4
489 ret i1 %t5
490}
491
492define i1 @positive_with_mask_not_arg(i32 %arg, i32 %arg2) {
493; CHECK-LABEL: @positive_with_mask_not_arg(
494; CHECK-NEXT: [[T1:%.*]] = and i32 [[ARG:%.*]], 1140850688
495; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
496; CHECK-NEXT: [[T3:%.*]] = add i32 [[ARG2:%.*]], 128
497; CHECK-NEXT: [[T4:%.*]] = icmp ult i32 [[T3]], 256
498; CHECK-NEXT: [[T5:%.*]] = and i1 [[T2]], [[T4]]
499; CHECK-NEXT: ret i1 [[T5]]
500;
501 %t1 = and i32 %arg, 1140850688
502 %t2 = icmp eq i32 %t1, 0
503 %t3 = add i32 %arg2, 128 ; not %arg
504 %t4 = icmp ult i32 %t3, 256
505 %t5 = and i1 %t2, %t4
506 ret i1 %t5
507}
508
509define i1 @negative_with_nonuniform_bad_mask(i32 %arg) {
510; CHECK-LABEL: @negative_with_nonuniform_bad_mask(
511; CHECK-NEXT: [[T1:%.*]] = and i32 [[ARG:%.*]], 1711276033
512; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
513; CHECK-NEXT: [[T3:%.*]] = add i32 [[ARG]], 128
514; CHECK-NEXT: [[T4:%.*]] = icmp ult i32 [[T3]], 256
515; CHECK-NEXT: [[T5:%.*]] = and i1 [[T2]], [[T4]]
516; CHECK-NEXT: ret i1 [[T5]]
517;
518 %t1 = and i32 %arg, 1711276033 ; lowest bit is set
519 %t2 = icmp eq i32 %t1, 0
520 %t3 = add i32 %arg, 128
521 %t4 = icmp ult i32 %t3, 256
522 %t5 = and i1 %t2, %t4
523 ret i1 %t5
524}
525
526define i1 @negative_with_uniform_bad_mask(i32 %arg) {
527; CHECK-LABEL: @negative_with_uniform_bad_mask(
528; CHECK-NEXT: [[T1:%.*]] = and i32 [[ARG:%.*]], -16777152
529; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
530; CHECK-NEXT: [[T3:%.*]] = add i32 [[ARG]], 128
531; CHECK-NEXT: [[T4:%.*]] = icmp ult i32 [[T3]], 256
532; CHECK-NEXT: [[T5:%.*]] = and i1 [[T2]], [[T4]]
533; CHECK-NEXT: ret i1 [[T5]]
534;
535 %t1 = and i32 %arg, 4278190144 ; 7'th bit is set
536 %t2 = icmp eq i32 %t1, 0
537 %t3 = add i32 %arg, 128
538 %t4 = icmp ult i32 %t3, 256
539 %t5 = and i1 %t2, %t4
540 ret i1 %t5
541}
542
543define i1 @negative_with_wrong_mask(i32 %arg) {
544; CHECK-LABEL: @negative_with_wrong_mask(
545; CHECK-NEXT: [[T1:%.*]] = and i32 [[ARG:%.*]], 1
546; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
547; CHECK-NEXT: [[T3:%.*]] = add i32 [[ARG]], 128
548; CHECK-NEXT: [[T4:%.*]] = icmp ult i32 [[T3]], 256
549; CHECK-NEXT: [[T5:%.*]] = and i1 [[T2]], [[T4]]
550; CHECK-NEXT: ret i1 [[T5]]
551;
552 %t1 = and i32 %arg, 1 ; not even checking the right mask
553 %t2 = icmp eq i32 %t1, 0
554 %t3 = add i32 %arg, 128
555 %t4 = icmp ult i32 %t3, 256
556 %t5 = and i1 %t2, %t4
557 ret i1 %t5
558}
559
560define i1 @negative_not_less_than(i32 %arg) {
561; CHECK-LABEL: @negative_not_less_than(
562; CHECK-NEXT: ret i1 false
563;
564 %t1 = icmp sgt i32 %arg, -1
565 %t2 = add i32 %arg, 256 ; should be less than 256
566 %t3 = icmp ult i32 %t2, 256
567 %t4 = and i1 %t1, %t3
568 ret i1 %t4
569}
570
571define i1 @negative_not_power_of_two(i32 %arg) {
572; CHECK-LABEL: @negative_not_power_of_two(
573; CHECK-NEXT: [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
574; CHECK-NEXT: [[T2:%.*]] = add i32 [[ARG]], 255
575; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 256
576; CHECK-NEXT: [[T4:%.*]] = and i1 [[T1]], [[T3]]
577; CHECK-NEXT: ret i1 [[T4]]
578;
579 %t1 = icmp sgt i32 %arg, -1
580 %t2 = add i32 %arg, 255 ; should be power of two
581 %t3 = icmp ult i32 %t2, 256
582 %t4 = and i1 %t1, %t3
583 ret i1 %t4
584}
585
586define i1 @negative_not_next_power_of_two(i32 %arg) {
587; CHECK-LABEL: @negative_not_next_power_of_two(
588; CHECK-NEXT: [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
589; CHECK-NEXT: [[T2:%.*]] = add i32 [[ARG]], 64
590; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 256
591; CHECK-NEXT: [[T4:%.*]] = and i1 [[T1]], [[T3]]
592; CHECK-NEXT: ret i1 [[T4]]
593;
594 %t1 = icmp sgt i32 %arg, -1
595 %t2 = add i32 %arg, 64 ; should be 256 >> 1
596 %t3 = icmp ult i32 %t2, 256
597 %t4 = and i1 %t1, %t3
598 ret i1 %t4
599}
600
601; I don't think this can be folded, at least not into single instruction.
602define i1 @two_signed_truncation_checks(i32 %arg) {
603; CHECK-LABEL: @two_signed_truncation_checks(
604; CHECK-NEXT: [[T1:%.*]] = add i32 [[ARG:%.*]], 512
605; CHECK-NEXT: [[T2:%.*]] = icmp ult i32 [[T1]], 1024
606; CHECK-NEXT: [[T3:%.*]] = add i32 [[ARG]], 128
607; CHECK-NEXT: [[T4:%.*]] = icmp ult i32 [[T3]], 256
608; CHECK-NEXT: [[T5:%.*]] = and i1 [[T2]], [[T4]]
609; CHECK-NEXT: ret i1 [[T5]]
610;
611 %t1 = add i32 %arg, 512
612 %t2 = icmp ult i32 %t1, 1024
613 %t3 = add i32 %arg, 128
614 %t4 = icmp ult i32 %t3, 256
615 %t5 = and i1 %t2, %t4
616 ret i1 %t5
617}
618
619define i1 @bad_trunc_stc(i32 %arg) {
620; CHECK-LABEL: @bad_trunc_stc(
621; CHECK-NEXT: [[T1:%.*]] = icmp sgt i32 [[ARG:%.*]], -1
622; CHECK-NEXT: [[T2:%.*]] = trunc i32 [[ARG]] to i16
623; CHECK-NEXT: [[T3:%.*]] = add i16 [[T2]], 128
624; CHECK-NEXT: [[T4:%.*]] = icmp ult i16 [[T3]], 256
625; CHECK-NEXT: [[T5:%.*]] = and i1 [[T1]], [[T4]]
626; CHECK-NEXT: ret i1 [[T5]]
627;
628 %t1 = icmp sgt i32 %arg, -1 ; checks a bit outside of the i16
629 %t2 = trunc i32 %arg to i16
630 %t3 = add i16 %t2, 128
631 %t4 = icmp ult i16 %t3, 256
632 %t5 = and i1 %t1, %t4
633 ret i1 %t5
634}