aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorJingu Kang <jingu.kang@arm.com>2021-03-11 13:07:36 +0000
committerJingu Kang <jingu.kang@arm.com>2021-03-25 22:56:05 +0000
commit3fd64cc7a361ae02f4c0f84f5f6a85a6f05c100c (patch)
tree499fec9e372ebf7bd24f9f042e01ec4e1d7bbbc5 /llvm/lib/Analysis/ValueTracking.cpp
parentbbb419151cc8994b3447f184fe841e87e159e5a3 (diff)
downloadllvm-3fd64cc7a361ae02f4c0f84f5f6a85a6f05c100c.zip
llvm-3fd64cc7a361ae02f4c0f84f5f6a85a6f05c100c.tar.gz
llvm-3fd64cc7a361ae02f4c0f84f5f6a85a6f05c100c.tar.bz2
[ValueTracking] Handle two PHIs in isKnownNonEqual()
loop: %cmp.0 = phi i32 [ 3, %entry ], [ %inc, %loop ] %pos.0 = phi i32 [ 1, %entry ], [ %cmp.0, %loop ] ... %inc = add i32 %cmp.0, 1 br label %loop On above example, %pos.0 uses previous iteration's %cmp.0 with backedge according to PHI's instruction's defintion. If the %inc is not same among iterations, we can say the two PHIs are not same. Differential Revision: https://reviews.llvm.org/D98422
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp44
1 files changed, 41 insertions, 3 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 7b43ce0..4b9afda 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -2548,6 +2548,36 @@ static bool isNonEqualMul(const Value *V1, const Value *V2, unsigned Depth,
return false;
}
+static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2,
+ unsigned Depth, const Query &Q) {
+ // Check two PHIs are in same block.
+ if (PN1->getParent() != PN2->getParent())
+ return false;
+
+ 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;
+
+ Query RecQ = Q;
+ RecQ.CxtI = IncomBB->getTerminator();
+ if (!isKnownNonEqual(IV1, IV2, Depth + 1, RecQ))
+ return false;
+ UsedFullRecursion = true;
+ }
+ return true;
+}
+
/// Return true if it is known that V1 != V2.
static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
const Query &Q) {
@@ -2599,12 +2629,20 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
case Instruction::SExt:
case Instruction::ZExt:
if (O1->getOperand(0)->getType() == O2->getOperand(0)->getType())
- return isKnownNonEqual(O1->getOperand(0), O2->getOperand(0),
- Depth + 1, Q);
+ return isKnownNonEqual(O1->getOperand(0), O2->getOperand(0), Depth + 1,
+ Q);
+ break;
+ case Instruction::PHI:
+ const PHINode *PN1 = 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;
break;
};
}
-
+
if (isAddOfNonZero(V1, V2, Depth, Q) || isAddOfNonZero(V2, V1, Depth, Q))
return true;