From 35bf4d6d8018160557a92b86181acbcef76f86eb Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Sat, 27 Nov 2010 08:15:55 +0000 Subject: Second attempt at fixing the performance regressions introduced by my recent GVN improvement. Looking through a single layer of PHI nodes when attempting to sink GEPs, we need to iteratively look through arbitrary PHI nests. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120202 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/CodeGenPrepare.cpp | 79 ++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 24 deletions(-) (limited to 'lib/Transforms/Scalar/CodeGenPrepare.cpp') diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp index 7df01f8435..60c7f7565e 100644 --- a/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -618,37 +618,68 @@ static bool IsNonLocalValue(Value *V, BasicBlock *BB) { bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr, const Type *AccessTy, DenseMap &SunkAddrs) { + Value *Repl = Addr; + // Try to collapse single-value PHI nodes. This is necessary to undo // unprofitable PRE transformations. - Value *Repl = Addr; - if (isa(Addr) && MemoryInst->hasOneUse()) { - PHINode *P = cast(Addr); - Instruction *Consensus = 0; - unsigned NumUses = 0; - for (unsigned i = 0, e = P->getNumIncomingValues(); i != e; ++i) { - Instruction *Incoming = dyn_cast(P->getIncomingValue(i)); - if (!Incoming || (Consensus && !Incoming->isIdenticalTo(Consensus))) { - Consensus = 0; - break; - } - - if (!Consensus || Incoming->isIdenticalTo(Consensus)) { - if (Incoming->getNumUses() > NumUses) { - Consensus = Incoming; - NumUses = Incoming->getNumUses(); - } - continue; + std::vector worklist; + SmallPtrSet Visited; + worklist.push_back(Addr); + + // Use a worklist to iteratively look through PHI nodes, and ensure that + // the addressing mode obtained from the non-PHI roots of the graph + // are equivalent. + Value *Consensus = 0; + unsigned NumUses = 0; + SmallVector AddrModeInsts; + ExtAddrMode AddrMode; + while (!worklist.empty()) { + Value *V = worklist.back(); + worklist.pop_back(); + + // Break use-def graph loops. + if (Visited.count(V)) { + Consensus = 0; + break; + } + + Visited.insert(V); + + // For a PHI node, push all of its incoming values. + if (PHINode *P = dyn_cast(V)) { + for (unsigned i = 0, e = P->getNumIncomingValues(); i != e; ++i) + worklist.push_back(P->getIncomingValue(i)); + continue; + } + + // For non-PHIs, determine the addressing mode being computed. + SmallVector NewAddrModeInsts; + ExtAddrMode NewAddrMode = + AddressingModeMatcher::Match(V, AccessTy,MemoryInst, + NewAddrModeInsts, *TLI); + + // Ensure that the obtained addressing mode is equivalent to that obtained + // for all other roots of the PHI traversal. Also, when choosing one + // such root as representative, select the one with the most uses in order + // to keep the cost modeling heuristics in AddressingModeMatcher applicable. + if (!Consensus || NewAddrMode == AddrMode) { + if (V->getNumUses() > NumUses) { + Consensus = V; + NumUses = V->getNumUses(); + AddrMode = NewAddrMode; + AddrModeInsts = NewAddrModeInsts; } + continue; } - if (Consensus) Addr = Consensus; + Consensus = 0; + break; } - // Figure out what addressing mode will be built up for this operation. - SmallVector AddrModeInsts; - ExtAddrMode AddrMode = AddressingModeMatcher::Match(Addr, AccessTy,MemoryInst, - AddrModeInsts, *TLI); - + // If the addressing mode couldn't be determined, or if multiple different + // ones were determined, bail out now. + if (!Consensus) return false; + // Check to see if any of the instructions supersumed by this addr mode are // non-local to I's BB. bool AnyNonLocal = false; -- cgit v1.2.3-18-g5258