diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
commit | d8e91e46262bc44006913e6796843909f1ac7bcd (patch) | |
tree | 7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/Transforms/Scalar/LoopUnswitch.cpp | |
parent | b7eb8e35e481a74962664b63dfb09483b200209a (diff) |
Notes
Diffstat (limited to 'lib/Transforms/Scalar/LoopUnswitch.cpp')
-rw-r--r-- | lib/Transforms/Scalar/LoopUnswitch.cpp | 103 |
1 files changed, 76 insertions, 27 deletions
diff --git a/lib/Transforms/Scalar/LoopUnswitch.cpp b/lib/Transforms/Scalar/LoopUnswitch.cpp index 6aad077ff19e..4a089dfa7dbf 100644 --- a/lib/Transforms/Scalar/LoopUnswitch.cpp +++ b/lib/Transforms/Scalar/LoopUnswitch.cpp @@ -28,18 +28,19 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/CodeMetrics.h" -#include "llvm/Analysis/DivergenceAnalysis.h" #include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/LegacyDivergenceAnalysis.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/LoopIterator.h" #include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/MemorySSA.h" +#include "llvm/Analysis/MemorySSAUpdater.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/Transforms/Utils/Local.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CallSite.h" @@ -65,8 +66,10 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/LoopUtils.h" #include "llvm/Transforms/Utils/ValueMapper.h" #include <algorithm> @@ -180,11 +183,13 @@ namespace { Loop *currentLoop = nullptr; DominatorTree *DT = nullptr; + MemorySSA *MSSA = nullptr; + std::unique_ptr<MemorySSAUpdater> MSSAU; BasicBlock *loopHeader = nullptr; BasicBlock *loopPreheader = nullptr; bool SanitizeMemory; - LoopSafetyInfo SafetyInfo; + SimpleLoopSafetyInfo SafetyInfo; // LoopBlocks contains all of the basic blocks of the loop, including the // preheader of the loop, the body of the loop, and the exit blocks of the @@ -214,8 +219,12 @@ namespace { void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired<AssumptionCacheTracker>(); AU.addRequired<TargetTransformInfoWrapperPass>(); + if (EnableMSSALoopDependency) { + AU.addRequired<MemorySSAWrapperPass>(); + AU.addPreserved<MemorySSAWrapperPass>(); + } if (hasBranchDivergence) - AU.addRequired<DivergenceAnalysis>(); + AU.addRequired<LegacyDivergenceAnalysis>(); getLoopAnalysisUsage(AU); } @@ -237,11 +246,11 @@ namespace { bool TryTrivialLoopUnswitch(bool &Changed); bool UnswitchIfProfitable(Value *LoopCond, Constant *Val, - TerminatorInst *TI = nullptr); + Instruction *TI = nullptr); void UnswitchTrivialCondition(Loop *L, Value *Cond, Constant *Val, - BasicBlock *ExitBlock, TerminatorInst *TI); + BasicBlock *ExitBlock, Instruction *TI); void UnswitchNontrivialCondition(Value *LIC, Constant *OnVal, Loop *L, - TerminatorInst *TI); + Instruction *TI); void RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC, Constant *Val, bool isEqual); @@ -249,8 +258,7 @@ namespace { void EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val, BasicBlock *TrueDest, BasicBlock *FalseDest, - BranchInst *OldBranch, - TerminatorInst *TI); + BranchInst *OldBranch, Instruction *TI); void SimplifyCode(std::vector<Instruction*> &Worklist, Loop *L); @@ -383,7 +391,8 @@ INITIALIZE_PASS_BEGIN(LoopUnswitch, "loop-unswitch", "Unswitch loops", INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) INITIALIZE_PASS_DEPENDENCY(LoopPass) INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) -INITIALIZE_PASS_DEPENDENCY(DivergenceAnalysis) +INITIALIZE_PASS_DEPENDENCY(LegacyDivergenceAnalysis) +INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass) INITIALIZE_PASS_END(LoopUnswitch, "loop-unswitch", "Unswitch loops", false, false) @@ -515,20 +524,33 @@ bool LoopUnswitch::runOnLoop(Loop *L, LPPassManager &LPM_Ref) { LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); LPM = &LPM_Ref; DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); + if (EnableMSSALoopDependency) { + MSSA = &getAnalysis<MemorySSAWrapperPass>().getMSSA(); + MSSAU = make_unique<MemorySSAUpdater>(MSSA); + assert(DT && "Cannot update MemorySSA without a valid DomTree."); + } currentLoop = L; Function *F = currentLoop->getHeader()->getParent(); SanitizeMemory = F->hasFnAttribute(Attribute::SanitizeMemory); if (SanitizeMemory) - computeLoopSafetyInfo(&SafetyInfo, L); + SafetyInfo.computeLoopSafetyInfo(L); + + if (MSSA && VerifyMemorySSA) + MSSA->verifyMemorySSA(); bool Changed = false; do { assert(currentLoop->isLCSSAForm(*DT)); + if (MSSA && VerifyMemorySSA) + MSSA->verifyMemorySSA(); redoLoop = false; Changed |= processCurrentLoop(); } while(redoLoop); + if (MSSA && VerifyMemorySSA) + MSSA->verifyMemorySSA(); + return Changed; } @@ -690,7 +712,7 @@ bool LoopUnswitch::processCurrentLoop() { // loop. for (Loop::block_iterator I = currentLoop->block_begin(), E = currentLoop->block_end(); I != E; ++I) { - TerminatorInst *TI = (*I)->getTerminator(); + Instruction *TI = (*I)->getTerminator(); // Unswitching on a potentially uninitialized predicate is not // MSan-friendly. Limit this to the cases when the original predicate is @@ -699,7 +721,7 @@ bool LoopUnswitch::processCurrentLoop() { // This is a workaround for the discrepancy between LLVM IR and MSan // semantics. See PR28054 for more details. if (SanitizeMemory && - !isGuaranteedToExecute(*TI, DT, currentLoop, &SafetyInfo)) + !SafetyInfo.isGuaranteedToExecute(*TI, DT, currentLoop)) continue; if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { @@ -853,7 +875,7 @@ static BasicBlock *isTrivialLoopExitBlock(Loop *L, BasicBlock *BB) { /// simplify the loop. If we decide that this is profitable, /// unswitch the loop, reprocess the pieces, then return true. bool LoopUnswitch::UnswitchIfProfitable(Value *LoopCond, Constant *Val, - TerminatorInst *TI) { + Instruction *TI) { // Check to see if it would be profitable to unswitch current loop. if (!BranchesInfo.CostAllowsUnswitching()) { LLVM_DEBUG(dbgs() << "NOT unswitching loop %" @@ -864,7 +886,7 @@ bool LoopUnswitch::UnswitchIfProfitable(Value *LoopCond, Constant *Val, return false; } if (hasBranchDivergence && - getAnalysis<DivergenceAnalysis>().isDivergent(LoopCond)) { + getAnalysis<LegacyDivergenceAnalysis>().isDivergent(LoopCond)) { LLVM_DEBUG(dbgs() << "NOT unswitching loop %" << currentLoop->getHeader()->getName() << " at non-trivial condition '" << *Val @@ -908,7 +930,7 @@ void LoopUnswitch::EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val, BasicBlock *TrueDest, BasicBlock *FalseDest, BranchInst *OldBranch, - TerminatorInst *TI) { + Instruction *TI) { assert(OldBranch->isUnconditional() && "Preheader is not split correctly"); assert(TrueDest != FalseDest && "Branch targets should be different"); // Insert a conditional branch on LIC to the two preheaders. The original @@ -952,13 +974,16 @@ void LoopUnswitch::EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val, if (OldBranchSucc != TrueDest && OldBranchSucc != FalseDest) { Updates.push_back({DominatorTree::Delete, OldBranchParent, OldBranchSucc}); } - DT->applyUpdates(Updates); + + if (MSSAU) + MSSAU->applyUpdates(Updates, *DT); } // If either edge is critical, split it. This helps preserve LoopSimplify // form for enclosing loops. - auto Options = CriticalEdgeSplittingOptions(DT, LI).setPreserveLCSSA(); + auto Options = + CriticalEdgeSplittingOptions(DT, LI, MSSAU.get()).setPreserveLCSSA(); SplitCriticalEdge(BI, 0, Options); SplitCriticalEdge(BI, 1, Options); } @@ -970,7 +995,7 @@ void LoopUnswitch::EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val, /// outside of the loop and updating loop info. void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond, Constant *Val, BasicBlock *ExitBlock, - TerminatorInst *TI) { + Instruction *TI) { LLVM_DEBUG(dbgs() << "loop-unswitch: Trivial-Unswitch loop %" << loopHeader->getName() << " [" << L->getBlocks().size() << " blocks] in Function " @@ -984,7 +1009,7 @@ void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond, Constant *Val, // First step, split the preheader, so that we know that there is a safe place // to insert the conditional branch. We will change loopPreheader to have a // conditional branch on Cond. - BasicBlock *NewPH = SplitEdge(loopPreheader, loopHeader, DT, LI); + BasicBlock *NewPH = SplitEdge(loopPreheader, loopHeader, DT, LI, MSSAU.get()); // Now that we have a place to insert the conditional branch, create a place // to branch to: this is the exit block out of the loop that we should @@ -995,7 +1020,8 @@ void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond, Constant *Val, // without actually branching to it (the exit block should be dominated by the // loop header, not the preheader). assert(!L->contains(ExitBlock) && "Exit block is in the loop?"); - BasicBlock *NewExit = SplitBlock(ExitBlock, &ExitBlock->front(), DT, LI); + BasicBlock *NewExit = + SplitBlock(ExitBlock, &ExitBlock->front(), DT, LI, MSSAU.get()); // Okay, now we have a position to branch from and a position to branch to, // insert the new conditional branch. @@ -1015,6 +1041,7 @@ void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond, Constant *Val, // particular value, rewrite the loop with this info. We know that this will // at least eliminate the old branch. RewriteLoopBodyWithConditionConstant(L, Cond, Val, false); + ++NumTrivial; } @@ -1026,7 +1053,7 @@ void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond, Constant *Val, /// condition. bool LoopUnswitch::TryTrivialLoopUnswitch(bool &Changed) { BasicBlock *CurrentBB = currentLoop->getHeader(); - TerminatorInst *CurrentTerm = CurrentBB->getTerminator(); + Instruction *CurrentTerm = CurrentBB->getTerminator(); LLVMContext &Context = CurrentBB->getContext(); // If loop header has only one reachable successor (currently via an @@ -1190,7 +1217,7 @@ void LoopUnswitch::SplitExitEdges(Loop *L, // Although SplitBlockPredecessors doesn't preserve loop-simplify in // general, if we call it on all predecessors of all exits then it does. - SplitBlockPredecessors(ExitBlock, Preds, ".us-lcssa", DT, LI, + SplitBlockPredecessors(ExitBlock, Preds, ".us-lcssa", DT, LI, MSSAU.get(), /*PreserveLCSSA*/ true); } } @@ -1199,7 +1226,7 @@ void LoopUnswitch::SplitExitEdges(Loop *L, /// Split it into loop versions and test the condition outside of either loop. /// Return the loops created as Out1/Out2. void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, - Loop *L, TerminatorInst *TI) { + Loop *L, Instruction *TI) { Function *F = loopHeader->getParent(); LLVM_DEBUG(dbgs() << "loop-unswitch: Unswitching loop %" << loopHeader->getName() << " [" << L->getBlocks().size() @@ -1216,7 +1243,8 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, // First step, split the preheader and exit blocks, and add these blocks to // the LoopBlocks list. - BasicBlock *NewPreheader = SplitEdge(loopPreheader, loopHeader, DT, LI); + BasicBlock *NewPreheader = + SplitEdge(loopPreheader, loopHeader, DT, LI, MSSAU.get()); LoopBlocks.push_back(NewPreheader); // We want the loop to come after the preheader, but before the exit blocks. @@ -1318,10 +1346,24 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, assert(OldBR->isUnconditional() && OldBR->getSuccessor(0) == LoopBlocks[0] && "Preheader splitting did not work correctly!"); + if (MSSAU) { + // Update MemorySSA after cloning, and before splitting to unreachables, + // since that invalidates the 1:1 mapping of clones in VMap. + LoopBlocksRPO LBRPO(L); + LBRPO.perform(LI); + MSSAU->updateForClonedLoop(LBRPO, ExitBlocks, VMap); + } + // Emit the new branch that selects between the two versions of this loop. EmitPreheaderBranchOnCondition(LIC, Val, NewBlocks[0], LoopBlocks[0], OldBR, TI); LPM->deleteSimpleAnalysisValue(OldBR, L); + if (MSSAU) { + // Update MemoryPhis in Exit blocks. + MSSAU->updateExitBlocksForClonedLoop(ExitBlocks, VMap, *DT); + if (VerifyMemorySSA) + MSSA->verifyMemorySSA(); + } // The OldBr was replaced by a new one and removed (but not erased) by // EmitPreheaderBranchOnCondition. It is no longer needed, so delete it. @@ -1347,6 +1389,9 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, if (!LoopProcessWorklist.empty() && LoopProcessWorklist.back() == NewLoop && LICHandle && !isa<Constant>(LICHandle)) RewriteLoopBodyWithConditionConstant(NewLoop, LICHandle, Val, true); + + if (MSSA && VerifyMemorySSA) + MSSA->verifyMemorySSA(); } /// Remove all instances of I from the worklist vector specified. @@ -1485,7 +1530,7 @@ void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC, // and hooked up so as to preserve the loop structure, because // trying to update it is complicated. So instead we preserve the // loop structure and put the block on a dead code path. - SplitEdge(Switch, SISucc, DT, LI); + SplitEdge(Switch, SISucc, DT, LI, MSSAU.get()); // Compute the successors instead of relying on the return value // of SplitEdge, since it may have split the switch successor // after PHI nodes. @@ -1539,6 +1584,8 @@ void LoopUnswitch::SimplifyCode(std::vector<Instruction*> &Worklist, Loop *L) { Worklist.push_back(Use); LPM->deleteSimpleAnalysisValue(I, L); RemoveFromWorklist(I, Worklist); + if (MSSAU) + MSSAU->removeMemoryAccess(I); I->eraseFromParent(); ++NumSimplify; continue; @@ -1578,6 +1625,8 @@ void LoopUnswitch::SimplifyCode(std::vector<Instruction*> &Worklist, Loop *L) { // Move all of the successor contents from Succ to Pred. Pred->getInstList().splice(BI->getIterator(), Succ->getInstList(), Succ->begin(), Succ->end()); + if (MSSAU) + MSSAU->moveAllAfterMergeBlocks(Succ, Pred, BI); LPM->deleteSimpleAnalysisValue(BI, L); RemoveFromWorklist(BI, Worklist); BI->eraseFromParent(); |