Skip to content

Commit e1afbd6

Browse files
committed
[ValueTracking] Add tests for overflow detection functions is isKnownNonZero; NFC
1 parent beded9b commit e1afbd6

File tree

1 file changed

+302
-5
lines changed

1 file changed

+302
-5
lines changed

llvm/test/Transforms/InstSimplify/known-non-zero.ll

Lines changed: 302 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,10 @@ exit:
9999
ret i1 %res
100100
}
101101

102-
103102
; The code below exposed a bug similar to the one exposed by D60846, see the commit 6ea477590085.
104103
; In a nutshell, we should not replace %result.0 with 0 here.
105104

106-
define zeroext i8 @update_phi_query_loc_in_recursive_call(ptr nocapture readonly %p){
105+
define zeroext i8 @update_phi_query_loc_in_recursive_call(ptr nocapture readonly %p) {
107106
; CHECK-LABEL: @update_phi_query_loc_in_recursive_call(
108107
; CHECK-NEXT: entry:
109108
; CHECK-NEXT: br label [[FOR_COND:%.*]]
@@ -126,16 +125,16 @@ define zeroext i8 @update_phi_query_loc_in_recursive_call(ptr nocapture readonly
126125
entry:
127126
br label %for.cond
128127

129-
for.cond: ; preds = %for.body, %entry
128+
for.cond: ; preds = %for.body, %entry
130129
%result.0 = phi i8 [ 0, %entry ], [ %conv2, %for.body ]
131130
%shift.0 = phi i32 [ 0, %entry ], [ 1, %for.body ]
132131
%cmp = icmp eq i32 %shift.0, 0
133132
br i1 %cmp, label %for.body, label %for.cond.cleanup
134133

135-
for.cond.cleanup: ; preds = %for.cond
134+
for.cond.cleanup: ; preds = %for.cond
136135
ret i8 %result.0
137136

138-
for.body: ; preds = %for.cond
137+
for.body: ; preds = %for.cond
139138
%0 = load i8, ptr %p, align 1
140139
%conv = zext i8 %0 to i32
141140
%mul = shl nuw nsw i32 %shift.0, 3
@@ -166,3 +165,301 @@ A:
166165
B:
167166
ret i1 0
168167
}
168+
169+
declare void @use.i1(i1)
170+
declare void @use.i8(i1)
171+
define i1 @extract_value_uadd(i8 %xx, i8 %yy) {
172+
; CHECK-LABEL: @extract_value_uadd(
173+
; CHECK-NEXT: [[X:%.*]] = add nuw i8 [[XX:%.*]], 1
174+
; CHECK-NEXT: [[Y:%.*]] = add nuw i8 [[YY:%.*]], 1
175+
; CHECK-NEXT: [[X_LEMMA:%.*]] = icmp ult i8 [[X]], -128
176+
; CHECK-NEXT: [[Y_LEMMA:%.*]] = icmp ult i8 [[Y]], -128
177+
; CHECK-NEXT: call void @llvm.assume(i1 [[X_LEMMA]])
178+
; CHECK-NEXT: call void @llvm.assume(i1 [[Y_LEMMA]])
179+
; CHECK-NEXT: [[ADD_UOV:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[X]], i8 [[Y]])
180+
; CHECK-NEXT: [[ADD:%.*]] = extractvalue { i8, i1 } [[ADD_UOV]], 0
181+
; CHECK-NEXT: [[UOV:%.*]] = extractvalue { i8, i1 } [[ADD_UOV]], 1
182+
; CHECK-NEXT: call void @use.i1(i1 [[UOV]])
183+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[ADD]], 0
184+
; CHECK-NEXT: ret i1 [[R]]
185+
;
186+
%x = add nuw i8 %xx, 1
187+
%y = add nuw i8 %yy, 1
188+
%x_lemma = icmp ult i8 %x, 128
189+
%y_lemma = icmp ult i8 %y, 128
190+
call void @llvm.assume(i1 %x_lemma)
191+
call void @llvm.assume(i1 %y_lemma)
192+
193+
%add_uov = call { i8, i1} @llvm.uadd.with.overflow(i8 %x, i8 %y)
194+
%add = extractvalue { i8, i1} %add_uov, 0
195+
%uov = extractvalue { i8, i1} %add_uov, 1
196+
call void @use.i1(i1 %uov)
197+
%r = icmp eq i8 %add, 0
198+
ret i1 %r
199+
}
200+
201+
define i1 @extract_value_uadd_fail(i8 %xx, i8 %yy) {
202+
; CHECK-LABEL: @extract_value_uadd_fail(
203+
; CHECK-NEXT: [[X:%.*]] = add i8 [[XX:%.*]], 1
204+
; CHECK-NEXT: [[Y:%.*]] = add i8 [[YY:%.*]], 1
205+
; CHECK-NEXT: [[X_LEMMA:%.*]] = icmp ult i8 [[X]], -128
206+
; CHECK-NEXT: [[Y_LEMMA:%.*]] = icmp ult i8 [[Y]], -128
207+
; CHECK-NEXT: call void @llvm.assume(i1 [[X_LEMMA]])
208+
; CHECK-NEXT: call void @llvm.assume(i1 [[Y_LEMMA]])
209+
; CHECK-NEXT: [[ADD_UOV:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[X]], i8 [[Y]])
210+
; CHECK-NEXT: [[ADD:%.*]] = extractvalue { i8, i1 } [[ADD_UOV]], 0
211+
; CHECK-NEXT: [[UOV:%.*]] = extractvalue { i8, i1 } [[ADD_UOV]], 1
212+
; CHECK-NEXT: call void @use.i1(i1 [[UOV]])
213+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[ADD]], 0
214+
; CHECK-NEXT: ret i1 [[R]]
215+
;
216+
%x = add i8 %xx, 1
217+
%y = add i8 %yy, 1
218+
%x_lemma = icmp ult i8 %x, 128
219+
%y_lemma = icmp ult i8 %y, 128
220+
call void @llvm.assume(i1 %x_lemma)
221+
call void @llvm.assume(i1 %y_lemma)
222+
223+
%add_uov = call { i8, i1} @llvm.uadd.with.overflow(i8 %x, i8 %y)
224+
%add = extractvalue { i8, i1} %add_uov, 0
225+
%uov = extractvalue { i8, i1} %add_uov, 1
226+
call void @use.i1(i1 %uov)
227+
%r = icmp eq i8 %add, 0
228+
ret i1 %r
229+
}
230+
231+
define i1 @extract_value_sadd(i8 %xx, i8 %yy) {
232+
; CHECK-LABEL: @extract_value_sadd(
233+
; CHECK-NEXT: [[X:%.*]] = add nuw i8 [[XX:%.*]], 1
234+
; CHECK-NEXT: [[Y:%.*]] = add nuw i8 [[YY:%.*]], 1
235+
; CHECK-NEXT: [[X_LEMMA:%.*]] = icmp ult i8 [[X]], -128
236+
; CHECK-NEXT: [[Y_LEMMA:%.*]] = icmp ult i8 [[Y]], -128
237+
; CHECK-NEXT: call void @llvm.assume(i1 [[X_LEMMA]])
238+
; CHECK-NEXT: call void @llvm.assume(i1 [[Y_LEMMA]])
239+
; CHECK-NEXT: [[ADD_SOV:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X]], i8 [[Y]])
240+
; CHECK-NEXT: [[ADD:%.*]] = extractvalue { i8, i1 } [[ADD_SOV]], 0
241+
; CHECK-NEXT: [[SOV:%.*]] = extractvalue { i8, i1 } [[ADD_SOV]], 1
242+
; CHECK-NEXT: call void @use.i1(i1 [[SOV]])
243+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[ADD]], 0
244+
; CHECK-NEXT: ret i1 [[R]]
245+
;
246+
%x = add nuw i8 %xx, 1
247+
%y = add nuw i8 %yy, 1
248+
%x_lemma = icmp ult i8 %x, 128
249+
%y_lemma = icmp ult i8 %y, 128
250+
call void @llvm.assume(i1 %x_lemma)
251+
call void @llvm.assume(i1 %y_lemma)
252+
253+
%add_sov = call { i8, i1} @llvm.sadd.with.overflow(i8 %x, i8 %y)
254+
%add = extractvalue { i8, i1} %add_sov, 0
255+
%sov = extractvalue { i8, i1} %add_sov, 1
256+
call void @use.i1(i1 %sov)
257+
%r = icmp eq i8 %add, 0
258+
ret i1 %r
259+
}
260+
261+
define i1 @extract_value_sadd_fail(i8 %xx, i8 %yy) {
262+
; CHECK-LABEL: @extract_value_sadd_fail(
263+
; CHECK-NEXT: [[X:%.*]] = add i8 [[XX:%.*]], 1
264+
; CHECK-NEXT: [[Y:%.*]] = add i8 [[YY:%.*]], 1
265+
; CHECK-NEXT: [[ADD_SOV:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X]], i8 [[Y]])
266+
; CHECK-NEXT: [[ADD:%.*]] = extractvalue { i8, i1 } [[ADD_SOV]], 0
267+
; CHECK-NEXT: [[SOV:%.*]] = extractvalue { i8, i1 } [[ADD_SOV]], 1
268+
; CHECK-NEXT: call void @use.i1(i1 [[SOV]])
269+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[ADD]], 0
270+
; CHECK-NEXT: ret i1 [[R]]
271+
;
272+
%x = add i8 %xx, 1
273+
%y = add i8 %yy, 1
274+
275+
%add_sov = call { i8, i1} @llvm.sadd.with.overflow(i8 %x, i8 %y)
276+
%add = extractvalue { i8, i1} %add_sov, 0
277+
%sov = extractvalue { i8, i1} %add_sov, 1
278+
call void @use.i1(i1 %sov)
279+
%r = icmp eq i8 %add, 0
280+
ret i1 %r
281+
}
282+
283+
define i1 @extract_value_usub(i8 %x, i8 %zz) {
284+
; CHECK-LABEL: @extract_value_usub(
285+
; CHECK-NEXT: [[Z:%.*]] = add nuw i8 [[ZZ:%.*]], 1
286+
; CHECK-NEXT: [[Y:%.*]] = add i8 [[X:%.*]], [[Z]]
287+
; CHECK-NEXT: [[SUB_UOV:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X]], i8 [[Y]])
288+
; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i8, i1 } [[SUB_UOV]], 0
289+
; CHECK-NEXT: [[UOV:%.*]] = extractvalue { i8, i1 } [[SUB_UOV]], 1
290+
; CHECK-NEXT: call void @use.i1(i1 [[UOV]])
291+
; CHECK-NEXT: call void @use.i8(i8 [[SUB]])
292+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[SUB]], 0
293+
; CHECK-NEXT: ret i1 [[R]]
294+
;
295+
%z = add nuw i8 %zz, 1
296+
%y = add i8 %x, %z
297+
298+
%sub_uov = call { i8, i1} @llvm.usub.with.overflow(i8 %x, i8 %y)
299+
%sub = extractvalue { i8, i1} %sub_uov, 0
300+
%uov = extractvalue { i8, i1} %sub_uov, 1
301+
call void @use.i1(i1 %uov)
302+
call void @use.i8(i8 %sub)
303+
%r = icmp eq i8 %sub, 0
304+
ret i1 %r
305+
}
306+
307+
define i1 @extract_value_usub_fail(i8 %x, i8 %z) {
308+
; CHECK-LABEL: @extract_value_usub_fail(
309+
; CHECK-NEXT: [[Y:%.*]] = add i8 [[X:%.*]], [[Z:%.*]]
310+
; CHECK-NEXT: [[SUB_UOV:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X]], i8 [[Y]])
311+
; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i8, i1 } [[SUB_UOV]], 0
312+
; CHECK-NEXT: [[UOV:%.*]] = extractvalue { i8, i1 } [[SUB_UOV]], 1
313+
; CHECK-NEXT: call void @use.i1(i1 [[UOV]])
314+
; CHECK-NEXT: call void @use.i8(i8 [[SUB]])
315+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[SUB]], 0
316+
; CHECK-NEXT: ret i1 [[R]]
317+
;
318+
%y = add i8 %x, %z
319+
%sub_uov = call { i8, i1} @llvm.usub.with.overflow(i8 %x, i8 %y)
320+
%sub = extractvalue { i8, i1} %sub_uov, 0
321+
%uov = extractvalue { i8, i1} %sub_uov, 1
322+
call void @use.i1(i1 %uov)
323+
call void @use.i8(i8 %sub)
324+
%r = icmp eq i8 %sub, 0
325+
ret i1 %r
326+
}
327+
328+
define i1 @extract_value_ssub(i8 %x, i8 %zz) {
329+
; CHECK-LABEL: @extract_value_ssub(
330+
; CHECK-NEXT: [[Z:%.*]] = add nuw i8 [[ZZ:%.*]], 1
331+
; CHECK-NEXT: [[Y:%.*]] = add i8 [[X:%.*]], [[Z]]
332+
; CHECK-NEXT: [[SUB_SOV:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[Y]], i8 [[X]])
333+
; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i8, i1 } [[SUB_SOV]], 0
334+
; CHECK-NEXT: [[SOV:%.*]] = extractvalue { i8, i1 } [[SUB_SOV]], 1
335+
; CHECK-NEXT: call void @use.i1(i1 [[SOV]])
336+
; CHECK-NEXT: call void @use.i8(i8 [[SUB]])
337+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[SUB]], 0
338+
; CHECK-NEXT: ret i1 [[R]]
339+
;
340+
%z = add nuw i8 %zz, 1
341+
%y = add i8 %x, %z
342+
343+
%sub_sov = call { i8, i1} @llvm.ssub.with.overflow(i8 %y, i8 %x)
344+
%sub = extractvalue { i8, i1} %sub_sov, 0
345+
%sov = extractvalue { i8, i1} %sub_sov, 1
346+
call void @use.i1(i1 %sov)
347+
call void @use.i8(i8 %sub)
348+
%r = icmp eq i8 %sub, 0
349+
ret i1 %r
350+
}
351+
352+
define i1 @extract_value_ssub_fail(i8 %x) {
353+
; CHECK-LABEL: @extract_value_ssub_fail(
354+
; CHECK-NEXT: [[SUB_SOV:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 10, i8 [[X:%.*]])
355+
; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i8, i1 } [[SUB_SOV]], 0
356+
; CHECK-NEXT: [[SOV:%.*]] = extractvalue { i8, i1 } [[SUB_SOV]], 1
357+
; CHECK-NEXT: call void @use.i1(i1 [[SOV]])
358+
; CHECK-NEXT: call void @use.i8(i8 [[SUB]])
359+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[SUB]], 0
360+
; CHECK-NEXT: ret i1 [[R]]
361+
;
362+
%sub_sov = call { i8, i1} @llvm.ssub.with.overflow(i8 10, i8 %x)
363+
%sub = extractvalue { i8, i1} %sub_sov, 0
364+
%sov = extractvalue { i8, i1} %sub_sov, 1
365+
call void @use.i1(i1 %sov)
366+
call void @use.i8(i8 %sub)
367+
%r = icmp eq i8 %sub, 0
368+
ret i1 %r
369+
}
370+
371+
define i1 @extract_value_umul(i8 %xx, i8 %yy) {
372+
; CHECK-LABEL: @extract_value_umul(
373+
; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], 1
374+
; CHECK-NEXT: [[Y:%.*]] = add nuw i8 [[YY:%.*]], 1
375+
; CHECK-NEXT: [[MUL_UOV:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X]], i8 [[Y]])
376+
; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i8, i1 } [[MUL_UOV]], 0
377+
; CHECK-NEXT: [[UOV:%.*]] = extractvalue { i8, i1 } [[MUL_UOV]], 1
378+
; CHECK-NEXT: call void @use.i1(i1 [[UOV]])
379+
; CHECK-NEXT: call void @use.i8(i8 [[MUL]])
380+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[MUL]], 0
381+
; CHECK-NEXT: ret i1 [[R]]
382+
;
383+
%x = or i8 %xx, 1
384+
%y = add nuw i8 %yy, 1
385+
386+
%mul_uov = call { i8, i1} @llvm.umul.with.overflow(i8 %x, i8 %y)
387+
%mul = extractvalue { i8, i1} %mul_uov, 0
388+
%uov = extractvalue { i8, i1} %mul_uov, 1
389+
call void @use.i1(i1 %uov)
390+
call void @use.i8(i8 %mul)
391+
%r = icmp eq i8 %mul, 0
392+
ret i1 %r
393+
}
394+
395+
define i1 @extract_value_umul_fail(i8 %xx, i8 %yy) {
396+
; CHECK-LABEL: @extract_value_umul_fail(
397+
; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], 2
398+
; CHECK-NEXT: [[Y:%.*]] = add nuw i8 [[YY:%.*]], 1
399+
; CHECK-NEXT: [[MUL_UOV:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X]], i8 [[Y]])
400+
; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i8, i1 } [[MUL_UOV]], 0
401+
; CHECK-NEXT: [[UOV:%.*]] = extractvalue { i8, i1 } [[MUL_UOV]], 1
402+
; CHECK-NEXT: call void @use.i1(i1 [[UOV]])
403+
; CHECK-NEXT: call void @use.i8(i8 [[MUL]])
404+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[MUL]], 0
405+
; CHECK-NEXT: ret i1 [[R]]
406+
;
407+
%x = or i8 %xx, 2
408+
%y = add nuw i8 %yy, 1
409+
410+
%mul_uov = call { i8, i1} @llvm.umul.with.overflow(i8 %x, i8 %y)
411+
%mul = extractvalue { i8, i1} %mul_uov, 0
412+
%uov = extractvalue { i8, i1} %mul_uov, 1
413+
call void @use.i1(i1 %uov)
414+
call void @use.i8(i8 %mul)
415+
%r = icmp eq i8 %mul, 0
416+
ret i1 %r
417+
}
418+
419+
define i1 @extract_value_smul(i8 %xx, i8 %yy) {
420+
; CHECK-LABEL: @extract_value_smul(
421+
; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], 1
422+
; CHECK-NEXT: [[Y:%.*]] = add nuw i8 [[YY:%.*]], 1
423+
; CHECK-NEXT: [[MUL_SOV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[Y]], i8 [[X]])
424+
; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i8, i1 } [[MUL_SOV]], 0
425+
; CHECK-NEXT: [[SOV:%.*]] = extractvalue { i8, i1 } [[MUL_SOV]], 1
426+
; CHECK-NEXT: call void @use.i1(i1 [[SOV]])
427+
; CHECK-NEXT: call void @use.i8(i8 [[MUL]])
428+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[MUL]], 0
429+
; CHECK-NEXT: ret i1 [[R]]
430+
;
431+
%x = or i8 %xx, 1
432+
%y = add nuw i8 %yy, 1
433+
434+
%mul_sov = call { i8, i1} @llvm.smul.with.overflow(i8 %y, i8 %x)
435+
%mul = extractvalue { i8, i1} %mul_sov, 0
436+
%sov = extractvalue { i8, i1} %mul_sov, 1
437+
call void @use.i1(i1 %sov)
438+
call void @use.i8(i8 %mul)
439+
%r = icmp eq i8 %mul, 0
440+
ret i1 %r
441+
}
442+
443+
define i1 @extract_value_smul_fail(i8 %xx, i8 %yy) {
444+
; CHECK-LABEL: @extract_value_smul_fail(
445+
; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], 1
446+
; CHECK-NEXT: [[Y:%.*]] = add i8 [[YY:%.*]], 1
447+
; CHECK-NEXT: [[MUL_SOV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[Y]], i8 [[X]])
448+
; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i8, i1 } [[MUL_SOV]], 0
449+
; CHECK-NEXT: [[SOV:%.*]] = extractvalue { i8, i1 } [[MUL_SOV]], 1
450+
; CHECK-NEXT: call void @use.i1(i1 [[SOV]])
451+
; CHECK-NEXT: call void @use.i8(i8 [[MUL]])
452+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[MUL]], 0
453+
; CHECK-NEXT: ret i1 [[R]]
454+
;
455+
%x = or i8 %xx, 1
456+
%y = add i8 %yy, 1
457+
458+
%mul_sov = call { i8, i1} @llvm.smul.with.overflow(i8 %y, i8 %x)
459+
%mul = extractvalue { i8, i1} %mul_sov, 0
460+
%sov = extractvalue { i8, i1} %mul_sov, 1
461+
call void @use.i1(i1 %sov)
462+
call void @use.i8(i8 %mul)
463+
%r = icmp eq i8 %mul, 0
464+
ret i1 %r
465+
}

0 commit comments

Comments
 (0)