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.
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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