[ARM] Better OR's for MVE compares
[llvm-core.git] / test / Transforms / InstSimplify / icmp-abs-nabs.ll
blobbe2e7b4d4a609860dada3f9fa8ff5d579bd47a07
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instsimplify -S | FileCheck %s
4 ; This is canonical form for this IR.
6 define i1 @abs_nsw_is_positive(i32 %x) {
7 ; CHECK-LABEL: @abs_nsw_is_positive(
8 ; CHECK-NEXT:    ret i1 true
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
17 ; Test non-canonical predicate and non-canonical form of abs().
19 define i1 @abs_nsw_is_positive_sge(i32 %x) {
20 ; CHECK-LABEL: @abs_nsw_is_positive_sge(
21 ; CHECK-NEXT:    ret i1 true
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
30 ; This is a range-based analysis. Any negative constant works.
32 define i1 @abs_nsw_is_positive_reduced_range(i32 %x) {
33 ; CHECK-LABEL: @abs_nsw_is_positive_reduced_range(
34 ; CHECK-NEXT:    ret i1 true
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
43 ; Negative test - we need 'nsw' in the abs().
45 define 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]]
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
60 ; Negative test - range intersection is not subset.
62 define 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]]
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
77 ; This is canonical form for this IR.
79 define i1 @abs_nsw_is_not_negative(i32 %x) {
80 ; CHECK-LABEL: @abs_nsw_is_not_negative(
81 ; CHECK-NEXT:    ret i1 false
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
90 ; Test non-canonical predicate and non-canonical form of abs().
92 define i1 @abs_nsw_is_not_negative_sle(i32 %x) {
93 ; CHECK-LABEL: @abs_nsw_is_not_negative_sle(
94 ; CHECK-NEXT:    ret i1 false
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
103 ; This is a range-based analysis. Any negative constant works.
105 define 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
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
116 ; Negative test - we need 'nsw' in the abs().
118 define 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]]
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
133 ; Negative test - range intersection is not empty.
135 define 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]]
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
150 ; Even if we don't have nsw, the range is still limited in the unsigned domain.
151 define i1 @abs_positive_or_signed_min(i32 %x) {
152 ; CHECK-LABEL: @abs_positive_or_signed_min(
153 ; CHECK-NEXT:    ret i1 true
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
162 define 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]]
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
177 ; This is canonical form for this IR. For nabs(), we don't require 'nsw'
179 define i1 @nabs_is_negative_or_0(i32 %x) {
180 ; CHECK-LABEL: @nabs_is_negative_or_0(
181 ; CHECK-NEXT:    ret i1 true
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
190 ; Test non-canonical predicate and non-canonical form of nabs().
192 define i1 @nabs_is_negative_or_0_sle(i32 %x) {
193 ; CHECK-LABEL: @nabs_is_negative_or_0_sle(
194 ; CHECK-NEXT:    ret i1 true
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
203 ; This is a range-based analysis. Any positive constant works.
205 define 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
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
216 ; Negative test - range intersection is not subset.
218 define 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]]
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
233 ; This is canonical form for this IR. For nabs(), we don't require 'nsw'
235 define i1 @nabs_is_not_over_0(i32 %x) {
236 ; CHECK-LABEL: @nabs_is_not_over_0(
237 ; CHECK-NEXT:    ret i1 false
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
246 ; Test non-canonical predicate and non-canonical form of nabs().
248 define i1 @nabs_is_not_over_0_sle(i32 %x) {
249 ; CHECK-LABEL: @nabs_is_not_over_0_sle(
250 ; CHECK-NEXT:    ret i1 false
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
259 ; This is a range-based analysis. Any positive constant works.
261 define 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
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
272 ; Negative test - range intersection is not subset.
274 define 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]]
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
289 ; More miscellaneous tests for predicates/types.
291 ; Equality predicates are ok.
293 define i1 @abs_nsw_is_positive_eq(i32 %x) {
294 ; CHECK-LABEL: @abs_nsw_is_positive_eq(
295 ; CHECK-NEXT:    ret i1 false
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
304 ; An unsigned compare may work.
306 define i1 @abs_nsw_is_positive_ult(i8 %x) {
307 ; CHECK-LABEL: @abs_nsw_is_positive_ult(
308 ; CHECK-NEXT:    ret i1 true
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
317 ; An unsigned compare may work.
319 define i1 @abs_nsw_is_not_negative_ugt(i8 %x) {
320 ; CHECK-LABEL: @abs_nsw_is_not_negative_ugt(
321 ; CHECK-NEXT:    ret i1 false
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
330 ; Vector types are ok.
332 define <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
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
343 ; Equality predicates are ok.
345 define i1 @nabs_is_negative_or_0_ne(i8 %x) {
346 ; CHECK-LABEL: @nabs_is_negative_or_0_ne(
347 ; CHECK-NEXT:    ret i1 true
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
356 ; Vector types are ok.
358 define <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
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
369 ; Negative test - intersection does not equal absolute value range.
370 ; PR39510 - https://bugs.llvm.org/show_bug.cgi?id=39510
372 define 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]]
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
387 ; Negative test - intersection does not equal absolute value range.
389 define 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]]
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