[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / Transforms / InstSimplify / result-of-usub-is-non-zero-and-no-overflow.ll
blobfd473ac9d251fcadd17b4afb689579e30d5387cd
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt %s -instsimplify -S | FileCheck %s
4 ; Here we subtract two values, check that subtraction did not overflow AND
5 ; that the result is non-zero. This can be simplified just to a comparison
6 ; between the base and offset.
8 declare void @use8(i8)
9 declare void @use64(i64)
10 declare void @use1(i1)
12 declare void @llvm.assume(i1)
14 ; If we are checking that we either did not get null or got no overflow,
15 ; this is tautological and is always true.
17 define i1 @commutativity0(i8 %base, i8 %offset) {
18 ; CHECK-LABEL: @commutativity0(
19 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
20 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
21 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]]
22 ; CHECK-NEXT:    call void @use1(i1 [[NO_UNDERFLOW]])
23 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
24 ; CHECK-NEXT:    call void @use1(i1 [[NOT_NULL]])
25 ; CHECK-NEXT:    ret i1 true
27   %adjusted = sub i8 %base, %offset
28   call void @use8(i8 %adjusted)
29   %no_underflow = icmp uge i8 %base, %offset
30   call void @use1(i1 %no_underflow)
31   %not_null = icmp ne i8 %adjusted, 0
32   call void @use1(i1 %not_null)
33   %r = or i1 %not_null, %no_underflow
34   ret i1 %r
36 define i1 @commutativity1(i8 %base, i8 %offset) {
37 ; CHECK-LABEL: @commutativity1(
38 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
39 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
40 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[OFFSET]], [[BASE]]
41 ; CHECK-NEXT:    call void @use1(i1 [[NO_UNDERFLOW]])
42 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
43 ; CHECK-NEXT:    call void @use1(i1 [[NOT_NULL]])
44 ; CHECK-NEXT:    ret i1 true
46   %adjusted = sub i8 %base, %offset
47   call void @use8(i8 %adjusted)
48   %no_underflow = icmp ule i8 %offset, %base ; swapped
49   call void @use1(i1 %no_underflow)
50   %not_null = icmp ne i8 %adjusted, 0
51   call void @use1(i1 %not_null)
52   %r = or i1 %not_null, %no_underflow
53   ret i1 %r
55 define i1 @commutativity2(i8 %base, i8 %offset) {
56 ; CHECK-LABEL: @commutativity2(
57 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
58 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
59 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]]
60 ; CHECK-NEXT:    call void @use1(i1 [[NO_UNDERFLOW]])
61 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
62 ; CHECK-NEXT:    call void @use1(i1 [[NOT_NULL]])
63 ; CHECK-NEXT:    ret i1 true
65   %adjusted = sub i8 %base, %offset
66   call void @use8(i8 %adjusted)
67   %no_underflow = icmp uge i8 %base, %offset
68   call void @use1(i1 %no_underflow)
69   %not_null = icmp ne i8 %adjusted, 0
70   call void @use1(i1 %not_null)
71   %r = or i1 %no_underflow, %not_null ; swapped
72   ret i1 %r
75 define i1 @commutativity3(i8 %base, i8 %offset) {
76 ; CHECK-LABEL: @commutativity3(
77 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
78 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
79 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[OFFSET]], [[BASE]]
80 ; CHECK-NEXT:    call void @use1(i1 [[NO_UNDERFLOW]])
81 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
82 ; CHECK-NEXT:    call void @use1(i1 [[NOT_NULL]])
83 ; CHECK-NEXT:    ret i1 true
85   %adjusted = sub i8 %base, %offset
86   call void @use8(i8 %adjusted)
87   %no_underflow = icmp ule i8 %offset, %base ; swapped
88   call void @use1(i1 %no_underflow)
89   %not_null = icmp ne i8 %adjusted, 0
90   call void @use1(i1 %not_null)
91   %r = or i1 %no_underflow, %not_null ; swapped
92   ret i1 %r
95 ;-------------------------------------------------------------------------------
97 define i1 @exaustive_t0_no_underflow(i8 %base, i8 %offset) {
98 ; CHECK-LABEL: @exaustive_t0_no_underflow(
99 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
100 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
101 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[BASE]], [[OFFSET]]
102 ; CHECK-NEXT:    ret i1 [[NO_UNDERFLOW]]
104   %adjusted = sub i8 %base, %offset
105   call void @use8(i8 %adjusted)
106   %not_null = icmp ne i8 %adjusted, 0
107   %no_underflow = icmp ult i8 %base, %offset
108   %r = and i1 %no_underflow, %not_null
109   ret i1 %r
112 define i1 @exaustive_t1_not_null(i8 %base, i8 %offset) {
113 ; CHECK-LABEL: @exaustive_t1_not_null(
114 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
115 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
116 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
117 ; CHECK-NEXT:    ret i1 [[NOT_NULL]]
119   %adjusted = sub i8 %base, %offset
120   call void @use8(i8 %adjusted)
121   %not_null = icmp ne i8 %adjusted, 0
122   %no_underflow = icmp ult i8 %base, %offset
123   %r = or i1 %no_underflow, %not_null
124   ret i1 %r
127 define i1 @exaustive_t2_false(i8 %base, i8 %offset) {
128 ; CHECK-LABEL: @exaustive_t2_false(
129 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
130 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
131 ; CHECK-NEXT:    ret i1 false
133   %adjusted = sub i8 %base, %offset
134   call void @use8(i8 %adjusted)
135   %not_null = icmp eq i8 %adjusted, 0
136   %no_underflow = icmp ult i8 %base, %offset
137   %r = and i1 %no_underflow, %not_null
138   ret i1 %r
141 define i1 @exaustive_t3_bad(i8 %base, i8 %offset) {
142 ; CHECK-LABEL: @exaustive_t3_bad(
143 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
144 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
145 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0
146 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[BASE]], [[OFFSET]]
147 ; CHECK-NEXT:    [[R:%.*]] = or i1 [[NO_UNDERFLOW]], [[NOT_NULL]]
148 ; CHECK-NEXT:    ret i1 [[R]]
150   %adjusted = sub i8 %base, %offset
151   call void @use8(i8 %adjusted)
152   %not_null = icmp eq i8 %adjusted, 0
153   %no_underflow = icmp ult i8 %base, %offset
154   %r = or i1 %no_underflow, %not_null
155   ret i1 %r
158 define i1 @exaustive_t4_no_underflow(i8 %base, i8 %offset) {
159 ; CHECK-LABEL: @exaustive_t4_no_underflow(
160 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
161 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
162 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp ugt i8 [[BASE]], [[OFFSET]]
163 ; CHECK-NEXT:    ret i1 [[NO_UNDERFLOW]]
165   %adjusted = sub i8 %base, %offset
166   call void @use8(i8 %adjusted)
167   %not_null = icmp ne i8 %adjusted, 0
168   %no_underflow = icmp ugt i8 %base, %offset
169   %r = and i1 %no_underflow, %not_null
170   ret i1 %r
173 define i1 @exaustive_t5_not_null(i8 %base, i8 %offset) {
174 ; CHECK-LABEL: @exaustive_t5_not_null(
175 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
176 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
177 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
178 ; CHECK-NEXT:    ret i1 [[NOT_NULL]]
180   %adjusted = sub i8 %base, %offset
181   call void @use8(i8 %adjusted)
182   %not_null = icmp ne i8 %adjusted, 0
183   %no_underflow = icmp ugt i8 %base, %offset
184   %r = or i1 %no_underflow, %not_null
185   ret i1 %r
188 define i1 @exaustive_t6_false(i8 %base, i8 %offset) {
189 ; CHECK-LABEL: @exaustive_t6_false(
190 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
191 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
192 ; CHECK-NEXT:    ret i1 false
194   %adjusted = sub i8 %base, %offset
195   call void @use8(i8 %adjusted)
196   %not_null = icmp eq i8 %adjusted, 0
197   %no_underflow = icmp ugt i8 %base, %offset
198   %r = and i1 %no_underflow, %not_null
199   ret i1 %r
202 define i1 @exaustive_t7_bad(i8 %base, i8 %offset) {
203 ; CHECK-LABEL: @exaustive_t7_bad(
204 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
205 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
206 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0
207 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp ugt i8 [[BASE]], [[OFFSET]]
208 ; CHECK-NEXT:    [[R:%.*]] = or i1 [[NO_UNDERFLOW]], [[NOT_NULL]]
209 ; CHECK-NEXT:    ret i1 [[R]]
211   %adjusted = sub i8 %base, %offset
212   call void @use8(i8 %adjusted)
213   %not_null = icmp eq i8 %adjusted, 0
214   %no_underflow = icmp ugt i8 %base, %offset
215   %r = or i1 %no_underflow, %not_null
216   ret i1 %r
219 define i1 @exaustive_t8_bad(i8 %base, i8 %offset) {
220 ; CHECK-LABEL: @exaustive_t8_bad(
221 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
222 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
223 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
224 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[BASE]], [[OFFSET]]
225 ; CHECK-NEXT:    [[R:%.*]] = and i1 [[NO_UNDERFLOW]], [[NOT_NULL]]
226 ; CHECK-NEXT:    ret i1 [[R]]
228   %adjusted = sub i8 %base, %offset
229   call void @use8(i8 %adjusted)
230   %not_null = icmp ne i8 %adjusted, 0
231   %no_underflow = icmp ule i8 %base, %offset
232   %r = and i1 %no_underflow, %not_null
233   ret i1 %r
236 define i1 @exaustive_t9_true(i8 %base, i8 %offset) {
237 ; CHECK-LABEL: @exaustive_t9_true(
238 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
239 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
240 ; CHECK-NEXT:    ret i1 true
242   %adjusted = sub i8 %base, %offset
243   call void @use8(i8 %adjusted)
244   %not_null = icmp ne i8 %adjusted, 0
245   %no_underflow = icmp ule i8 %base, %offset
246   %r = or i1 %no_underflow, %not_null
247   ret i1 %r
250 define i1 @exaustive_t10_not_null(i8 %base, i8 %offset) {
251 ; CHECK-LABEL: @exaustive_t10_not_null(
252 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
253 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
254 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0
255 ; CHECK-NEXT:    ret i1 [[NOT_NULL]]
257   %adjusted = sub i8 %base, %offset
258   call void @use8(i8 %adjusted)
259   %not_null = icmp eq i8 %adjusted, 0
260   %no_underflow = icmp ule i8 %base, %offset
261   %r = and i1 %no_underflow, %not_null
262   ret i1 %r
265 define i1 @exaustive_t11_no_underflow(i8 %base, i8 %offset) {
266 ; CHECK-LABEL: @exaustive_t11_no_underflow(
267 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
268 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
269 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[BASE]], [[OFFSET]]
270 ; CHECK-NEXT:    ret i1 [[NO_UNDERFLOW]]
272   %adjusted = sub i8 %base, %offset
273   call void @use8(i8 %adjusted)
274   %not_null = icmp eq i8 %adjusted, 0
275   %no_underflow = icmp ule i8 %base, %offset
276   %r = or i1 %no_underflow, %not_null
277   ret i1 %r
280 define i1 @exaustive_t12_bad(i8 %base, i8 %offset) {
281 ; CHECK-LABEL: @exaustive_t12_bad(
282 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
283 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
284 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
285 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]]
286 ; CHECK-NEXT:    [[R:%.*]] = and i1 [[NO_UNDERFLOW]], [[NOT_NULL]]
287 ; CHECK-NEXT:    ret i1 [[R]]
289   %adjusted = sub i8 %base, %offset
290   call void @use8(i8 %adjusted)
291   %not_null = icmp ne i8 %adjusted, 0
292   %no_underflow = icmp uge i8 %base, %offset
293   %r = and i1 %no_underflow, %not_null
294   ret i1 %r
297 define i1 @exaustive_t13_true(i8 %base, i8 %offset) {
298 ; CHECK-LABEL: @exaustive_t13_true(
299 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
300 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
301 ; CHECK-NEXT:    ret i1 true
303   %adjusted = sub i8 %base, %offset
304   call void @use8(i8 %adjusted)
305   %not_null = icmp ne i8 %adjusted, 0
306   %no_underflow = icmp uge i8 %base, %offset
307   %r = or i1 %no_underflow, %not_null
308   ret i1 %r
311 define i1 @exaustive_t14_not_null(i8 %base, i8 %offset) {
312 ; CHECK-LABEL: @exaustive_t14_not_null(
313 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
314 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
315 ; CHECK-NEXT:    [[NOT_NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0
316 ; CHECK-NEXT:    ret i1 [[NOT_NULL]]
318   %adjusted = sub i8 %base, %offset
319   call void @use8(i8 %adjusted)
320   %not_null = icmp eq i8 %adjusted, 0
321   %no_underflow = icmp uge i8 %base, %offset
322   %r = and i1 %no_underflow, %not_null
323   ret i1 %r
326 define i1 @exaustive_t15_no_underflow(i8 %base, i8 %offset) {
327 ; CHECK-LABEL: @exaustive_t15_no_underflow(
328 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]]
329 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
330 ; CHECK-NEXT:    [[NO_UNDERFLOW:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]]
331 ; CHECK-NEXT:    ret i1 [[NO_UNDERFLOW]]
333   %adjusted = sub i8 %base, %offset
334   call void @use8(i8 %adjusted)
335   %not_null = icmp eq i8 %adjusted, 0
336   %no_underflow = icmp uge i8 %base, %offset
337   %r = or i1 %no_underflow, %not_null
338   ret i1 %r