Skip to content

Commit 076581f

Browse files
authored
[ValueTracking] Implement sdiv/udiv support for isKnownNonNullFromDominatingCondition (#67282)
The second operand of a sdiv/udiv has to be non-null, as division by zero is UB. Proofs: https://alive2.llvm.org/ce/z/WttZbb Fixes #64240.
1 parent 47826b3 commit 076581f

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2264,6 +2264,10 @@ static bool isKnownNonNullFromDominatingCondition(const Value *V,
22642264
return true;
22652265
}
22662266

2267+
if (match(U, m_IDiv(m_Value(), m_Specific(V))) &&
2268+
isValidAssumeForContext(cast<Instruction>(U), CtxI, DT))
2269+
return true;
2270+
22672271
// Consider only compare instructions uniquely controlling a branch
22682272
Value *RHS;
22692273
CmpInst::Predicate Pred;

llvm/test/Analysis/ValueTracking/select-known-non-zero.ll

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,3 +393,57 @@ define i1 @inv_select_v_sle_nonneg(i8 %v, i8 %C, i8 %y) {
393393
%r = icmp eq i8 %s, 0
394394
ret i1 %r
395395
}
396+
397+
; Check udiv/sdiv occuring before icmp.
398+
define i64 @incorrect_safe_div_1(i64 %n, i64 %d) {
399+
; CHECK-LABEL: @incorrect_safe_div_1(
400+
; CHECK-NEXT: [[TMP1:%.*]] = udiv i64 [[N:%.*]], [[D:%.*]]
401+
; CHECK-NEXT: ret i64 [[TMP1]]
402+
;
403+
%1 = udiv i64 %n, %d
404+
%2 = icmp eq i64 %d, 0
405+
%3 = select i1 %2, i64 -1, i64 %1
406+
ret i64 %3
407+
}
408+
409+
; Check icmp occuring before udiv/sdiv.
410+
define i64 @incorrect_safe_div_2(i64 %n, i64 %d) {
411+
; CHECK-LABEL: @incorrect_safe_div_2(
412+
; CHECK-NEXT: [[TMP1:%.*]] = sdiv i64 [[N:%.*]], [[D:%.*]]
413+
; CHECK-NEXT: ret i64 [[TMP1]]
414+
;
415+
%1 = icmp eq i64 %d, 0
416+
%2 = sdiv i64 %n, %d
417+
%3 = select i1 %1, i64 -1, i64 %2
418+
ret i64 %3
419+
}
420+
421+
define i64 @incorrect_safe_div_call_1(i64 %n, i64 %d) {
422+
; CHECK-LABEL: @incorrect_safe_div_call_1(
423+
; CHECK-NEXT: [[TMP1:%.*]] = sdiv i64 [[N:%.*]], [[D:%.*]]
424+
; CHECK-NEXT: tail call void @use(i64 [[D]])
425+
; CHECK-NEXT: ret i64 [[TMP1]]
426+
;
427+
%1 = sdiv i64 %n, %d
428+
tail call void @use(i64 %d)
429+
%2 = icmp eq i64 %d, 0
430+
%3 = select i1 %2, i64 -1, i64 %1
431+
ret i64 %3
432+
}
433+
434+
define i64 @incorrect_safe_div_call_2(i64 %n, i64 %d) {
435+
; CHECK-LABEL: @incorrect_safe_div_call_2(
436+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[D:%.*]], 0
437+
; CHECK-NEXT: tail call void @use(i64 [[D]])
438+
; CHECK-NEXT: [[TMP2:%.*]] = udiv i64 [[N:%.*]], [[D]]
439+
; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 -1, i64 [[TMP2]]
440+
; CHECK-NEXT: ret i64 [[TMP3]]
441+
;
442+
%1 = icmp eq i64 %d, 0
443+
tail call void @use(i64 %d)
444+
%2 = udiv i64 %n, %d
445+
%3 = select i1 %1, i64 -1, i64 %2
446+
ret i64 %3
447+
}
448+
449+
declare void @use(i64)

0 commit comments

Comments
 (0)