diff --git a/llvm/include/llvm/Analysis/LoopInfo.h b/llvm/include/llvm/Analysis/LoopInfo.h index a5717bae12c3f..c2c68004a9f9c 100644 --- a/llvm/include/llvm/Analysis/LoopInfo.h +++ b/llvm/include/llvm/Analysis/LoopInfo.h @@ -1199,6 +1199,14 @@ class LoopInfo : public LoopInfoBase { return true; } + + // Return true if a new use of V added in ExitBB would require an LCSSA PHI + // to be inserted at the begining of the block. Note that V is assumed to + // dominate ExitBB, and ExitBB must be the exit block of some loop. The + // IR is assumed to be in LCSSA form before the planned insertion. + bool wouldBeOutOfLoopUseRequiringLCSSA(const Value *V, + const BasicBlock *ExitBB) const; + }; // Allow clients to walk the list of nested loops... diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp index 5d3621935b8a4..93a00215e34ae 100644 --- a/llvm/lib/Analysis/LoopInfo.cpp +++ b/llvm/lib/Analysis/LoopInfo.cpp @@ -924,6 +924,31 @@ void LoopInfo::erase(Loop *Unloop) { } } +bool +LoopInfo::wouldBeOutOfLoopUseRequiringLCSSA(const Value *V, + const BasicBlock *ExitBB) const { + if (V->getType()->isTokenTy()) + // We can't form PHIs of token type, so the definition of LCSSA excludes + // values of that type. + return false; + + const Instruction *I = dyn_cast(V); + if (!I) + return false; + const Loop *L = getLoopFor(I->getParent()); + if (!L) + return false; + if (L->contains(ExitBB)) + // Could be an exit bb of a subloop and contained in defining loop + return false; + + // We found a (new) out-of-loop use location, for a value defined in-loop. + // (Note that because of LCSSA, we don't have to account for values defined + // in sibling loops. Such values will have LCSSA phis of their own in the + // common parent loop.) + return true; +} + AnalysisKey LoopAnalysis::Key; LoopInfo LoopAnalysis::run(Function &F, FunctionAnalysisManager &AM) { diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index da054c67fe8dd..777e89e37e808 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -1510,16 +1510,15 @@ static Instruction *cloneInstructionInExitBlock( // LCSSA. That will eliminate creating PHI nodes just to nuke them when // sinking bottom-up. for (Use &Op : New->operands()) - if (Instruction *OInst = dyn_cast(Op)) - if (Loop *OLoop = LI->getLoopFor(OInst->getParent())) - if (!OLoop->contains(&PN) && !Op->getType()->isTokenTy()) { - PHINode *OpPN = - PHINode::Create(OInst->getType(), PN.getNumIncomingValues(), - OInst->getName() + ".lcssa", &ExitBlock.front()); - for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) - OpPN->addIncoming(OInst, PN.getIncomingBlock(i)); - Op = OpPN; - } + if (LI->wouldBeOutOfLoopUseRequiringLCSSA(Op.get(), PN.getParent())) { + auto *OInst = cast(Op.get()); + PHINode *OpPN = + PHINode::Create(OInst->getType(), PN.getNumIncomingValues(), + OInst->getName() + ".lcssa", &ExitBlock.front()); + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) + OpPN->addIncoming(OInst, PN.getIncomingBlock(i)); + Op = OpPN; + } return New; } @@ -1860,18 +1859,17 @@ class LoopPromoter : public LoadAndStorePromoter { // (if legal) if doing so would add an out-of-loop use to an instruction // defined in-loop. Value *maybeInsertLCSSAPHI(Value *V, BasicBlock *BB) const { - if (Instruction *I = dyn_cast(V)) - if (Loop *L = LI.getLoopFor(I->getParent())) - if (!L->contains(BB) && !I->getType()->isTokenTy()) { - // We need to create an LCSSA PHI node for the incoming value and - // store that. - PHINode *PN = PHINode::Create(I->getType(), PredCache.size(BB), - I->getName() + ".lcssa", &BB->front()); - for (BasicBlock *Pred : PredCache.get(BB)) - PN->addIncoming(I, Pred); - return PN; - } - return V; + if (!LI.wouldBeOutOfLoopUseRequiringLCSSA(V, BB)) + return V; + + Instruction *I = cast(V); + // We need to create an LCSSA PHI node for the incoming value and + // store that. + PHINode *PN = PHINode::Create(I->getType(), PredCache.size(BB), + I->getName() + ".lcssa", &BB->front()); + for (BasicBlock *Pred : PredCache.get(BB)) + PN->addIncoming(I, Pred); + return PN; } public: