From dfb8c3bbfcab611b98f6d8a532e67169bb46ece4 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Fri, 19 Nov 2010 22:15:03 +0000 Subject: [PATCH] When folding addressing modes in CodeGenPrepare, attempt to look through PHI nodes if all the operands of the PHI are equivalent. This allows CodeGenPrepare to undo unprofitable PRE transforms. llvm-svn: 119853 --- llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp b/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp index 35d02d974017..7df01f84357d 100644 --- a/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -618,6 +618,32 @@ static bool IsNonLocalValue(Value *V, BasicBlock *BB) { bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr, const Type *AccessTy, DenseMap &SunkAddrs) { + // 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; + } + } + + if (Consensus) Addr = Consensus; + } + // Figure out what addressing mode will be built up for this operation. SmallVector AddrModeInsts; ExtAddrMode AddrMode = AddressingModeMatcher::Match(Addr, AccessTy,MemoryInst, @@ -725,10 +751,10 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr, SunkAddr = new IntToPtrInst(Result, Addr->getType(), "sunkaddr",InsertPt); } - MemoryInst->replaceUsesOfWith(Addr, SunkAddr); + MemoryInst->replaceUsesOfWith(Repl, SunkAddr); - if (Addr->use_empty()) { - RecursivelyDeleteTriviallyDeadInstructions(Addr); + if (Repl->use_empty()) { + RecursivelyDeleteTriviallyDeadInstructions(Repl); // This address is now available for reassignment, so erase the table entry; // we don't want to match some completely different instruction. SunkAddrs[Addr] = 0;