[llvm] [ValueTracking] Improve ananlysis of PHI nodes. (PR #71224)
Mikhail Gudim via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 3 13:01:42 PDT 2023
https://github.com/mgudim created https://github.com/llvm/llvm-project/pull/71224
In general, phi node `p = phi [%v0, %bb0], ..., [%v_n, %bb_n]` is not equal to `%x` if each of `%v0, ..., %v_n` is not equal to `%x`. If `x` happens to be also a `phi` node in the same basic block, we check that that the incomming values for the same predecessors are not equal.
>From a1101c684f63f759ab35f89e88bca0b5254edc45 Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at gmail.com>
Date: Tue, 10 Oct 2023 01:09:34 -0400
Subject: [PATCH] [ValueTracking] Improve ananlysis of PHI nodes.
In general, phi node `p = phi [%v0, %bb0], ..., [%v_n, %bb_n]` is not equal to
`%x` if each of `%v0, ..., %v_n` is not equal to `%x`. If `x` happens
to be also a `phi` node in the same basic block, we check that that the
incomming values for the same predecessors are not equal.
---
llvm/lib/Analysis/ValueTracking.cpp | 74 ++++++------
llvm/test/Analysis/BasicAA/non-equal-phi.ll | 123 ++++++++++++++++++++
2 files changed, 162 insertions(+), 35 deletions(-)
create mode 100644 llvm/test/Analysis/BasicAA/non-equal-phi.ll
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 2458c1cb9f8ec1d..b019459f06f3764 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3092,53 +3092,62 @@ static bool isNonEqualShl(const Value *V1, const Value *V2, unsigned Depth,
return false;
}
-static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2,
- unsigned Depth, const SimplifyQuery &Q) {
- // Check two PHIs are in same block.
- if (PN1->getParent() != PN2->getParent())
+static bool isNonEqualSelect(const Value *V1, const Value *V2, unsigned Depth,
+ const SimplifyQuery &Q) {
+ const SelectInst *SI1 = dyn_cast<SelectInst>(V1);
+ if (!SI1)
return false;
+ if (const SelectInst *SI2 = dyn_cast<SelectInst>(V2)) {
+ const Value *Cond1 = SI1->getCondition();
+ const Value *Cond2 = SI2->getCondition();
+ if (Cond1 == Cond2)
+ return isKnownNonEqual(SI1->getTrueValue(), SI2->getTrueValue(),
+ Depth + 1, Q) &&
+ isKnownNonEqual(SI1->getFalseValue(), SI2->getFalseValue(),
+ Depth + 1, Q);
+ }
+ return isKnownNonEqual(SI1->getTrueValue(), V2, Depth + 1, Q) &&
+ isKnownNonEqual(SI1->getFalseValue(), V2, Depth + 1, Q);
+}
+
+static bool isNonEqualPhisSameBB(const PHINode *PN1, const PHINode *PN2,
+ unsigned Depth, const SimplifyQuery &Q) {
SmallPtrSet<const BasicBlock *, 8> VisitedBBs;
- bool UsedFullRecursion = false;
for (const BasicBlock *IncomBB : PN1->blocks()) {
if (!VisitedBBs.insert(IncomBB).second)
continue; // Don't reprocess blocks that we have dealt with already.
const Value *IV1 = PN1->getIncomingValueForBlock(IncomBB);
const Value *IV2 = PN2->getIncomingValueForBlock(IncomBB);
- const APInt *C1, *C2;
- if (match(IV1, m_APInt(C1)) && match(IV2, m_APInt(C2)) && *C1 != *C2)
- continue;
-
- // Only one pair of phi operands is allowed for full recursion.
- if (UsedFullRecursion)
- return false;
SimplifyQuery RecQ = Q;
RecQ.CxtI = IncomBB->getTerminator();
if (!isKnownNonEqual(IV1, IV2, Depth + 1, RecQ))
return false;
- UsedFullRecursion = true;
}
return true;
}
-static bool isNonEqualSelect(const Value *V1, const Value *V2, unsigned Depth,
- const SimplifyQuery &Q) {
- const SelectInst *SI1 = dyn_cast<SelectInst>(V1);
- if (!SI1)
+static bool isNonEqualPhi(const Value *V1, const Value *V2, unsigned Depth,
+ const SimplifyQuery &Q) {
+ const PHINode *PN1 = dyn_cast<PHINode>(V1);
+ if (!PN1)
return false;
- if (const SelectInst *SI2 = dyn_cast<SelectInst>(V2)) {
- const Value *Cond1 = SI1->getCondition();
- const Value *Cond2 = SI2->getCondition();
- if (Cond1 == Cond2)
- return isKnownNonEqual(SI1->getTrueValue(), SI2->getTrueValue(),
- Depth + 1, Q) &&
- isKnownNonEqual(SI1->getFalseValue(), SI2->getFalseValue(),
- Depth + 1, Q);
+ if (const PHINode *PN2 = dyn_cast<PHINode>(V2)) {
+ if (PN1->getParent() == PN2->getParent())
+ return isNonEqualPhisSameBB(PN1, PN2, Depth, Q);
}
- return isKnownNonEqual(SI1->getTrueValue(), V2, Depth + 1, Q) &&
- isKnownNonEqual(SI1->getFalseValue(), V2, Depth + 1, Q);
+ for (const BasicBlock *IncomBB : PN1->blocks()) {
+ Value *V = PN1->getIncomingValueForBlock(IncomBB);
+ if (V == PN1)
+ continue;
+ SimplifyQuery RecQ = Q;
+ RecQ.CxtI = IncomBB->getTerminator();
+ if (!isKnownNonEqual(V, V2, Depth + 1, RecQ))
+ return false;
+ }
+ return true;
}
/// Return true if it is known that V1 != V2.
@@ -3161,14 +3170,6 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
if (O1 && O2 && O1->getOpcode() == O2->getOpcode()) {
if (auto Values = getInvertibleOperands(O1, O2))
return isKnownNonEqual(Values->first, Values->second, Depth + 1, Q);
-
- if (const PHINode *PN1 = dyn_cast<PHINode>(V1)) {
- const PHINode *PN2 = cast<PHINode>(V2);
- // FIXME: This is missing a generalization to handle the case where one is
- // a PHI and another one isn't.
- if (isNonEqualPHIs(PN1, PN2, Depth, Q))
- return true;
- };
}
if (isAddOfNonZero(V1, V2, Depth, Q) || isAddOfNonZero(V2, V1, Depth, Q))
@@ -3194,6 +3195,9 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
if (isNonEqualSelect(V1, V2, Depth, Q) || isNonEqualSelect(V2, V1, Depth, Q))
return true;
+ if (isNonEqualPhi(V1, V2, Depth, Q) || isNonEqualPhi(V2, V1, Depth, Q))
+ return true;
+
return false;
}
diff --git a/llvm/test/Analysis/BasicAA/non-equal-phi.ll b/llvm/test/Analysis/BasicAA/non-equal-phi.ll
new file mode 100644
index 000000000000000..29b13a600418886
--- /dev/null
+++ b/llvm/test/Analysis/BasicAA/non-equal-phi.ll
@@ -0,0 +1,123 @@
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+
+ at a = external local_unnamed_addr global ptr, align 8
+
+
+define void @no_alias_phi(i1 %c, i64 %x) {
+; CHECK-LABEL: no_alias_phi
+; CHECK: NoAlias: i32* %arrayidx0, i32* %arrayidx1
+entry:
+ br i1 %c, label %bb1, label %bb2
+
+bb1:
+ %add1_ = add nsw i64 %x, 1
+ br label %end
+
+bb2:
+ %add2_ = add nsw i64 %x, 2
+ br label %end
+
+end:
+ %cond = phi i64 [%add1_, %bb1 ], [ %add2_, %bb2 ]
+ %arrayidx0 = getelementptr inbounds i32, ptr @a, i64 %cond
+ %arrayidx1 = getelementptr inbounds i32, ptr @a, i64 %x
+ store i32 123, ptr %arrayidx0, align 4
+ store i32 456, ptr %arrayidx1, align 4
+ ret void
+}
+
+define void @may_alias_phi(i1 %c, i64 %x) {
+; CHECK-LABEL: may_alias_phi
+; CHECK: MayAlias: i32* %arrayidx0, i32* %arrayidx1
+entry:
+ br i1 %c, label %bb1, label %bb2
+
+bb1:
+ %add1_ = add nsw i64 %x, 1
+ br label %end
+
+bb2:
+ br label %end
+
+end:
+ %cond = phi i64 [%add1_, %bb1 ], [ %x, %bb2 ]
+ %arrayidx0 = getelementptr inbounds i32, ptr @a, i64 %cond
+ %arrayidx1 = getelementptr inbounds i32, ptr @a, i64 %x
+ store i32 123, ptr %arrayidx0, align 4
+ store i32 456, ptr %arrayidx1, align 4
+ ret void
+}
+
+define void @no_alias_phi_same_bb(i1 %c, i64 %x) {
+; CHECK-LABEL: no_alias_phi_same_bb
+; CHECK: NoAlias: i32* %arrayidx0, i32* %arrayidx1
+entry:
+ br i1 %c, label %bb1, label %bb2
+
+bb1:
+ %add1_ = add nsw i64 %x, 1
+ %add3_ = add nsw i64 %x, 3
+ br label %end
+
+bb2:
+ %add2_ = add nsw i64 %x, 2
+ %add4_ = add nsw i64 %x, 4
+ br label %end
+
+end:
+ %phi1_ = phi i64 [%add1_, %bb1 ], [ %add2_, %bb2 ]
+ %phi2_ = phi i64 [%add3_, %bb1 ], [ %add4_, %bb2 ]
+ %arrayidx0 = getelementptr inbounds i32, ptr @a, i64 %phi1_
+ %arrayidx1 = getelementptr inbounds i32, ptr @a, i64 %phi2_
+ store i32 123, ptr %arrayidx0, align 4
+ store i32 456, ptr %arrayidx1, align 4
+ ret void
+}
+
+define void @no_alias_phi_same_bb_2(i1 %c, i64 %x) {
+; CHECK-LABEL: no_alias_phi_same_bb_2
+; CHECK: NoAlias: i32* %arrayidx0, i32* %arrayidx1
+entry:
+ br i1 %c, label %bb1, label %bb2
+
+bb1:
+ %add1_ = add nsw i64 %x, 1
+ br label %end
+
+bb2:
+ %add2_ = add nsw i64 %x, 2
+ br label %end
+
+end:
+ %phi1_ = phi i64 [%x, %bb1 ], [ %add2_, %bb2 ]
+ %phi2_ = phi i64 [%add1_, %bb1 ], [ %x, %bb2 ]
+ %arrayidx0 = getelementptr inbounds i32, ptr @a, i64 %phi1_
+ %arrayidx1 = getelementptr inbounds i32, ptr @a, i64 %phi2_
+ store i32 123, ptr %arrayidx0, align 4
+ store i32 456, ptr %arrayidx1, align 4
+ ret void
+}
+
+define void @may_alias_phi_same_bb(i1 %c, i64 %x) {
+; CHECK-LABEL: may_alias_phi_same_bb
+; CHECK: MayAlias: i32* %arrayidx0, i32* %arrayidx1
+entry:
+ br i1 %c, label %bb1, label %bb2
+
+bb1:
+ br label %end
+
+bb2:
+ %add2_ = add nsw i64 %x, 2
+ %add4_ = add nsw i64 %x, 4
+ br label %end
+
+end:
+ %phi1_ = phi i64 [%x, %bb1 ], [ %add2_, %bb2 ]
+ %phi2_ = phi i64 [%x, %bb1 ], [ %add4_, %bb2 ]
+ %arrayidx0 = getelementptr inbounds i32, ptr @a, i64 %phi1_
+ %arrayidx1 = getelementptr inbounds i32, ptr @a, i64 %phi2_
+ store i32 123, ptr %arrayidx0, align 4
+ store i32 456, ptr %arrayidx1, align 4
+ ret void
+}
More information about the llvm-commits
mailing list