diff options
author | Jingu Kang <jingu.kang@arm.com> | 2021-03-11 13:07:36 +0000 |
---|---|---|
committer | Jingu Kang <jingu.kang@arm.com> | 2021-03-25 22:56:05 +0000 |
commit | 3fd64cc7a361ae02f4c0f84f5f6a85a6f05c100c (patch) | |
tree | 499fec9e372ebf7bd24f9f042e01ec4e1d7bbbc5 /llvm/lib/Analysis/ValueTracking.cpp | |
parent | bbb419151cc8994b3447f184fe841e87e159e5a3 (diff) | |
download | llvm-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.cpp | 44 |
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; |