diff options
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; |