Skip to content

Commit 0a1f947

Browse files
dtcxzywjoaosaffran
authored andcommitted
[ValueTracking] Infer NonEqual from dominating conditions/assumptions (llvm#117442)
This patch adds context-sensitive analysis support for `isKnownNonEqual`. It is required for llvm#117436.
1 parent 29ba758 commit 0a1f947

File tree

3 files changed

+248
-3
lines changed

3 files changed

+248
-3
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3857,6 +3857,50 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2,
38573857
match(V2, m_PtrToIntSameSize(Q.DL, m_Value(B))))
38583858
return isKnownNonEqual(A, B, DemandedElts, Depth + 1, Q);
38593859

3860+
if (!Q.CxtI)
3861+
return false;
3862+
3863+
// Try to infer NonEqual based on information from dominating conditions.
3864+
if (Q.DC && Q.DT) {
3865+
for (BranchInst *BI : Q.DC->conditionsFor(V1)) {
3866+
Value *Cond = BI->getCondition();
3867+
BasicBlockEdge Edge0(BI->getParent(), BI->getSuccessor(0));
3868+
if (Q.DT->dominates(Edge0, Q.CxtI->getParent()) &&
3869+
isImpliedCondition(Cond, ICmpInst::ICMP_NE, V1, V2, Q.DL,
3870+
/*LHSIsTrue=*/true, Depth)
3871+
.value_or(false))
3872+
return true;
3873+
3874+
BasicBlockEdge Edge1(BI->getParent(), BI->getSuccessor(1));
3875+
if (Q.DT->dominates(Edge1, Q.CxtI->getParent()) &&
3876+
isImpliedCondition(Cond, ICmpInst::ICMP_NE, V1, V2, Q.DL,
3877+
/*LHSIsTrue=*/false, Depth)
3878+
.value_or(false))
3879+
return true;
3880+
}
3881+
}
3882+
3883+
if (!Q.AC)
3884+
return false;
3885+
3886+
// Try to infer NonEqual based on information from assumptions.
3887+
for (auto &AssumeVH : Q.AC->assumptionsFor(V1)) {
3888+
if (!AssumeVH)
3889+
continue;
3890+
CallInst *I = cast<CallInst>(AssumeVH);
3891+
3892+
assert(I->getFunction() == Q.CxtI->getFunction() &&
3893+
"Got assumption for the wrong function!");
3894+
assert(I->getIntrinsicID() == Intrinsic::assume &&
3895+
"must be an assume intrinsic");
3896+
3897+
if (isImpliedCondition(I->getArgOperand(0), ICmpInst::ICMP_NE, V1, V2, Q.DL,
3898+
/*LHSIsTrue=*/true, Depth)
3899+
.value_or(false) &&
3900+
isValidAssumeForContext(I, Q.CxtI, Q.DT))
3901+
return true;
3902+
}
3903+
38603904
return false;
38613905
}
38623906

@@ -10231,10 +10275,10 @@ void llvm::findValuesAffectedByCondition(
1023110275
Worklist.push_back(B);
1023210276
}
1023310277
} else if (match(V, m_ICmp(Pred, m_Value(A), m_Value(B)))) {
10234-
AddCmpOperands(A, B);
10235-
1023610278
bool HasRHSC = match(B, m_ConstantInt());
1023710279
if (ICmpInst::isEquality(Pred)) {
10280+
AddAffected(A);
10281+
AddAffected(B);
1023810282
if (HasRHSC) {
1023910283
Value *Y;
1024010284
// (X & C) or (X | C).
@@ -10248,6 +10292,7 @@ void llvm::findValuesAffectedByCondition(
1024810292
}
1024910293
}
1025010294
} else {
10295+
AddCmpOperands(A, B);
1025110296
if (HasRHSC) {
1025210297
// Handle (A + C1) u< C2, which is the canonical form of
1025310298
// A > C3 && A < C4.

llvm/test/Analysis/BasicAA/fallback-mayalias.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
; Check that BasicAA falls back to MayAlias (instead of PartialAlias) when none
44
; of its little tricks are applicable.
55

6-
; CHECK: MayAlias: float* %arrayidxA, float* %arrayidxB
6+
; CHECK: NoAlias: float* %arrayidxA, float* %arrayidxB
77

88
define void @fallback_mayalias(ptr noalias nocapture %C, i64 %i, i64 %j) local_unnamed_addr {
99
entry:

llvm/test/Transforms/InstCombine/icmp-dom.ll

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,3 +534,203 @@ else:
534534
%cmp1 = icmp eq i32 %and1, 0
535535
ret i1 %cmp1
536536
}
537+
538+
; TODO: X != Y implies X | Y != 0
539+
define i1 @or_nonzero_from_nonequal(i8 %x, i8 %y) {
540+
; CHECK-LABEL: @or_nonzero_from_nonequal(
541+
; CHECK-NEXT: entry:
542+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]
543+
; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
544+
; CHECK: if.then:
545+
; CHECK-NEXT: [[OR:%.*]] = or i8 [[X]], [[Y]]
546+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[OR]], 0
547+
; CHECK-NEXT: ret i1 [[CMP]]
548+
; CHECK: if.else:
549+
; CHECK-NEXT: ret i1 false
550+
;
551+
entry:
552+
%cond = icmp eq i8 %x, %y
553+
br i1 %cond, label %if.else, label %if.then
554+
555+
if.then:
556+
%or = or i8 %x, %y
557+
%cmp = icmp eq i8 %or, 0
558+
ret i1 %cmp
559+
560+
if.else:
561+
ret i1 false
562+
}
563+
564+
define i1 @test_nonequal_domcond1(i64 %x, i64 %y, i64 %z, i64 %w) {
565+
; CHECK-LABEL: @test_nonequal_domcond1(
566+
; CHECK-NEXT: entry:
567+
; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[Y:%.*]], [[X:%.*]]
568+
; CHECK-NEXT: [[COND2:%.*]] = icmp eq i64 [[W:%.*]], [[Z:%.*]]
569+
; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[COND1]], i1 true, i1 [[COND2]]
570+
; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
571+
; CHECK: if.then:
572+
; CHECK-NEXT: ret i1 false
573+
; CHECK: if.end:
574+
; CHECK-NEXT: ret i1 false
575+
;
576+
entry:
577+
%cond1 = icmp eq i64 %y, %x
578+
%cond2 = icmp eq i64 %w, %z
579+
%or.cond = select i1 %cond1, i1 true, i1 %cond2
580+
br i1 %or.cond, label %if.end, label %if.then
581+
582+
if.then:
583+
%sub1 = sub i64 %w, %z
584+
%sub2 = sub i64 %y, %x
585+
%umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
586+
%cmp = icmp eq i64 %umin, 0
587+
ret i1 %cmp
588+
589+
if.end:
590+
ret i1 false
591+
}
592+
593+
define i1 @test_nonequal_domcond2(i64 %x, i64 %y, i64 %z, i64 %w) {
594+
; CHECK-LABEL: @test_nonequal_domcond2(
595+
; CHECK-NEXT: entry:
596+
; CHECK-NEXT: [[COND1:%.*]] = icmp ne i64 [[Y:%.*]], [[X:%.*]]
597+
; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[W:%.*]], [[Z:%.*]]
598+
; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[COND1]], i1 [[COND2]], i1 false
599+
; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
600+
; CHECK: if.then:
601+
; CHECK-NEXT: ret i1 false
602+
; CHECK: if.end:
603+
; CHECK-NEXT: ret i1 false
604+
;
605+
entry:
606+
%cond1 = icmp ne i64 %y, %x
607+
%cond2 = icmp ne i64 %w, %z
608+
%or.cond = select i1 %cond1, i1 %cond2, i1 false
609+
br i1 %or.cond, label %if.then, label %if.end
610+
611+
if.then:
612+
%sub1 = sub i64 %w, %z
613+
%sub2 = sub i64 %y, %x
614+
%umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
615+
%cmp = icmp eq i64 %umin, 0
616+
ret i1 %cmp
617+
618+
if.end:
619+
ret i1 false
620+
}
621+
622+
define i1 @test_nonequal_assume(i64 %x, i64 %y, i64 %z, i64 %w) {
623+
; CHECK-LABEL: @test_nonequal_assume(
624+
; CHECK-NEXT: entry:
625+
; CHECK-NEXT: [[COND1:%.*]] = icmp ne i64 [[Y:%.*]], [[X:%.*]]
626+
; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
627+
; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[W:%.*]], [[Z:%.*]]
628+
; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
629+
; CHECK-NEXT: ret i1 false
630+
;
631+
entry:
632+
%cond1 = icmp ne i64 %y, %x
633+
call void @llvm.assume(i1 %cond1)
634+
%cond2 = icmp ne i64 %w, %z
635+
call void @llvm.assume(i1 %cond2)
636+
637+
%sub1 = sub i64 %w, %z
638+
%sub2 = sub i64 %y, %x
639+
%umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
640+
%cmp = icmp eq i64 %umin, 0
641+
ret i1 %cmp
642+
}
643+
644+
; Negative tests
645+
646+
define i1 @test_nonequal_invalid_domcond1(i64 %x, i64 %y, i64 %z, i64 %w) {
647+
; CHECK-LABEL: @test_nonequal_invalid_domcond1(
648+
; CHECK-NEXT: entry:
649+
; CHECK-NEXT: [[COND1:%.*]] = icmp ne i64 [[Y:%.*]], [[X:%.*]]
650+
; CHECK-NEXT: [[COND2:%.*]] = icmp eq i64 [[W:%.*]], [[Z:%.*]]
651+
; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[COND1]], i1 true, i1 [[COND2]]
652+
; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
653+
; CHECK: if.then:
654+
; CHECK-NEXT: ret i1 true
655+
; CHECK: if.end:
656+
; CHECK-NEXT: ret i1 false
657+
;
658+
entry:
659+
%cond1 = icmp ne i64 %y, %x
660+
%cond2 = icmp eq i64 %w, %z
661+
%or.cond = select i1 %cond1, i1 true, i1 %cond2
662+
br i1 %or.cond, label %if.end, label %if.then
663+
664+
if.then:
665+
%sub1 = sub i64 %w, %z
666+
%sub2 = sub i64 %y, %x
667+
%umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
668+
%cmp = icmp eq i64 %umin, 0
669+
ret i1 %cmp
670+
671+
if.end:
672+
ret i1 false
673+
}
674+
675+
define i1 @test_nonequal_invalid_domcond2(i64 %x, i64 %y, i64 %z, i64 %w) {
676+
; CHECK-LABEL: @test_nonequal_invalid_domcond2(
677+
; CHECK-NEXT: entry:
678+
; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[Y:%.*]], [[X:%.*]]
679+
; CHECK-NEXT: [[COND2:%.*]] = icmp eq i64 [[W:%.*]], [[Z:%.*]]
680+
; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[COND1]], i1 true, i1 [[COND2]]
681+
; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
682+
; CHECK: if.then:
683+
; CHECK-NEXT: br label [[IF_END]]
684+
; CHECK: if.end:
685+
; CHECK-NEXT: [[SUB1:%.*]] = sub i64 [[W]], [[Z]]
686+
; CHECK-NEXT: [[SUB2:%.*]] = sub i64 [[Y]], [[X]]
687+
; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SUB1]], i64 [[SUB2]])
688+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[UMIN]], 0
689+
; CHECK-NEXT: ret i1 [[CMP]]
690+
;
691+
entry:
692+
%cond1 = icmp eq i64 %y, %x
693+
%cond2 = icmp eq i64 %w, %z
694+
%or.cond = select i1 %cond1, i1 true, i1 %cond2
695+
br i1 %or.cond, label %if.then, label %if.end
696+
697+
if.then:
698+
br label %if.end
699+
700+
if.end:
701+
%sub1 = sub i64 %w, %z
702+
%sub2 = sub i64 %y, %x
703+
%umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
704+
%cmp = icmp eq i64 %umin, 0
705+
ret i1 %cmp
706+
}
707+
708+
define i1 @test_nonequal_invalid_assume(i64 %x, i64 %y, i64 %z, i64 %w) {
709+
; CHECK-LABEL: @test_nonequal_invalid_assume(
710+
; CHECK-NEXT: entry:
711+
; CHECK-NEXT: [[SUB1:%.*]] = sub i64 [[W:%.*]], [[Z:%.*]]
712+
; CHECK-NEXT: [[SUB2:%.*]] = sub i64 [[Y:%.*]], [[X:%.*]]
713+
; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SUB1]], i64 [[SUB2]])
714+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[UMIN]], 0
715+
; CHECK-NEXT: call void @side_effect()
716+
; CHECK-NEXT: [[COND1:%.*]] = icmp ne i64 [[Y]], [[X]]
717+
; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
718+
; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[W]], [[Z]]
719+
; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
720+
; CHECK-NEXT: ret i1 [[CMP]]
721+
;
722+
entry:
723+
%sub1 = sub i64 %w, %z
724+
%sub2 = sub i64 %y, %x
725+
%umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
726+
%cmp = icmp eq i64 %umin, 0
727+
728+
call void @side_effect()
729+
%cond1 = icmp ne i64 %y, %x
730+
call void @llvm.assume(i1 %cond1)
731+
%cond2 = icmp ne i64 %w, %z
732+
call void @llvm.assume(i1 %cond2)
733+
ret i1 %cmp
734+
}
735+
736+
declare void @side_effect()

0 commit comments

Comments
 (0)