Skip to content

Commit 51d36e9

Browse files
dtcxzywIanWood1
authored andcommitted
[ValueTracking] Refactor isKnownNonEqualFromContext (llvm#127388)
This patch avoids adding RHS for comparisons with two variable operands (llvm#118493 (comment)). Instead, we iterate over related dominating conditions of both V1 and V2 in `isKnownNonEqualFromContext`, as suggested by goldsteinn (llvm#117442 (comment)). Compile-time improvement: https://llvm-compile-time-tracker.com/compare.php?from=c6d95c441a29a45782ff72d6cb82839b86fd0e4a&to=88464baedd7b1731281eaa0ce4438122b4d218a7&stat=instructions:u
1 parent 4276252 commit 51d36e9

File tree

2 files changed

+139
-44
lines changed

2 files changed

+139
-44
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 61 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3804,6 +3804,63 @@ static bool isNonEqualPointersWithRecursiveGEP(const Value *A, const Value *B,
38043804
(StartOffset.sle(OffsetB) && StepOffset.isNegative()));
38053805
}
38063806

3807+
static bool isKnownNonEqualFromContext(const Value *V1, const Value *V2,
3808+
unsigned Depth, const SimplifyQuery &Q) {
3809+
if (!Q.CxtI)
3810+
return false;
3811+
3812+
// Try to infer NonEqual based on information from dominating conditions.
3813+
if (Q.DC && Q.DT) {
3814+
auto IsKnownNonEqualFromDominatingCondition = [&](const Value *V) {
3815+
for (BranchInst *BI : Q.DC->conditionsFor(V)) {
3816+
Value *Cond = BI->getCondition();
3817+
BasicBlockEdge Edge0(BI->getParent(), BI->getSuccessor(0));
3818+
if (Q.DT->dominates(Edge0, Q.CxtI->getParent()) &&
3819+
isImpliedCondition(Cond, ICmpInst::ICMP_NE, V1, V2, Q.DL,
3820+
/*LHSIsTrue=*/true, Depth)
3821+
.value_or(false))
3822+
return true;
3823+
3824+
BasicBlockEdge Edge1(BI->getParent(), BI->getSuccessor(1));
3825+
if (Q.DT->dominates(Edge1, Q.CxtI->getParent()) &&
3826+
isImpliedCondition(Cond, ICmpInst::ICMP_NE, V1, V2, Q.DL,
3827+
/*LHSIsTrue=*/false, Depth)
3828+
.value_or(false))
3829+
return true;
3830+
}
3831+
3832+
return false;
3833+
};
3834+
3835+
if (IsKnownNonEqualFromDominatingCondition(V1) ||
3836+
IsKnownNonEqualFromDominatingCondition(V2))
3837+
return true;
3838+
}
3839+
3840+
if (!Q.AC)
3841+
return false;
3842+
3843+
// Try to infer NonEqual based on information from assumptions.
3844+
for (auto &AssumeVH : Q.AC->assumptionsFor(V1)) {
3845+
if (!AssumeVH)
3846+
continue;
3847+
CallInst *I = cast<CallInst>(AssumeVH);
3848+
3849+
assert(I->getFunction() == Q.CxtI->getFunction() &&
3850+
"Got assumption for the wrong function!");
3851+
assert(I->getIntrinsicID() == Intrinsic::assume &&
3852+
"must be an assume intrinsic");
3853+
3854+
if (isImpliedCondition(I->getArgOperand(0), ICmpInst::ICMP_NE, V1, V2, Q.DL,
3855+
/*LHSIsTrue=*/true, Depth)
3856+
.value_or(false) &&
3857+
isValidAssumeForContext(I, Q.CxtI, Q.DT))
3858+
return true;
3859+
}
3860+
3861+
return false;
3862+
}
3863+
38073864
/// Return true if it is known that V1 != V2.
38083865
static bool isKnownNonEqual(const Value *V1, const Value *V2,
38093866
const APInt &DemandedElts, unsigned Depth,
@@ -3875,49 +3932,8 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2,
38753932
match(V2, m_PtrToIntSameSize(Q.DL, m_Value(B))))
38763933
return isKnownNonEqual(A, B, DemandedElts, Depth + 1, Q);
38773934

3878-
if (!Q.CxtI)
3879-
return false;
3880-
3881-
// Try to infer NonEqual based on information from dominating conditions.
3882-
if (Q.DC && Q.DT) {
3883-
for (BranchInst *BI : Q.DC->conditionsFor(V1)) {
3884-
Value *Cond = BI->getCondition();
3885-
BasicBlockEdge Edge0(BI->getParent(), BI->getSuccessor(0));
3886-
if (Q.DT->dominates(Edge0, Q.CxtI->getParent()) &&
3887-
isImpliedCondition(Cond, ICmpInst::ICMP_NE, V1, V2, Q.DL,
3888-
/*LHSIsTrue=*/true, Depth)
3889-
.value_or(false))
3890-
return true;
3891-
3892-
BasicBlockEdge Edge1(BI->getParent(), BI->getSuccessor(1));
3893-
if (Q.DT->dominates(Edge1, Q.CxtI->getParent()) &&
3894-
isImpliedCondition(Cond, ICmpInst::ICMP_NE, V1, V2, Q.DL,
3895-
/*LHSIsTrue=*/false, Depth)
3896-
.value_or(false))
3897-
return true;
3898-
}
3899-
}
3900-
3901-
if (!Q.AC)
3902-
return false;
3903-
3904-
// Try to infer NonEqual based on information from assumptions.
3905-
for (auto &AssumeVH : Q.AC->assumptionsFor(V1)) {
3906-
if (!AssumeVH)
3907-
continue;
3908-
CallInst *I = cast<CallInst>(AssumeVH);
3909-
3910-
assert(I->getFunction() == Q.CxtI->getFunction() &&
3911-
"Got assumption for the wrong function!");
3912-
assert(I->getIntrinsicID() == Intrinsic::assume &&
3913-
"must be an assume intrinsic");
3914-
3915-
if (isImpliedCondition(I->getArgOperand(0), ICmpInst::ICMP_NE, V1, V2, Q.DL,
3916-
/*LHSIsTrue=*/true, Depth)
3917-
.value_or(false) &&
3918-
isValidAssumeForContext(I, Q.CxtI, Q.DT))
3919-
return true;
3920-
}
3935+
if (isKnownNonEqualFromContext(V1, V2, Depth, Q))
3936+
return true;
39213937

39223938
return false;
39233939
}
@@ -10348,7 +10364,8 @@ void llvm::findValuesAffectedByCondition(
1034810364
bool HasRHSC = match(B, m_ConstantInt());
1034910365
if (ICmpInst::isEquality(Pred)) {
1035010366
AddAffected(A);
10351-
AddAffected(B);
10367+
if (IsAssume)
10368+
AddAffected(B);
1035210369
if (HasRHSC) {
1035310370
Value *Y;
1035410371
// (X & C) or (X | C).

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

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,4 +733,82 @@ entry:
733733
ret i1 %cmp
734734
}
735735

736+
; TODO: We can prove `%cond2` is always false
737+
define void @test_nonequal_domcond_loop1(i32 %x0, i1 %x1) {
738+
; CHECK-LABEL: @test_nonequal_domcond_loop1(
739+
; CHECK-NEXT: entry:
740+
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
741+
; CHECK: loop.header:
742+
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X0:%.*]], [[LATCH:%.*]] ]
743+
; CHECK-NEXT: br label [[LATCH]]
744+
; CHECK: latch:
745+
; CHECK-NEXT: br i1 [[X1:%.*]], label [[IF_THEN:%.*]], label [[LOOP_HEADER]]
746+
; CHECK: if.then:
747+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X0]], 1
748+
; CHECK-NEXT: [[COND1:%.*]] = icmp eq i32 [[AND]], [[PHI]]
749+
; CHECK-NEXT: br i1 [[COND1]], label [[IF_THEN2:%.*]], label [[LATCH]]
750+
; CHECK: if.then2:
751+
; CHECK-NEXT: br label [[BB:%.*]]
752+
; CHECK: indirectbb:
753+
; CHECK-NEXT: [[COND2:%.*]] = icmp eq i32 [[PHI]], 31
754+
; CHECK-NEXT: br i1 [[COND2]], label [[EXIT:%.*]], label [[LATCH]]
755+
; CHECK: exit:
756+
; CHECK-NEXT: ret void
757+
;
758+
entry:
759+
br label %loop.header
760+
761+
loop.header:
762+
%phi = phi i32 [ 0, %entry ], [ %x0, %latch ]
763+
br label %latch
764+
765+
latch:
766+
br i1 %x1, label %if.then, label %loop.header
767+
768+
if.then:
769+
%and = and i32 %x0, 1
770+
%cond1 = icmp eq i32 %and, %phi
771+
br i1 %cond1, label %if.then2, label %latch
772+
773+
if.then2:
774+
br label %indirectbb
775+
776+
indirectbb:
777+
%cond2 = icmp eq i32 %phi, 31
778+
br i1 %cond2, label %exit, label %latch
779+
780+
exit:
781+
ret void
782+
}
783+
784+
define void @test_nonequal_domcond_loop2(ptr %p) {
785+
; CHECK-LABEL: @test_nonequal_domcond_loop2(
786+
; CHECK-NEXT: entry:
787+
; CHECK-NEXT: [[LOAD1:%.*]] = load volatile i8, ptr [[P:%.*]], align 1
788+
; CHECK-NEXT: br label [[WHILE_COND:%.*]]
789+
; CHECK: while.cond:
790+
; CHECK-NEXT: [[LOAD2:%.*]] = load volatile i8, ptr [[P]], align 1
791+
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[LOAD2]], 0
792+
; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i8 [[LOAD2]], [[LOAD1]]
793+
; CHECK-NEXT: [[OR:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]]
794+
; CHECK-NEXT: br i1 [[OR]], label [[WHILE_COND]], label [[FOR_BODY:%.*]]
795+
; CHECK: for.body:
796+
; CHECK-NEXT: br i1 false, label [[WHILE_COND]], label [[FOR_BODY]]
797+
;
798+
entry:
799+
%load1 = load volatile i8, ptr %p, align 1
800+
br label %while.cond
801+
802+
while.cond:
803+
%load2 = load volatile i8, ptr %p, align 1
804+
%cmp1 = icmp eq i8 %load2, 0
805+
%cmp2 = icmp uge i8 %load2, %load1
806+
%or = select i1 %cmp1, i1 true, i1 %cmp2
807+
br i1 %or, label %while.cond, label %for.body
808+
809+
for.body:
810+
%cond = icmp eq i8 %load1, %load2
811+
br i1 %cond, label %while.cond, label %for.body
812+
}
813+
736814
declare void @side_effect()

0 commit comments

Comments
 (0)