1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instsimplify -S | FileCheck %s
3
4; This is canonical form for this IR.
5
6define i1 @abs_nsw_is_positive(i32 %x) {
7; CHECK-LABEL: @abs_nsw_is_positive(
8; CHECK-NEXT:    ret i1 true
9;
10  %cmp = icmp slt i32 %x, 0
11  %negx = sub nsw i32 0, %x
12  %abs = select i1 %cmp, i32 %negx, i32 %x
13  %r = icmp sgt i32 %abs, -1
14  ret i1 %r
15}
16
17; Test non-canonical predicate and non-canonical form of abs().
18
19define i1 @abs_nsw_is_positive_sge(i32 %x) {
20; CHECK-LABEL: @abs_nsw_is_positive_sge(
21; CHECK-NEXT:    ret i1 true
22;
23  %cmp = icmp slt i32 %x, 1
24  %negx = sub nsw i32 0, %x
25  %abs = select i1 %cmp, i32 %negx, i32 %x
26  %r = icmp sge i32 %abs, 0
27  ret i1 %r
28}
29
30; This is a range-based analysis. Any negative constant works.
31
32define i1 @abs_nsw_is_positive_reduced_range(i32 %x) {
33; CHECK-LABEL: @abs_nsw_is_positive_reduced_range(
34; CHECK-NEXT:    ret i1 true
35;
36  %cmp = icmp slt i32 %x, 0
37  %negx = sub nsw i32 0, %x
38  %abs = select i1 %cmp, i32 %negx, i32 %x
39  %r = icmp sgt i32 %abs, -42
40  ret i1 %r
41}
42
43; Negative test - we need 'nsw' in the abs().
44
45define i1 @abs_is_positive_reduced_range(i32 %x) {
46; CHECK-LABEL: @abs_is_positive_reduced_range(
47; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
48; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
49; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
50; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[ABS]], 42
51; CHECK-NEXT:    ret i1 [[R]]
52;
53  %cmp = icmp slt i32 %x, 0
54  %negx = sub i32 0, %x
55  %abs = select i1 %cmp, i32 %negx, i32 %x
56  %r = icmp sgt i32 %abs, 42
57  ret i1 %r
58}
59
60; Negative test - range intersection is not subset.
61
62define i1 @abs_nsw_is_positive_wrong_range(i32 %x) {
63; CHECK-LABEL: @abs_nsw_is_positive_wrong_range(
64; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
65; CHECK-NEXT:    [[NEGX:%.*]] = sub nsw i32 0, [[X]]
66; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
67; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[ABS]], 0
68; CHECK-NEXT:    ret i1 [[R]]
69;
70  %cmp = icmp slt i32 %x, 0
71  %negx = sub nsw i32 0, %x
72  %abs = select i1 %cmp, i32 %negx, i32 %x
73  %r = icmp sgt i32 %abs, 0
74  ret i1 %r
75}
76
77; This is canonical form for this IR.
78
79define i1 @abs_nsw_is_not_negative(i32 %x) {
80; CHECK-LABEL: @abs_nsw_is_not_negative(
81; CHECK-NEXT:    ret i1 false
82;
83  %cmp = icmp slt i32 %x, 0
84  %negx = sub nsw i32 0, %x
85  %abs = select i1 %cmp, i32 %negx, i32 %x
86  %r = icmp slt i32 %abs, 0
87  ret i1 %r
88}
89
90; Test non-canonical predicate and non-canonical form of abs().
91
92define i1 @abs_nsw_is_not_negative_sle(i32 %x) {
93; CHECK-LABEL: @abs_nsw_is_not_negative_sle(
94; CHECK-NEXT:    ret i1 false
95;
96  %cmp = icmp slt i32 %x, 1
97  %negx = sub nsw i32 0, %x
98  %abs = select i1 %cmp, i32 %negx, i32 %x
99  %r = icmp sle i32 %abs, -1
100  ret i1 %r
101}
102
103; This is a range-based analysis. Any negative constant works.
104
105define i1 @abs_nsw_is_not_negative_reduced_range(i32 %x) {
106; CHECK-LABEL: @abs_nsw_is_not_negative_reduced_range(
107; CHECK-NEXT:    ret i1 false
108;
109  %cmp = icmp slt i32 %x, 0
110  %negx = sub nsw i32 0, %x
111  %abs = select i1 %cmp, i32 %negx, i32 %x
112  %r = icmp slt i32 %abs, -24
113  ret i1 %r
114}
115
116; Negative test - we need 'nsw' in the abs().
117
118define i1 @abs_is_not_negative_reduced_range(i32 %x) {
119; CHECK-LABEL: @abs_is_not_negative_reduced_range(
120; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
121; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
122; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
123; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[ABS]], 42
124; CHECK-NEXT:    ret i1 [[R]]
125;
126  %cmp = icmp slt i32 %x, 0
127  %negx = sub i32 0, %x
128  %abs = select i1 %cmp, i32 %negx, i32 %x
129  %r = icmp slt i32 %abs, 42
130  ret i1 %r
131}
132
133; Negative test - range intersection is not empty.
134
135define i1 @abs_nsw_is_not_negative_wrong_range(i32 %x) {
136; CHECK-LABEL: @abs_nsw_is_not_negative_wrong_range(
137; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
138; CHECK-NEXT:    [[NEGX:%.*]] = sub nsw i32 0, [[X]]
139; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
140; CHECK-NEXT:    [[R:%.*]] = icmp sle i32 [[ABS]], 0
141; CHECK-NEXT:    ret i1 [[R]]
142;
143  %cmp = icmp slt i32 %x, 0
144  %negx = sub nsw i32 0, %x
145  %abs = select i1 %cmp, i32 %negx, i32 %x
146  %r = icmp sle i32 %abs, 0
147  ret i1 %r
148}
149
150; Even if we don't have nsw, the range is still limited in the unsigned domain.
151define i1 @abs_positive_or_signed_min(i32 %x) {
152; CHECK-LABEL: @abs_positive_or_signed_min(
153; CHECK-NEXT:    ret i1 true
154;
155  %cmp = icmp slt i32 %x, 0
156  %negx = sub i32 0, %x
157  %abs = select i1 %cmp, i32 %negx, i32 %x
158  %r = icmp ult i32 %abs, 2147483649
159  ret i1 %r
160}
161
162define i1 @abs_positive_or_signed_min_reduced_range(i32 %x) {
163; CHECK-LABEL: @abs_positive_or_signed_min_reduced_range(
164; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
165; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
166; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGX]], i32 [[X]]
167; CHECK-NEXT:    [[R:%.*]] = icmp ult i32 [[ABS]], -2147483648
168; CHECK-NEXT:    ret i1 [[R]]
169;
170  %cmp = icmp slt i32 %x, 0
171  %negx = sub i32 0, %x
172  %abs = select i1 %cmp, i32 %negx, i32 %x
173  %r = icmp ult i32 %abs, 2147483648
174  ret i1 %r
175}
176
177; This is canonical form for this IR. For nabs(), we don't require 'nsw'
178
179define i1 @nabs_is_negative_or_0(i32 %x) {
180; CHECK-LABEL: @nabs_is_negative_or_0(
181; CHECK-NEXT:    ret i1 true
182;
183  %cmp = icmp slt i32 %x, 0
184  %negx = sub i32 0, %x
185  %nabs = select i1 %cmp, i32 %x, i32 %negx
186  %r = icmp slt i32 %nabs, 1
187  ret i1 %r
188}
189
190; Test non-canonical predicate and non-canonical form of nabs().
191
192define i1 @nabs_is_negative_or_0_sle(i32 %x) {
193; CHECK-LABEL: @nabs_is_negative_or_0_sle(
194; CHECK-NEXT:    ret i1 true
195;
196  %cmp = icmp slt i32 %x, 1
197  %negx = sub i32 0, %x
198  %nabs = select i1 %cmp, i32 %x, i32 %negx
199  %r = icmp sle i32 %nabs, 0
200  ret i1 %r
201}
202
203; This is a range-based analysis. Any positive constant works.
204
205define i1 @nabs_is_negative_or_0_reduced_range(i32 %x) {
206; CHECK-LABEL: @nabs_is_negative_or_0_reduced_range(
207; CHECK-NEXT:    ret i1 true
208;
209  %cmp = icmp slt i32 %x, 1
210  %negx = sub i32 0, %x
211  %nabs = select i1 %cmp, i32 %x, i32 %negx
212  %r = icmp slt i32 %nabs, 421
213  ret i1 %r
214}
215
216; Negative test - range intersection is not subset.
217
218define i1 @nabs_is_negative_or_0_wrong_range(i32 %x) {
219; CHECK-LABEL: @nabs_is_negative_or_0_wrong_range(
220; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
221; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
222; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
223; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[NABS]], 0
224; CHECK-NEXT:    ret i1 [[R]]
225;
226  %cmp = icmp slt i32 %x, 1
227  %negx = sub i32 0, %x
228  %nabs = select i1 %cmp, i32 %x, i32 %negx
229  %r = icmp slt i32 %nabs, 0
230  ret i1 %r
231}
232
233; This is canonical form for this IR. For nabs(), we don't require 'nsw'
234
235define i1 @nabs_is_not_over_0(i32 %x) {
236; CHECK-LABEL: @nabs_is_not_over_0(
237; CHECK-NEXT:    ret i1 false
238;
239  %cmp = icmp slt i32 %x, 0
240  %negx = sub i32 0, %x
241  %nabs = select i1 %cmp, i32 %x, i32 %negx
242  %r = icmp sgt i32 %nabs, 0
243  ret i1 %r
244}
245
246; Test non-canonical predicate and non-canonical form of nabs().
247
248define i1 @nabs_is_not_over_0_sle(i32 %x) {
249; CHECK-LABEL: @nabs_is_not_over_0_sle(
250; CHECK-NEXT:    ret i1 false
251;
252  %cmp = icmp slt i32 %x, 1
253  %negx = sub i32 0, %x
254  %nabs = select i1 %cmp, i32 %x, i32 %negx
255  %r = icmp sge i32 %nabs, 1
256  ret i1 %r
257}
258
259; This is a range-based analysis. Any positive constant works.
260
261define i1 @nabs_is_not_over_0_reduced_range(i32 %x) {
262; CHECK-LABEL: @nabs_is_not_over_0_reduced_range(
263; CHECK-NEXT:    ret i1 false
264;
265  %cmp = icmp slt i32 %x, 1
266  %negx = sub i32 0, %x
267  %nabs = select i1 %cmp, i32 %x, i32 %negx
268  %r = icmp sgt i32 %nabs, 4223
269  ret i1 %r
270}
271
272; Negative test - range intersection is not subset.
273
274define i1 @nabs_is_not_over_0_wrong_range(i32 %x) {
275; CHECK-LABEL: @nabs_is_not_over_0_wrong_range(
276; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1
277; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
278; CHECK-NEXT:    [[NABS:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[NEGX]]
279; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[NABS]], -1
280; CHECK-NEXT:    ret i1 [[R]]
281;
282  %cmp = icmp slt i32 %x, 1
283  %negx = sub i32 0, %x
284  %nabs = select i1 %cmp, i32 %x, i32 %negx
285  %r = icmp sgt i32 %nabs, -1
286  ret i1 %r
287}
288
289; More miscellaneous tests for predicates/types.
290
291; Equality predicates are ok.
292
293define i1 @abs_nsw_is_positive_eq(i32 %x) {
294; CHECK-LABEL: @abs_nsw_is_positive_eq(
295; CHECK-NEXT:    ret i1 false
296;
297  %cmp = icmp slt i32 %x, 1
298  %negx = sub nsw i32 0, %x
299  %abs = select i1 %cmp, i32 %negx, i32 %x
300  %r = icmp eq i32 %abs, -8
301  ret i1 %r
302}
303
304; An unsigned compare may work.
305
306define i1 @abs_nsw_is_positive_ult(i8 %x) {
307; CHECK-LABEL: @abs_nsw_is_positive_ult(
308; CHECK-NEXT:    ret i1 true
309;
310  %cmp = icmp slt i8 %x, 0
311  %negx = sub nsw i8 0, %x
312  %abs = select i1 %cmp, i8 %negx, i8 %x
313  %r = icmp ult i8 %abs, 139
314  ret i1 %r
315}
316
317; An unsigned compare may work.
318
319define i1 @abs_nsw_is_not_negative_ugt(i8 %x) {
320; CHECK-LABEL: @abs_nsw_is_not_negative_ugt(
321; CHECK-NEXT:    ret i1 false
322;
323  %cmp = icmp slt i8 %x, 0
324  %negx = sub nsw i8 0, %x
325  %abs = select i1 %cmp, i8 %negx, i8 %x
326  %r = icmp ugt i8 %abs, 127
327  ret i1 %r
328}
329
330; Vector types are ok.
331
332define <2 x i1> @abs_nsw_is_not_negative_vec_splat(<2 x i32> %x) {
333; CHECK-LABEL: @abs_nsw_is_not_negative_vec_splat(
334; CHECK-NEXT:    ret <2 x i1> zeroinitializer
335;
336  %cmp = icmp slt <2 x i32> %x, zeroinitializer
337  %negx = sub nsw <2 x i32> zeroinitializer, %x
338  %abs = select <2 x i1> %cmp, <2 x i32> %negx, <2 x i32> %x
339  %r = icmp slt <2 x i32> %abs, <i32 -8, i32 -8>
340  ret <2 x i1> %r
341}
342
343; Equality predicates are ok.
344
345define i1 @nabs_is_negative_or_0_ne(i8 %x) {
346; CHECK-LABEL: @nabs_is_negative_or_0_ne(
347; CHECK-NEXT:    ret i1 true
348;
349  %cmp = icmp slt i8 %x, 0
350  %negx = sub i8 0, %x
351  %nabs = select i1 %cmp, i8 %x, i8 %negx
352  %r = icmp ne i8 %nabs, 12
353  ret i1 %r
354}
355
356; Vector types are ok.
357
358define <3 x i1> @nabs_is_not_over_0_sle_vec_splat(<3 x i33> %x) {
359; CHECK-LABEL: @nabs_is_not_over_0_sle_vec_splat(
360; CHECK-NEXT:    ret <3 x i1> zeroinitializer
361;
362  %cmp = icmp slt <3 x i33> %x, <i33 1, i33 1, i33 1>
363  %negx = sub <3 x i33> zeroinitializer, %x
364  %nabs = select <3 x i1> %cmp, <3 x i33> %x, <3 x i33> %negx
365  %r = icmp sge <3 x i33> %nabs, <i33 1, i33 1, i33 1>
366  ret <3 x i1> %r
367}
368
369; Negative test - intersection does not equal absolute value range.
370; PR39510 - https://bugs.llvm.org/show_bug.cgi?id=39510
371
372define i1 @abs_no_intersection(i32 %a) {
373; CHECK-LABEL: @abs_no_intersection(
374; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A:%.*]], 0
375; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 0, [[A]]
376; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[A]]
377; CHECK-NEXT:    [[R:%.*]] = icmp ne i32 [[COND]], 2
378; CHECK-NEXT:    ret i1 [[R]]
379;
380  %cmp = icmp slt i32 %a, 0
381  %sub = sub nsw i32 0, %a
382  %cond = select i1 %cmp, i32 %sub, i32 %a
383  %r = icmp ne i32 %cond, 2
384  ret i1 %r
385}
386
387; Negative test - intersection does not equal absolute value range.
388
389define i1 @nabs_no_intersection(i32 %a) {
390; CHECK-LABEL: @nabs_no_intersection(
391; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 0
392; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[A]]
393; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[A]]
394; CHECK-NEXT:    [[R:%.*]] = icmp ne i32 [[COND]], -2
395; CHECK-NEXT:    ret i1 [[R]]
396;
397  %cmp = icmp sgt i32 %a, 0
398  %sub = sub i32 0, %a
399  %cond = select i1 %cmp, i32 %sub, i32 %a
400  %r = icmp ne i32 %cond, -2
401  ret i1 %r
402}
403
404; We can't fold this to false unless both subs have nsw.
405define i1 @abs_sub_sub_missing_nsw(i32 %x, i32 %y) {
406; CHECK-LABEL: @abs_sub_sub_missing_nsw(
407; CHECK-NEXT:    [[A:%.*]] = sub i32 [[X:%.*]], [[Y:%.*]]
408; CHECK-NEXT:    [[B:%.*]] = sub nsw i32 [[Y]], [[X]]
409; CHECK-NEXT:    [[C:%.*]] = icmp sgt i32 [[A]], -1
410; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[A]], i32 [[B]]
411; CHECK-NEXT:    [[E:%.*]] = icmp slt i32 [[D]], 0
412; CHECK-NEXT:    ret i1 [[E]]
413;
414  %a = sub i32 %x, %y
415  %b = sub nsw i32 %y, %x
416  %c = icmp sgt i32 %a, -1
417  %d = select i1 %c, i32 %a, i32 %b
418  %e = icmp slt i32 %d, 0
419  ret i1 %e
420}
421