1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
7 declare void @llvm.assume(i1)
9 ; Here we don't know that at least one of the values being added is non-zero
10 define i1 @t0_bad(i8 %base, i8 %offset) {
11 ; CHECK-LABEL: @t0_bad(
12 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
13 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
14 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
15 ; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[ADJUSTED]], [[BASE]]
16 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]
17 ; CHECK-NEXT: ret i1 [[R]]
19 %adjusted = add i8 %base, %offset
20 call void @use8(i8 %adjusted)
21 %not_null = icmp ne i8 %adjusted, 0
22 %no_underflow = icmp ult i8 %adjusted, %base
23 %r = and i1 %not_null, %no_underflow
27 define i1 @t0_bad_logical(i8 %base, i8 %offset) {
28 ; CHECK-LABEL: @t0_bad_logical(
29 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
30 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
31 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
32 ; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[ADJUSTED]], [[BASE]]
33 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]
34 ; CHECK-NEXT: ret i1 [[R]]
36 %adjusted = add i8 %base, %offset
37 call void @use8(i8 %adjusted)
38 %not_null = icmp ne i8 %adjusted, 0
39 %no_underflow = icmp ult i8 %adjusted, %base
40 %r = select i1 %not_null, i1 %no_underflow, i1 false
44 ; Ok, base is non-zero.
45 define i1 @t1(i8 %base, i8 %offset) {
47 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
48 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
49 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
50 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
51 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
52 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
53 ; CHECK-NEXT: ret i1 [[TMP2]]
55 %cmp = icmp slt i8 %base, 0
56 call void @llvm.assume(i1 %cmp)
58 %adjusted = add i8 %base, %offset
59 call void @use8(i8 %adjusted)
60 %not_null = icmp ne i8 %adjusted, 0
61 %no_underflow = icmp ult i8 %adjusted, %base
62 %r = and i1 %not_null, %no_underflow
66 define i1 @t1_logical(i8 %base, i8 %offset) {
67 ; CHECK-LABEL: @t1_logical(
68 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
69 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
70 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
71 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
72 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
73 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
74 ; CHECK-NEXT: ret i1 [[TMP2]]
76 %cmp = icmp slt i8 %base, 0
77 call void @llvm.assume(i1 %cmp)
79 %adjusted = add i8 %base, %offset
80 call void @use8(i8 %adjusted)
81 %not_null = icmp ne i8 %adjusted, 0
82 %no_underflow = icmp ult i8 %adjusted, %base
83 %r = select i1 %not_null, i1 %no_underflow, i1 false
87 ; Ok, offset is non-zero.
88 define i1 @t2(i8 %base, i8 %offset) {
90 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[OFFSET:%.*]], 0
91 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
92 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET]]
93 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
94 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
95 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
96 ; CHECK-NEXT: ret i1 [[TMP2]]
98 %cmp = icmp slt i8 %offset, 0
99 call void @llvm.assume(i1 %cmp)
101 %adjusted = add i8 %base, %offset
102 call void @use8(i8 %adjusted)
103 %not_null = icmp ne i8 %adjusted, 0
104 %no_underflow = icmp ult i8 %adjusted, %base
105 %r = and i1 %not_null, %no_underflow
109 define i1 @t2_logical(i8 %base, i8 %offset) {
110 ; CHECK-LABEL: @t2_logical(
111 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[OFFSET:%.*]], 0
112 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
113 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET]]
114 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
115 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
116 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[BASE]]
117 ; CHECK-NEXT: ret i1 [[TMP2]]
119 %cmp = icmp slt i8 %offset, 0
120 call void @llvm.assume(i1 %cmp)
122 %adjusted = add i8 %base, %offset
123 call void @use8(i8 %adjusted)
124 %not_null = icmp ne i8 %adjusted, 0
125 %no_underflow = icmp ult i8 %adjusted, %base
126 %r = select i1 %not_null, i1 %no_underflow, i1 false
130 ; We need to produce extra instruction, so one of icmp's must go away.
131 define i1 @t3_oneuse0(i8 %base, i8 %offset) {
132 ; CHECK-LABEL: @t3_oneuse0(
133 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
134 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
135 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
136 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
137 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
138 ; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])
139 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
140 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
141 ; CHECK-NEXT: ret i1 [[TMP2]]
143 %cmp = icmp slt i8 %base, 0
144 call void @llvm.assume(i1 %cmp)
146 %adjusted = add i8 %base, %offset
147 call void @use8(i8 %adjusted)
148 %not_null = icmp ne i8 %adjusted, 0
149 call void @use1(i1 %not_null)
150 %no_underflow = icmp ult i8 %adjusted, %base
151 %r = and i1 %not_null, %no_underflow
155 define i1 @t3_oneuse0_logical(i8 %base, i8 %offset) {
156 ; CHECK-LABEL: @t3_oneuse0_logical(
157 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
158 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
159 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
160 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
161 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
162 ; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])
163 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
164 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
165 ; CHECK-NEXT: ret i1 [[TMP2]]
167 %cmp = icmp slt i8 %base, 0
168 call void @llvm.assume(i1 %cmp)
170 %adjusted = add i8 %base, %offset
171 call void @use8(i8 %adjusted)
172 %not_null = icmp ne i8 %adjusted, 0
173 call void @use1(i1 %not_null)
174 %no_underflow = icmp ult i8 %adjusted, %base
175 %r = select i1 %not_null, i1 %no_underflow, i1 false
178 define i1 @t4_oneuse1(i8 %base, i8 %offset) {
179 ; CHECK-LABEL: @t4_oneuse1(
180 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
181 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
182 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
183 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
184 ; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[ADJUSTED]], [[BASE]]
185 ; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])
186 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
187 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
188 ; CHECK-NEXT: ret i1 [[TMP2]]
190 %cmp = icmp slt i8 %base, 0
191 call void @llvm.assume(i1 %cmp)
193 %adjusted = add i8 %base, %offset
194 call void @use8(i8 %adjusted)
195 %not_null = icmp ne i8 %adjusted, 0
196 %no_underflow = icmp ult i8 %adjusted, %base
197 call void @use1(i1 %no_underflow)
198 %r = and i1 %not_null, %no_underflow
202 define i1 @t4_oneuse1_logical(i8 %base, i8 %offset) {
203 ; CHECK-LABEL: @t4_oneuse1_logical(
204 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
205 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
206 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
207 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
208 ; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[ADJUSTED]], [[BASE]]
209 ; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])
210 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
211 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
212 ; CHECK-NEXT: ret i1 [[TMP2]]
214 %cmp = icmp slt i8 %base, 0
215 call void @llvm.assume(i1 %cmp)
217 %adjusted = add i8 %base, %offset
218 call void @use8(i8 %adjusted)
219 %not_null = icmp ne i8 %adjusted, 0
220 %no_underflow = icmp ult i8 %adjusted, %base
221 call void @use1(i1 %no_underflow)
222 %r = select i1 %not_null, i1 %no_underflow, i1 false
225 define i1 @t5_oneuse2_bad(i8 %base, i8 %offset) {
226 ; CHECK-LABEL: @t5_oneuse2_bad(
227 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
228 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
229 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
230 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
231 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
232 ; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])
233 ; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[ADJUSTED]], [[BASE]]
234 ; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])
235 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]
236 ; CHECK-NEXT: ret i1 [[R]]
238 %cmp = icmp slt i8 %base, 0
239 call void @llvm.assume(i1 %cmp)
241 %adjusted = add i8 %base, %offset
242 call void @use8(i8 %adjusted)
243 %not_null = icmp ne i8 %adjusted, 0
244 call void @use1(i1 %not_null)
245 %no_underflow = icmp ult i8 %adjusted, %base
246 call void @use1(i1 %no_underflow)
247 %r = and i1 %not_null, %no_underflow
251 define i1 @t5_oneuse2_bad_logical(i8 %base, i8 %offset) {
252 ; CHECK-LABEL: @t5_oneuse2_bad_logical(
253 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
254 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
255 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
256 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
257 ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0
258 ; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]])
259 ; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[ADJUSTED]], [[BASE]]
260 ; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]])
261 ; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]]
262 ; CHECK-NEXT: ret i1 [[R]]
264 %cmp = icmp slt i8 %base, 0
265 call void @llvm.assume(i1 %cmp)
267 %adjusted = add i8 %base, %offset
268 call void @use8(i8 %adjusted)
269 %not_null = icmp ne i8 %adjusted, 0
270 call void @use1(i1 %not_null)
271 %no_underflow = icmp ult i8 %adjusted, %base
272 call void @use1(i1 %no_underflow)
273 %r = select i1 %not_null, i1 %no_underflow, i1 false
277 define i1 @t6_commutativity0(i8 %base, i8 %offset) {
278 ; CHECK-LABEL: @t6_commutativity0(
279 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
280 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
281 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
282 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
283 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
284 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
285 ; CHECK-NEXT: ret i1 [[TMP2]]
287 %cmp = icmp slt i8 %base, 0
288 call void @llvm.assume(i1 %cmp)
290 %adjusted = add i8 %base, %offset
291 call void @use8(i8 %adjusted)
292 %not_null = icmp ne i8 %adjusted, 0
293 %no_underflow = icmp ult i8 %adjusted, %base
294 %r = and i1 %no_underflow, %not_null ; swapped
298 define i1 @t6_commutativity0_logical(i8 %base, i8 %offset) {
299 ; CHECK-LABEL: @t6_commutativity0_logical(
300 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
301 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
302 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
303 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
304 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
305 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
306 ; CHECK-NEXT: ret i1 [[TMP2]]
308 %cmp = icmp slt i8 %base, 0
309 call void @llvm.assume(i1 %cmp)
311 %adjusted = add i8 %base, %offset
312 call void @use8(i8 %adjusted)
313 %not_null = icmp ne i8 %adjusted, 0
314 %no_underflow = icmp ult i8 %adjusted, %base
315 %r = select i1 %no_underflow, i1 %not_null, i1 false ; swapped
318 define i1 @t7_commutativity1(i8 %base, i8 %offset) {
319 ; CHECK-LABEL: @t7_commutativity1(
320 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
321 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
322 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
323 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
324 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
325 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
326 ; CHECK-NEXT: ret i1 [[TMP2]]
328 %cmp = icmp slt i8 %base, 0
329 call void @llvm.assume(i1 %cmp)
331 %adjusted = add i8 %base, %offset
332 call void @use8(i8 %adjusted)
333 %not_null = icmp ne i8 %adjusted, 0
334 %no_underflow = icmp ugt i8 %base, %adjusted ; swapped
335 %r = and i1 %not_null, %no_underflow
339 define i1 @t7_commutativity1_logical(i8 %base, i8 %offset) {
340 ; CHECK-LABEL: @t7_commutativity1_logical(
341 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
342 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
343 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
344 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
345 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
346 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
347 ; CHECK-NEXT: ret i1 [[TMP2]]
349 %cmp = icmp slt i8 %base, 0
350 call void @llvm.assume(i1 %cmp)
352 %adjusted = add i8 %base, %offset
353 call void @use8(i8 %adjusted)
354 %not_null = icmp ne i8 %adjusted, 0
355 %no_underflow = icmp ugt i8 %base, %adjusted ; swapped
356 %r = select i1 %not_null, i1 %no_underflow, i1 false
359 define i1 @t7_commutativity3(i8 %base, i8 %offset) {
360 ; CHECK-LABEL: @t7_commutativity3(
361 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
362 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
363 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
364 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
365 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
366 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
367 ; CHECK-NEXT: ret i1 [[TMP2]]
369 %cmp = icmp slt i8 %base, 0
370 call void @llvm.assume(i1 %cmp)
372 %adjusted = add i8 %base, %offset
373 call void @use8(i8 %adjusted)
374 %not_null = icmp ne i8 %adjusted, 0
375 %no_underflow = icmp ugt i8 %base, %adjusted ; swapped
376 %r = and i1 %no_underflow, %not_null ; swapped
380 define i1 @t7_commutativity3_logical(i8 %base, i8 %offset) {
381 ; CHECK-LABEL: @t7_commutativity3_logical(
382 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
383 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
384 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
385 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
386 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
387 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
388 ; CHECK-NEXT: ret i1 [[TMP2]]
390 %cmp = icmp slt i8 %base, 0
391 call void @llvm.assume(i1 %cmp)
393 %adjusted = add i8 %base, %offset
394 call void @use8(i8 %adjusted)
395 %not_null = icmp ne i8 %adjusted, 0
396 %no_underflow = icmp ugt i8 %base, %adjusted ; swapped
397 %r = select i1 %no_underflow, i1 %not_null, i1 false ; swapped
401 ; We could have the opposite question, did we get null or overflow happened?
402 define i1 @t8(i8 %base, i8 %offset) {
404 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
405 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
406 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
407 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
408 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
409 ; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i8 [[TMP1]], [[OFFSET]]
410 ; CHECK-NEXT: ret i1 [[TMP2]]
412 %cmp = icmp slt i8 %base, 0
413 call void @llvm.assume(i1 %cmp)
415 %adjusted = add i8 %base, %offset
416 call void @use8(i8 %adjusted)
417 %not_null = icmp eq i8 %adjusted, 0
418 %no_underflow = icmp uge i8 %adjusted, %base
419 %r = or i1 %not_null, %no_underflow
423 define i1 @t8_logical(i8 %base, i8 %offset) {
424 ; CHECK-LABEL: @t8_logical(
425 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
426 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
427 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
428 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
429 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
430 ; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i8 [[TMP1]], [[OFFSET]]
431 ; CHECK-NEXT: ret i1 [[TMP2]]
433 %cmp = icmp slt i8 %base, 0
434 call void @llvm.assume(i1 %cmp)
436 %adjusted = add i8 %base, %offset
437 call void @use8(i8 %adjusted)
438 %not_null = icmp eq i8 %adjusted, 0
439 %no_underflow = icmp uge i8 %adjusted, %base
440 %r = select i1 %not_null, i1 true, i1 %no_underflow
444 ; The comparison can be with any of the values being added.
445 define i1 @t9(i8 %base, i8 %offset) {
447 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
448 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
449 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
450 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
451 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
452 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
453 ; CHECK-NEXT: ret i1 [[TMP2]]
455 %cmp = icmp slt i8 %base, 0
456 call void @llvm.assume(i1 %cmp)
458 %adjusted = add i8 %base, %offset
459 call void @use8(i8 %adjusted)
460 %not_null = icmp ne i8 %adjusted, 0
461 %no_underflow = icmp ult i8 %adjusted, %offset
462 %r = and i1 %not_null, %no_underflow
466 define i1 @t9_logical(i8 %base, i8 %offset) {
467 ; CHECK-LABEL: @t9_logical(
468 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[BASE:%.*]], 0
469 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
470 ; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE]], [[OFFSET:%.*]]
471 ; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
472 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[BASE]]
473 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[OFFSET]]
474 ; CHECK-NEXT: ret i1 [[TMP2]]
476 %cmp = icmp slt i8 %base, 0
477 call void @llvm.assume(i1 %cmp)
479 %adjusted = add i8 %base, %offset
480 call void @use8(i8 %adjusted)
481 %not_null = icmp ne i8 %adjusted, 0
482 %no_underflow = icmp ult i8 %adjusted, %offset
483 %r = select i1 %not_null, i1 %no_underflow, i1 false