From 8ba725b4564a0fe8721758d78101f05a68536bdf Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 8 Apr 2004 19:59:34 +0000 Subject: [PATCH] Implement ScalarRepl/select_promote.ll git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12779 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Utils/PromoteMemoryToRegister.cpp | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index fd320daae59..0efab0bd5af 100644 --- a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -71,11 +71,42 @@ bool llvm::isAllocaPromotable(const AllocaInst *AI, const TargetData &TD) { if (!isa(UI) || cast(UI)->isVolatile()) return false; // Scan looking for memory accesses. + // FIXME: this should REALLY use alias analysis. for (--UI; !isa(UI); --UI) if (isa(UI) || isa(UI) || isa(UI)) return false; // If we got this far, we can promote the PHI use. + } else if (const SelectInst *SI = dyn_cast(*UI)) { + // We only support selects in a few simple cases. The select is only + // allowed to have one use, which must be a load instruction, and can only + // use alloca instructions (no random pointers). Also, there cannot be + // any accesses to AI between the PHI node and the use of the PHI. + if (!SI->hasOneUse()) return false; + + // Our transformation causes the unconditional loading of all pointer + // operands of the select. Because this could cause a fault if there is a + // critical edge in the CFG and if one of the pointers is illegal, we + // refuse to promote the select unless it is obviously safe. For now, + // obviously safe means that all of the operands are allocas. + // + if (!isa(SI->getOperand(1)) || + !isa(SI->getOperand(2))) + return false; + + // Now make sure the one user instruction is in the same basic block as + // the PHI, and that there are no loads or stores between the PHI node and + // the access. + BasicBlock::const_iterator UI = cast(SI->use_back()); + if (!isa(UI) || cast(UI)->isVolatile()) return false; + + // Scan looking for memory accesses. + // FIXME: this should REALLY use alias analysis. + for (--UI; &*UI != SI; --UI) + if (isa(UI) || isa(UI) || isa(UI)) + return false; + + // If we got this far, we can promote the select use. } else { return false; // Not a load, store, or promotable PHI? } @@ -170,6 +201,28 @@ void PromoteMem2Reg::run() { } else if (LoadInst *LI = dyn_cast(User)) { // Otherwise it must be a load instruction, keep track of variable reads UsingBlocks.push_back(LI->getParent()); + } else if (SelectInst *SI = dyn_cast(User)) { + // Because of the restrictions we placed on Select instruction uses + // above things are very simple. Transform the PHI of addresses into a + // select of loaded values. + LoadInst *Load = cast(SI->use_back()); + std::string LoadName = Load->getName(); Load->setName(""); + + Value *TrueVal = new LoadInst(SI->getOperand(1), + SI->getOperand(1)->getName()+".val", SI); + Value *FalseVal = new LoadInst(SI->getOperand(2), + SI->getOperand(2)->getName()+".val", SI); + + Value *NewSI = new SelectInst(SI->getOperand(0), TrueVal, + FalseVal, Load->getName(), SI); + Load->replaceAllUsesWith(NewSI); + Load->getParent()->getInstList().erase(Load); + SI->getParent()->getInstList().erase(SI); + + // Restart our scan of uses... + DefiningBlocks.clear(); + UsingBlocks.clear(); + goto RestartUseScan; } else { // Because of the restrictions we placed on PHI node uses above, the PHI // node reads the block in any using predecessors. Transform the PHI of -- 2.34.1