Index: lib/Transforms/Scalar/SimpleLoopUnswitch.cpp =================================================================== --- lib/Transforms/Scalar/SimpleLoopUnswitch.cpp +++ lib/Transforms/Scalar/SimpleLoopUnswitch.cpp @@ -25,6 +25,8 @@ #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/Utils/Local.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constant.h" @@ -349,7 +351,8 @@ /// If `SE` is not null, it will be updated based on the potential loop SCEVs /// invalidated by this. static bool unswitchTrivialBranch(Loop &L, BranchInst &BI, DominatorTree &DT, - LoopInfo &LI, ScalarEvolution *SE) { + LoopInfo &LI, ScalarEvolution *SE, + MemorySSAUpdater *MSSAU) { assert(BI.isConditional() && "Can only unswitch a conditional branch!"); LLVM_DEBUG(dbgs() << " Trying to unswitch branch: " << BI << "\n"); @@ -423,11 +426,14 @@ SE->forgetTopmostLoop(&L); } + if (MSSAU && VerifyMemorySSA) + MSSAU->getMemorySSA()->verifyMemorySSA(); + // Split the preheader, so that we know that there is a safe place to insert // the conditional branch. We will change the preheader to have a conditional // branch on LoopCond. BasicBlock *OldPH = L.getLoopPreheader(); - BasicBlock *NewPH = SplitEdge(OldPH, L.getHeader(), &DT, &LI); + BasicBlock *NewPH = SplitEdge(OldPH, L.getHeader(), &DT, &LI, MSSAU); // 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 are @@ -439,9 +445,13 @@ "A branch's parent isn't a predecessor!"); UnswitchedBB = LoopExitBB; } else { - UnswitchedBB = SplitBlock(LoopExitBB, &LoopExitBB->front(), &DT, &LI); + UnswitchedBB = + SplitBlock(LoopExitBB, &LoopExitBB->front(), &DT, &LI, MSSAU); } + if (MSSAU && VerifyMemorySSA) + MSSAU->getMemorySSA()->verifyMemorySSA(); + // Actually move the invariant uses into the unswitched position. If possible, // we do this by moving the instructions, but when doing partial unswitching // we do it by building a new merge of the values in the unswitched position. @@ -452,12 +462,17 @@ // its successors. OldPH->getInstList().splice(OldPH->end(), BI.getParent()->getInstList(), BI); + if (MSSAU) { + // Temporarily clone the terminator, to make MSSA update cheaper by + // separating "insert edge" updates from "remove edge" ones. + ParentBB->getInstList().push_back(BI.clone()); + } else { + // Create a new unconditional branch that will continue the loop as a new + // terminator. + BranchInst::Create(ContinueBB, ParentBB); + } BI.setSuccessor(LoopExitSuccIdx, UnswitchedBB); BI.setSuccessor(1 - LoopExitSuccIdx, NewPH); - - // Create a new unconditional branch that will continue the loop as a new - // terminator. - BranchInst::Create(ContinueBB, ParentBB); } else { // Only unswitching a subset of inputs to the condition, so we will need to // build a new branch that merges the invariant inputs. @@ -473,6 +488,32 @@ *UnswitchedBB, *NewPH); } + // Update the dominator tree with the added edge. + DT.insertEdge(OldPH, UnswitchedBB); + + // After the dominator tree was updated with the added edge, update MemorySSA + // if available. + if (MSSAU) { + SmallVector Updates; + Updates.push_back({cfg::UpdateKind::Insert, OldPH, UnswitchedBB}); + MSSAU->applyInsertUpdates(Updates, DT); + } + + // Finish updating dominator tree and memory ssa for full unswitch. + if (FullUnswitch) { + if (MSSAU) { + // Remove the cloned branch instruction. + ParentBB->getTerminator()->eraseFromParent(); + // Create unconditional branch now. + BranchInst::Create(ContinueBB, ParentBB); + MSSAU->removeEdge(ParentBB, LoopExitBB); + } + DT.deleteEdge(ParentBB, LoopExitBB); + } + + if (MSSAU && VerifyMemorySSA) + MSSAU->getMemorySSA()->verifyMemorySSA(); + // Rewrite the relevant PHI nodes. if (UnswitchedBB == LoopExitBB) rewritePHINodesForUnswitchedExitBlock(*UnswitchedBB, *ParentBB, *OldPH); @@ -480,13 +521,6 @@ rewritePHINodesForExitAndUnswitchedBlocks(*LoopExitBB, *UnswitchedBB, *ParentBB, *OldPH, FullUnswitch); - // Now we need to update the dominator tree. - SmallVector DTUpdates; - DTUpdates.push_back({DT.Insert, OldPH, UnswitchedBB}); - if (FullUnswitch) - DTUpdates.push_back({DT.Delete, ParentBB, LoopExitBB}); - DT.applyUpdates(DTUpdates); - // The constant we can replace all of our invariants with inside the loop // body. If any of the invariants have a value other than this the loop won't // be entered. @@ -537,7 +571,8 @@ /// If `SE` is not null, it will be updated based on the potential loop SCEVs /// invalidated by this. static bool unswitchTrivialSwitch(Loop &L, SwitchInst &SI, DominatorTree &DT, - LoopInfo &LI, ScalarEvolution *SE) { + LoopInfo &LI, ScalarEvolution *SE, + MemorySSAUpdater *MSSAU) { LLVM_DEBUG(dbgs() << " Trying to unswitch switch: " << SI << "\n"); Value *LoopCond = SI.getCondition(); @@ -564,6 +599,9 @@ LLVM_DEBUG(dbgs() << " unswitching trivial switch...\n"); + if (MSSAU && VerifyMemorySSA) + MSSAU->getMemorySSA()->verifyMemorySSA(); + // We may need to invalidate SCEVs for the outermost loop reached by any of // the exits. Loop *OuterL = &L; @@ -626,7 +664,7 @@ // Split the preheader, so that we know that there is a safe place to insert // the switch. BasicBlock *OldPH = L.getLoopPreheader(); - BasicBlock *NewPH = SplitEdge(OldPH, L.getHeader(), &DT, &LI); + BasicBlock *NewPH = SplitEdge(OldPH, L.getHeader(), &DT, &LI, MSSAU); OldPH->getTerminator()->eraseFromParent(); // Now add the unswitched switch. @@ -649,9 +687,10 @@ rewritePHINodesForUnswitchedExitBlock(*DefaultExitBB, *ParentBB, *OldPH); } else { auto *SplitBB = - SplitBlock(DefaultExitBB, &DefaultExitBB->front(), &DT, &LI); - rewritePHINodesForExitAndUnswitchedBlocks( - *DefaultExitBB, *SplitBB, *ParentBB, *OldPH, /*FullUnswitch*/ true); + SplitBlock(DefaultExitBB, &DefaultExitBB->front(), &DT, &LI, MSSAU); + rewritePHINodesForExitAndUnswitchedBlocks(*DefaultExitBB, *SplitBB, + *ParentBB, *OldPH, + /*FullUnswitch*/ true); DefaultExitBB = SplitExitBBMap[DefaultExitBB] = SplitBB; } } @@ -675,9 +714,10 @@ BasicBlock *&SplitExitBB = SplitExitBBMap[ExitBB]; if (!SplitExitBB) { // If this is the first time we see this, do the split and remember it. - SplitExitBB = SplitBlock(ExitBB, &ExitBB->front(), &DT, &LI); - rewritePHINodesForExitAndUnswitchedBlocks( - *ExitBB, *SplitExitBB, *ParentBB, *OldPH, /*FullUnswitch*/ true); + SplitExitBB = SplitBlock(ExitBB, &ExitBB->front(), &DT, &LI, MSSAU); + rewritePHINodesForExitAndUnswitchedBlocks(*ExitBB, *SplitExitBB, + *ParentBB, *OldPH, + /*FullUnswitch*/ true); } // Update the case pair to point to the split block. CasePair.second = SplitExitBB; @@ -754,6 +794,13 @@ DTUpdates.push_back({DT.Insert, OldPH, UnswitchedBB}); } DT.applyUpdates(DTUpdates); + + if (MSSAU) { + MSSAU->applyUpdates(DTUpdates, DT); + if (VerifyMemorySSA) + MSSAU->getMemorySSA()->verifyMemorySSA(); + } + assert(DT.verify(DominatorTree::VerificationLevel::Fast)); // We may have changed the nesting relationship for this loop so hoist it to @@ -779,7 +826,8 @@ /// If `SE` is not null, it will be updated based on the potential loop SCEVs /// invalidated by this. static bool unswitchAllTrivialConditions(Loop &L, DominatorTree &DT, - LoopInfo &LI, ScalarEvolution *SE) { + LoopInfo &LI, ScalarEvolution *SE, + MemorySSAUpdater *MSSAU) { bool Changed = false; // If loop header has only one reachable successor we should keep looking for @@ -813,7 +861,7 @@ if (isa(SI->getCondition())) return Changed; - if (!unswitchTrivialSwitch(L, *SI, DT, LI, SE)) + if (!unswitchTrivialSwitch(L, *SI, DT, LI, SE, MSSAU)) // Couldn't unswitch this one so we're done. return Changed; @@ -845,7 +893,7 @@ // Found a trivial condition candidate: non-foldable conditional branch. If // we fail to unswitch this, we can't do anything else that is trivial. - if (!unswitchTrivialBranch(L, *BI, DT, LI, SE)) + if (!unswitchTrivialBranch(L, *BI, DT, LI, SE, MSSAU)) return Changed; // Mark that we managed to unswitch something. @@ -898,7 +946,7 @@ const SmallDenseMap &DominatingSucc, ValueToValueMapTy &VMap, SmallVectorImpl &DTUpdates, AssumptionCache &AC, - DominatorTree &DT, LoopInfo &LI) { + DominatorTree &DT, LoopInfo &LI, MemorySSAUpdater *MSSAU) { SmallVector NewBlocks; NewBlocks.reserve(L.getNumBlocks() + ExitBlocks.size()); @@ -943,7 +991,7 @@ // place to merge the CFG, so split the exit first. This is always safe to // do because there cannot be any non-loop predecessors of a loop exit in // loop simplified form. - auto *MergeBB = SplitBlock(ExitBB, &ExitBB->front(), &DT, &LI); + auto *MergeBB = SplitBlock(ExitBB, &ExitBB->front(), &DT, &LI, MSSAU); // Rearrange the names to make it easier to write test cases by having the // exit block carry the suffix rather than the merge block carrying the @@ -1374,7 +1422,7 @@ static void deleteDeadClonedBlocks(Loop &L, ArrayRef ExitBlocks, ArrayRef> VMaps, - DominatorTree &DT) { + DominatorTree &DT, MemorySSAUpdater *MSSAU) { // Find all the dead clones, and remove them from their successors. SmallVector DeadBlocks; for (BasicBlock *BB : llvm::concat(L.blocks(), ExitBlocks)) @@ -1386,6 +1434,13 @@ DeadBlocks.push_back(ClonedBB); } + // Remove all MemorySSA in the dead blocks + if (MSSAU) { + SmallPtrSet DeadBlockSet(DeadBlocks.begin(), + DeadBlocks.end()); + MSSAU->removeBlocks(DeadBlockSet); + } + // Drop any remaining references to break cycles. for (BasicBlock *BB : DeadBlocks) BB->dropAllReferences(); @@ -1394,10 +1449,10 @@ BB->eraseFromParent(); } -static void -deleteDeadBlocksFromLoop(Loop &L, - SmallVectorImpl &ExitBlocks, - DominatorTree &DT, LoopInfo &LI) { +static void deleteDeadBlocksFromLoop(Loop &L, + SmallVectorImpl &ExitBlocks, + DominatorTree &DT, LoopInfo &LI, + MemorySSAUpdater *MSSAU) { // Find all the dead blocks tied to this loop, and remove them from their // successors. SmallPtrSet DeadBlockSet; @@ -1418,6 +1473,10 @@ } } + // Remove all MemorySSA in the dead blocks + if (MSSAU) + MSSAU->removeBlocks(DeadBlockSet); + // Filter out the dead blocks from the exit blocks list so that it can be // used in the caller. llvm::erase_if(ExitBlocks, @@ -1817,7 +1876,7 @@ Loop &L, Instruction &TI, ArrayRef Invariants, SmallVectorImpl &ExitBlocks, DominatorTree &DT, LoopInfo &LI, AssumptionCache &AC, function_ref)> UnswitchCB, - ScalarEvolution *SE) { + ScalarEvolution *SE, MemorySSAUpdater *MSSAU) { auto *ParentBB = TI.getParent(); BranchInst *BI = dyn_cast(&TI); SwitchInst *SI = BI ? nullptr : cast(&TI); @@ -1834,6 +1893,9 @@ assert(isa(BI->getCondition()) && "Partial unswitching requires an instruction as the condition!"); + if (MSSAU && VerifyMemorySSA) + MSSAU->getMemorySSA()->verifyMemorySSA(); + // Constant and BBs tracking the cloned and continuing successor. When we are // unswitching the entire condition, this can just be trivially chosen to // unswitch towards `true`. However, when we are unswitching a set of @@ -1874,6 +1936,10 @@ // Compute the parent loop now before we start hacking on things. Loop *ParentL = L.getParentLoop(); + // Get blocks in RPO order for MSSA update, before changing the CFG. + LoopBlocksRPO LBRPO(&L); + if (MSSAU) + LBRPO.perform(&LI); // Compute the outer-most loop containing one of our exit blocks. This is the // furthest up our loopnest which can be mutated, which we will use below to @@ -1923,7 +1989,7 @@ // between the unswitched versions, and we will have a new preheader for the // original loop. BasicBlock *SplitBB = L.getLoopPreheader(); - BasicBlock *LoopPH = SplitEdge(SplitBB, L.getHeader(), &DT, &LI); + BasicBlock *LoopPH = SplitEdge(SplitBB, L.getHeader(), &DT, &LI, MSSAU); // Keep track of the dominator tree updates needed. SmallVector DTUpdates; @@ -1936,7 +2002,7 @@ VMaps.emplace_back(new ValueToValueMapTy()); ClonedPHs[SuccBB] = buildClonedLoopBlocks( L, LoopPH, SplitBB, ExitBlocks, ParentBB, SuccBB, RetainedSuccBB, - DominatingSucc, *VMaps.back(), DTUpdates, AC, DT, LI); + DominatingSucc, *VMaps.back(), DTUpdates, AC, DT, LI, MSSAU); } // The stitching of the branched code back together depends on whether we're @@ -1944,7 +2010,63 @@ // nuke the initial terminator placed in the split block. SplitBB->getTerminator()->eraseFromParent(); if (FullUnswitch) { - // First we need to unhook the successor relationship as we'll be replacing + // Splice the terminator from the original loop and rewrite its + // successors. + SplitBB->getInstList().splice(SplitBB->end(), ParentBB->getInstList(), TI); + + // Keep a clone of the terminator for MSSA updates. + Instruction *NewTI = TI.clone(); + ParentBB->getInstList().push_back(NewTI); + + // First wire up the moved terminator to the preheaders. + if (BI) { + BasicBlock *ClonedPH = ClonedPHs.begin()->second; + BI->setSuccessor(ClonedSucc, ClonedPH); + BI->setSuccessor(1 - ClonedSucc, LoopPH); + DTUpdates.push_back({DominatorTree::Insert, SplitBB, ClonedPH}); + } else { + assert(SI && "Must either be a branch or switch!"); + + // Walk the cases and directly update their successors. + assert(SI->getDefaultDest() == RetainedSuccBB && + "Not retaining default successor!"); + SI->setDefaultDest(LoopPH); + for (auto &Case : SI->cases()) + if (Case.getCaseSuccessor() == RetainedSuccBB) + Case.setSuccessor(LoopPH); + else + Case.setSuccessor(ClonedPHs.find(Case.getCaseSuccessor())->second); + + // We need to use the set to populate domtree updates as even when there + // are multiple cases pointing at the same successor we only want to + // remove and insert one edge in the domtree. + for (BasicBlock *SuccBB : UnswitchedSuccBBs) + DTUpdates.push_back( + {DominatorTree::Insert, SplitBB, ClonedPHs.find(SuccBB)->second}); + } + + if (MSSAU) { + DT.applyUpdates(DTUpdates); + DTUpdates.clear(); + + // Remove all but one edge to the retained block and all unswitched + // blocks. This is to avoid having duplicate entries in the cloned Phis, + // when we know we only keep a single edge for each case. + MSSAU->removeDuplicatePhiEdgesBetween(ParentBB, RetainedSuccBB); + for (BasicBlock *SuccBB : UnswitchedSuccBBs) + MSSAU->removeDuplicatePhiEdgesBetween(ParentBB, SuccBB); + + for (auto &VMap : VMaps) + MSSAU->updateForClonedLoop(LBRPO, ExitBlocks, *VMap, + /*IgnoreIncomingWithNoClones=*/true); + MSSAU->updateExitBlocksForClonedLoop(ExitBlocks, VMaps, DT); + + // Remove all edges to unswitched blocks. + for (BasicBlock *SuccBB : UnswitchedSuccBBs) + MSSAU->removeEdge(ParentBB, SuccBB); + } + + // Now unhook the successor relationship as we'll be replacing // the terminator with a direct branch. This is much simpler for branches // than switches so we handle those first. if (BI) { @@ -1962,9 +2084,10 @@ // is a duplicate edge to the retained successor as the retained successor // is always the default successor and as we'll replace this with a direct // branch we no longer need the duplicate entries in the PHI nodes. - assert(SI->getDefaultDest() == RetainedSuccBB && + SwitchInst *NewSI = cast(NewTI); + assert(NewSI->getDefaultDest() == RetainedSuccBB && "Not retaining default successor!"); - for (auto &Case : SI->cases()) + for (auto &Case : NewSI->cases()) Case.getCaseSuccessor()->removePredecessor( ParentBB, /*DontDeleteUselessPHIs*/ true); @@ -1976,34 +2099,8 @@ DTUpdates.push_back({DominatorTree::Delete, ParentBB, SuccBB}); } - // Now that we've unhooked the successor relationship, splice the terminator - // from the original loop to the split. - SplitBB->getInstList().splice(SplitBB->end(), ParentBB->getInstList(), TI); - - // Now wire up the terminator to the preheaders. - if (BI) { - BasicBlock *ClonedPH = ClonedPHs.begin()->second; - BI->setSuccessor(ClonedSucc, ClonedPH); - BI->setSuccessor(1 - ClonedSucc, LoopPH); - DTUpdates.push_back({DominatorTree::Insert, SplitBB, ClonedPH}); - } else { - assert(SI && "Must either be a branch or switch!"); - - // Walk the cases and directly update their successors. - SI->setDefaultDest(LoopPH); - for (auto &Case : SI->cases()) - if (Case.getCaseSuccessor() == RetainedSuccBB) - Case.setSuccessor(LoopPH); - else - Case.setSuccessor(ClonedPHs.find(Case.getCaseSuccessor())->second); - - // We need to use the set to populate domtree updates as even when there - // are multiple cases pointing at the same successor we only want to - // remove and insert one edge in the domtree. - for (BasicBlock *SuccBB : UnswitchedSuccBBs) - DTUpdates.push_back( - {DominatorTree::Insert, SplitBB, ClonedPHs.find(SuccBB)->second}); - } + // After MSSAU update, remove the cloned terminator instruction NewTI. + ParentBB->getTerminator()->eraseFromParent(); // Create a new unconditional branch to the continuing block (as opposed to // the one cloned). @@ -2022,12 +2119,19 @@ // Apply the updates accumulated above to get an up-to-date dominator tree. DT.applyUpdates(DTUpdates); + if (!FullUnswitch && MSSAU) { + // Update MSSA for partial unswitch, after DT update. + SmallVector Updates; + Updates.push_back( + {cfg::UpdateKind::Insert, SplitBB, ClonedPHs.begin()->second}); + MSSAU->applyInsertUpdates(Updates, DT); + } // Now that we have an accurate dominator tree, first delete the dead cloned // blocks so that we can accurately build any cloned loops. It is important to // not delete the blocks from the original loop yet because we still want to // reference the original loop to understand the cloned loop's structure. - deleteDeadClonedBlocks(L, ExitBlocks, VMaps, DT); + deleteDeadClonedBlocks(L, ExitBlocks, VMaps, DT, MSSAU); // Build the cloned loop structure itself. This may be substantially // different from the original structure due to the simplified CFG. This also @@ -2039,10 +2143,17 @@ // Now that our cloned loops have been built, we can update the original loop. // First we delete the dead blocks from it and then we rebuild the loop // structure taking these deletions into account. - deleteDeadBlocksFromLoop(L, ExitBlocks, DT, LI); + deleteDeadBlocksFromLoop(L, ExitBlocks, DT, LI, MSSAU); + + if (MSSAU && VerifyMemorySSA) + MSSAU->getMemorySSA()->verifyMemorySSA(); + SmallVector HoistedLoops; bool IsStillLoop = rebuildLoopAfterUnswitch(L, ExitBlocks, LI, HoistedLoops); + if (MSSAU && VerifyMemorySSA) + MSSAU->getMemorySSA()->verifyMemorySSA(); + // This transformation has a high risk of corrupting the dominator tree, and // the below steps to rebuild loop structures will result in hard to debug // errors in that case so verify that the dominator tree is sane first. @@ -2167,6 +2278,9 @@ SibLoops.push_back(UpdatedL); UnswitchCB(IsStillLoop, SibLoops); + if (MSSAU && VerifyMemorySSA) + MSSAU->getMemorySSA()->verifyMemorySSA(); + ++NumBranches; } @@ -2227,11 +2341,16 @@ static BranchInst * turnGuardIntoBranch(IntrinsicInst *GI, Loop &L, SmallVectorImpl &ExitBlocks, - DominatorTree &DT, LoopInfo &LI) { + DominatorTree &DT, LoopInfo &LI, MemorySSAUpdater *MSSAU) { SmallVector DTUpdates; LLVM_DEBUG(dbgs() << "Turning " << *GI << " into a branch.\n"); BasicBlock *CheckBB = GI->getParent(); + if (MSSAU && VerifyMemorySSA) { + MSSAU->getMemorySSA()->verifyMemorySSA(); + MSSAU->getMemorySSA()->dump(); + } + // Remove all CheckBB's successors from DomTree. A block can be seen among // successors more than once, but for DomTree it should be added only once. SmallPtrSet Successors; @@ -2249,10 +2368,14 @@ BasicBlock *GuardedBlock = CheckBI->getSuccessor(0); GuardedBlock->setName("guarded"); CheckBI->getSuccessor(1)->setName("deopt"); + BasicBlock *DeoptBlock = CheckBI->getSuccessor(1); // We now have a new exit block. ExitBlocks.push_back(CheckBI->getSuccessor(1)); + if (MSSAU) + MSSAU->moveAllAfterSpliceBlocks(CheckBB, GuardedBlock, GI); + GI->moveBefore(DeoptBlockTerm); GI->setArgOperand(0, ConstantInt::getFalse(GI->getContext())); @@ -2270,6 +2393,13 @@ // Inform LI of a new loop block. L.addBasicBlockToLoop(GuardedBlock, LI); + if (MSSAU) { + MemoryDef *MD = cast(MSSAU->getMemorySSA()->getMemoryAccess(GI)); + MSSAU->moveToPlace(MD, DeoptBlock, MemorySSA::End); + if (VerifyMemorySSA) + MSSAU->getMemorySSA()->verifyMemorySSA(); + } + ++NumGuards; return CheckBI; } @@ -2363,7 +2493,7 @@ unswitchBestCondition(Loop &L, DominatorTree &DT, LoopInfo &LI, AssumptionCache &AC, TargetTransformInfo &TTI, function_ref)> UnswitchCB, - ScalarEvolution *SE) { + ScalarEvolution *SE, MemorySSAUpdater *MSSAU) { // Collect all invariant conditions within this loop (as opposed to an inner // loop which would be handled when visiting that inner loop). SmallVector>, 4> @@ -2605,13 +2735,13 @@ // If the best candidate is a guard, turn it into a branch. if (isGuard(BestUnswitchTI)) BestUnswitchTI = turnGuardIntoBranch(cast(BestUnswitchTI), L, - ExitBlocks, DT, LI); + ExitBlocks, DT, LI, MSSAU); LLVM_DEBUG(dbgs() << " Unswitching non-trivial (cost = " << BestUnswitchCost << ") terminator: " << *BestUnswitchTI << "\n"); unswitchNontrivialInvariants(L, *BestUnswitchTI, BestUnswitchInvariants, - ExitBlocks, DT, LI, AC, UnswitchCB, SE); + ExitBlocks, DT, LI, AC, UnswitchCB, SE, MSSAU); return true; } @@ -2624,6 +2754,7 @@ /// /// The `DT`, `LI`, `AC`, `TTI` parameters are required analyses that are also /// updated based on the unswitch. +/// The `MSSA` analysis is also updated if valid (i.e. its use is enabled). /// /// If either `NonTrivial` is true or the flag `EnableNonTrivialUnswitch` is /// true, we will attempt to do non-trivial unswitching as well as trivial @@ -2639,7 +2770,7 @@ AssumptionCache &AC, TargetTransformInfo &TTI, bool NonTrivial, function_ref)> UnswitchCB, - ScalarEvolution *SE) { + ScalarEvolution *SE, MemorySSAUpdater *MSSAU) { assert(L.isRecursivelyLCSSAForm(DT, LI) && "Loops must be in LCSSA form before unswitching."); bool Changed = false; @@ -2649,7 +2780,7 @@ return false; // Try trivial unswitch first before loop over other basic blocks in the loop. - if (unswitchAllTrivialConditions(L, DT, LI, SE)) { + if (unswitchAllTrivialConditions(L, DT, LI, SE, MSSAU)) { // If we unswitched successfully we will want to clean up the loop before // processing it further so just mark it as unswitched and return. UnswitchCB(/*CurrentLoopValid*/ true, {}); @@ -2670,7 +2801,7 @@ // Try to unswitch the best invariant condition. We prefer this full unswitch to // a partial unswitch when possible below the threshold. - if (unswitchBestCondition(L, DT, LI, AC, TTI, UnswitchCB, SE)) + if (unswitchBestCondition(L, DT, LI, AC, TTI, UnswitchCB, SE, MSSAU)) return true; // No other opportunities to unswitch. @@ -2704,10 +2835,19 @@ U.markLoopAsDeleted(L, LoopName); }; + Optional MSSAU; + if (AR.MSSA) { + MSSAU = MemorySSAUpdater(AR.MSSA); + if (VerifyMemorySSA) + AR.MSSA->verifyMemorySSA(); + } if (!unswitchLoop(L, AR.DT, AR.LI, AR.AC, AR.TTI, NonTrivial, UnswitchCB, - &AR.SE)) + &AR.SE, MSSAU.hasValue() ? MSSAU.getPointer() : nullptr)) return PreservedAnalyses::all(); + if (AR.MSSA && VerifyMemorySSA) + AR.MSSA->verifyMemorySSA(); + // Historically this pass has had issues with the dominator tree so verify it // in asserts builds. assert(AR.DT.verify(DominatorTree::VerificationLevel::Fast)); @@ -2733,6 +2873,10 @@ void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); AU.addRequired(); + if (EnableMSSALoopDependency) { + AU.addRequired(); + AU.addPreserved(); + } getLoopAnalysisUsage(AU); } }; @@ -2752,6 +2896,12 @@ auto &LI = getAnalysis().getLoopInfo(); auto &AC = getAnalysis().getAssumptionCache(F); auto &TTI = getAnalysis().getTTI(F); + MemorySSA *MSSA = nullptr; + Optional MSSAU; + if (EnableMSSALoopDependency) { + MSSA = &getAnalysis().getMSSA(); + MSSAU = MemorySSAUpdater(MSSA); + } auto *SEWP = getAnalysisIfAvailable(); auto *SE = SEWP ? &SEWP->getSE() : nullptr; @@ -2771,7 +2921,14 @@ LPM.markLoopAsDeleted(*L); }; - bool Changed = unswitchLoop(*L, DT, LI, AC, TTI, NonTrivial, UnswitchCB, SE); + if (MSSA && VerifyMemorySSA) + MSSA->verifyMemorySSA(); + + bool Changed = unswitchLoop(*L, DT, LI, AC, TTI, NonTrivial, UnswitchCB, SE, + MSSAU.hasValue() ? MSSAU.getPointer() : nullptr); + + if (MSSA && VerifyMemorySSA) + MSSA->verifyMemorySSA(); // If anything was unswitched, also clear any cached information about this // loop. @@ -2791,6 +2948,7 @@ INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) INITIALIZE_PASS_DEPENDENCY(LoopPass) +INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass) INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) INITIALIZE_PASS_END(SimpleLoopUnswitchLegacyPass, "simple-loop-unswitch", "Simple unswitch loops", false, false) Index: test/Transforms/SimpleLoopUnswitch/2006-06-13-SingleEntryPHI.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2006-06-13-SingleEntryPHI.ll +++ test/Transforms/SimpleLoopUnswitch/2006-06-13-SingleEntryPHI.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -simple-loop-unswitch -disable-output +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -disable-output %struct.BLEND_MAP = type { i16, i16, i16, i32, %struct.BLEND_MAP_ENTRY* } %struct.BLEND_MAP_ENTRY = type { float, i8, { [5 x float], [4 x i8] } } Index: test/Transforms/SimpleLoopUnswitch/2006-06-27-DeadSwitchCase.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2006-06-27-DeadSwitchCase.ll +++ test/Transforms/SimpleLoopUnswitch/2006-06-27-DeadSwitchCase.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -simple-loop-unswitch -disable-output +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -disable-output define void @init_caller_save() { entry: Index: test/Transforms/SimpleLoopUnswitch/2007-05-09-Unreachable.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2007-05-09-Unreachable.ll +++ test/Transforms/SimpleLoopUnswitch/2007-05-09-Unreachable.ll @@ -1,5 +1,6 @@ ; PR1333 ; RUN: opt < %s -simple-loop-unswitch -disable-output +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -disable-output target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64" target triple = "i686-pc-linux-gnu" Index: test/Transforms/SimpleLoopUnswitch/2007-05-09-tl.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2007-05-09-tl.ll +++ test/Transforms/SimpleLoopUnswitch/2007-05-09-tl.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -simple-loop-unswitch -disable-output +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -disable-output ; PR1333 define void @pp_cxx_expression() { Index: test/Transforms/SimpleLoopUnswitch/2007-07-12-ExitDomInfo.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2007-07-12-ExitDomInfo.ll +++ test/Transforms/SimpleLoopUnswitch/2007-07-12-ExitDomInfo.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -simple-loop-unswitch -instcombine -disable-output +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -instcombine -disable-output @str3 = external constant [3 x i8] ; <[3 x i8]*> [#uses=1] Index: test/Transforms/SimpleLoopUnswitch/2007-07-13-DomInfo.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2007-07-13-DomInfo.ll +++ test/Transforms/SimpleLoopUnswitch/2007-07-13-DomInfo.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -simple-loop-unswitch -disable-output +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -disable-output define i32 @main(i32 %argc, i8** %argv) { entry: Index: test/Transforms/SimpleLoopUnswitch/2007-07-18-DomInfo.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2007-07-18-DomInfo.ll +++ test/Transforms/SimpleLoopUnswitch/2007-07-18-DomInfo.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -simple-loop-unswitch -disable-output +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -disable-output ; PR1559 target triple = "i686-pc-linux-gnu" Index: test/Transforms/SimpleLoopUnswitch/2007-08-01-LCSSA.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2007-08-01-LCSSA.ll +++ test/Transforms/SimpleLoopUnswitch/2007-08-01-LCSSA.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -simple-loop-unswitch -instcombine -disable-output +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -instcombine -disable-output %struct.ClassDef = type { %struct.QByteArray, %struct.QByteArray, %"struct.QList", %"struct.QList", i8, i8, %"struct.QList", %"struct.QList", %"struct.QList", %"struct.QList", %"struct.QList", %"struct.QList", %"struct.QMap", %"struct.QList", %"struct.QMap", i32, i32 } %struct.FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct.FILE*, i32, i32, i32, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i32, i32, [40 x i8] } %struct.Generator = type { %struct.FILE*, %struct.ClassDef*, %"struct.QList", %struct.QByteArray, %"struct.QList" } Index: test/Transforms/SimpleLoopUnswitch/2008-06-02-DomInfo.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2008-06-02-DomInfo.ll +++ test/Transforms/SimpleLoopUnswitch/2008-06-02-DomInfo.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -simple-loop-unswitch -instcombine -gvn -disable-output +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -instcombine -gvn -disable-output ; PR2372 target triple = "i386-pc-linux-gnu" Index: test/Transforms/SimpleLoopUnswitch/2010-11-18-LCSSA.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2010-11-18-LCSSA.ll +++ test/Transforms/SimpleLoopUnswitch/2010-11-18-LCSSA.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -simple-loop-unswitch +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa ; PR8622 @g_38 = external global i32, align 4 Index: test/Transforms/SimpleLoopUnswitch/2011-06-02-CritSwitch.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2011-06-02-CritSwitch.ll +++ test/Transforms/SimpleLoopUnswitch/2011-06-02-CritSwitch.ll @@ -1,4 +1,5 @@ ; RUN: opt -simple-loop-unswitch -disable-output < %s +; RUN: opt -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -disable-output < %s ; PR10031 define i32 @test(i32 %command) { Index: test/Transforms/SimpleLoopUnswitch/2011-09-26-EHCrash.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2011-09-26-EHCrash.ll +++ test/Transforms/SimpleLoopUnswitch/2011-09-26-EHCrash.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -sroa -simple-loop-unswitch -disable-output +; RUN: opt < %s -sroa -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -disable-output ; PR11016 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-macosx10.7.2" Index: test/Transforms/SimpleLoopUnswitch/2012-04-02-IndirectBr.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2012-04-02-IndirectBr.ll +++ test/Transforms/SimpleLoopUnswitch/2012-04-02-IndirectBr.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -S -simple-loop-unswitch -verify-loop-info -verify-dom-info | FileCheck %s +; RUN: opt < %s -S -simple-loop-unswitch -verify-loop-info -verify-dom-info -enable-mssa-loop-dependency=true -verify-memoryssa | FileCheck %s ; PR12343: -simple-loop-unswitch crash on indirect branch ; CHECK: %0 = icmp eq i64 undef, 0 Index: test/Transforms/SimpleLoopUnswitch/2012-05-20-Phi.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2012-05-20-Phi.ll +++ test/Transforms/SimpleLoopUnswitch/2012-05-20-Phi.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -simple-loop-unswitch -disable-output +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -disable-output ; PR12887 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" Index: test/Transforms/SimpleLoopUnswitch/2015-09-18-Addrspace.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/2015-09-18-Addrspace.ll +++ test/Transforms/SimpleLoopUnswitch/2015-09-18-Addrspace.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -simple-loop-unswitch -S | FileCheck %s +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -S | FileCheck %s ; In cases where two address spaces do not have the same size pointer, the ; input for the addrspacecast should not be used as a substitute for itself Index: test/Transforms/SimpleLoopUnswitch/LIV-loop-condtion.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/LIV-loop-condtion.ll +++ test/Transforms/SimpleLoopUnswitch/LIV-loop-condtion.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -simple-loop-unswitch -S 2>&1 | FileCheck %s +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -S 2>&1 | FileCheck %s ; This is to test trivial loop unswitch only happens when trivial condition ; itself is an LIV loop condition (not partial LIV which could occur in and/or). Index: test/Transforms/SimpleLoopUnswitch/basictest.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/basictest.ll +++ test/Transforms/SimpleLoopUnswitch/basictest.ll @@ -1,4 +1,5 @@ ; RUN: opt -passes='loop(unswitch),verify' -S < %s | FileCheck %s +; RUN: opt -enable-mssa-loop-dependency=true -verify-memoryssa -passes='loop(unswitch),verify' -S < %s | FileCheck %s define i32 @test(i32* %A, i1 %C) { entry: Index: test/Transforms/SimpleLoopUnswitch/cleanuppad.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/cleanuppad.ll +++ test/Transforms/SimpleLoopUnswitch/cleanuppad.ll @@ -1,4 +1,5 @@ ; RUN: opt -S -simple-loop-unswitch < %s | FileCheck %s +; RUN: opt -S -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa < %s | FileCheck %s target triple = "x86_64-pc-win32" define void @f(i32 %doit, i1 %x, i1 %y) personality i32 (...)* @__CxxFrameHandler3 { Index: test/Transforms/SimpleLoopUnswitch/copy-metadata.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/copy-metadata.ll +++ test/Transforms/SimpleLoopUnswitch/copy-metadata.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -simple-loop-unswitch -S | FileCheck %s +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -S | FileCheck %s ; This test checks if unswitched condition preserve make.implicit metadata. define i32 @test(i1 %cond) { Index: test/Transforms/SimpleLoopUnswitch/crash.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/crash.ll +++ test/Transforms/SimpleLoopUnswitch/crash.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -simple-loop-unswitch -disable-output +; RUN: opt < %s -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -disable-output define void @test1(i32* %S2) { entry: Index: test/Transforms/SimpleLoopUnswitch/exponential-behavior.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/exponential-behavior.ll +++ test/Transforms/SimpleLoopUnswitch/exponential-behavior.ll @@ -1,4 +1,5 @@ ; RUN: opt -simple-loop-unswitch -S < %s | FileCheck %s +; RUN: opt -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -S < %s | FileCheck %s define void @f(i32 %n, i32* %ptr) { ; CHECK-LABEL: @f( Index: test/Transforms/SimpleLoopUnswitch/guards.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/guards.ll +++ test/Transforms/SimpleLoopUnswitch/guards.ll @@ -1,5 +1,6 @@ ; RUN: opt -passes='loop(unswitch),verify' -enable-nontrivial-unswitch -simple-loop-unswitch-guards -S < %s | FileCheck %s ; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -simple-loop-unswitch-guards -S < %s | FileCheck %s +; RUN: opt -passes='loop(unswitch),verify' -enable-nontrivial-unswitch -simple-loop-unswitch-guards -enable-mssa-loop-dependency=true -verify-memoryssa -S < %s | FileCheck %s declare void @llvm.experimental.guard(i1, ...) Index: test/Transforms/SimpleLoopUnswitch/infinite-loop.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/infinite-loop.ll +++ test/Transforms/SimpleLoopUnswitch/infinite-loop.ll @@ -1,6 +1,7 @@ ; REQUIRES: asserts ; RUN: opt -simple-loop-unswitch -disable-output -stats -info-output-file - < %s | FileCheck --check-prefix=STATS %s ; RUN: opt -simple-loop-unswitch -S < %s | FileCheck %s +; RUN: opt -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -S < %s | FileCheck %s ; PR5373 ; Loop unswitching shouldn't trivially unswitch the true case of condition %a Index: test/Transforms/SimpleLoopUnswitch/msan.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/msan.ll +++ test/Transforms/SimpleLoopUnswitch/msan.ll @@ -1,4 +1,5 @@ ; RUN: opt -passes='loop(unswitch),verify' -S < %s | FileCheck %s +; RUN: opt -enable-mssa-loop-dependency=true -verify-memoryssa -passes='loop(unswitch),verify' -S < %s | FileCheck %s declare void @unknown() declare void @unknown2() Index: test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-cost.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-cost.ll +++ test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-cost.ll @@ -2,6 +2,7 @@ ; ; RUN: opt -passes='loop(unswitch),verify' -enable-nontrivial-unswitch -unswitch-threshold=5 -S < %s | FileCheck %s ; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -unswitch-threshold=5 -S < %s | FileCheck %s +; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -unswitch-threshold=5 -enable-mssa-loop-dependency=true -verify-memoryssa -S < %s | FileCheck %s declare void @a() declare void @b() Index: test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll +++ test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll @@ -1,5 +1,6 @@ ; RUN: opt -passes='loop(unswitch),verify' -enable-nontrivial-unswitch -S < %s | FileCheck %s ; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -S < %s | FileCheck %s +; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -S < %s | FileCheck %s declare i32 @a() declare i32 @b() Index: test/Transforms/SimpleLoopUnswitch/pr37888.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/pr37888.ll +++ test/Transforms/SimpleLoopUnswitch/pr37888.ll @@ -1,4 +1,5 @@ ; RUN: opt -simple-loop-unswitch -loop-deletion -S < %s | FileCheck %s +; RUN: opt -simple-loop-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -loop-deletion -S < %s | FileCheck %s ; ; Check that when we do unswitching where we re-enqueue the loop to be processed ; again, but manage to delete the loop before ever getting to iterate on it, it Index: test/Transforms/SimpleLoopUnswitch/preserve-analyses.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/preserve-analyses.ll +++ test/Transforms/SimpleLoopUnswitch/preserve-analyses.ll @@ -1,4 +1,5 @@ ; RUN: opt -simple-loop-unswitch -verify-loop-info -verify-dom-info -disable-output < %s +; RUN: opt -simple-loop-unswitch -verify-loop-info -verify-dom-info -enable-mssa-loop-dependency=true -verify-memoryssa -disable-output < %s ; Loop unswitch should be able to unswitch these loops and ; preserve LCSSA and LoopSimplify forms. Index: test/Transforms/SimpleLoopUnswitch/trivial-unswitch-iteration.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/trivial-unswitch-iteration.ll +++ test/Transforms/SimpleLoopUnswitch/trivial-unswitch-iteration.ll @@ -1,4 +1,5 @@ ; RUN: opt -passes='loop(loop-instsimplify,simplify-cfg,unswitch),verify' -S < %s | FileCheck %s +; RUN: opt -enable-mssa-loop-dependency=true -verify-memoryssa -passes='loop(loop-instsimplify,simplify-cfg,unswitch),verify' -S < %s | FileCheck %s declare void @some_func() noreturn Index: test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll +++ test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll @@ -1,4 +1,5 @@ ; RUN: opt -passes='loop(unswitch),verify' -S < %s | FileCheck %s +; RUN: opt -enable-mssa-loop-dependency=true -verify-memoryssa -passes='loop(unswitch),verify' -S < %s | FileCheck %s declare void @some_func() noreturn declare void @sink(i32) Index: test/Transforms/SimpleLoopUnswitch/update-scev.ll =================================================================== --- test/Transforms/SimpleLoopUnswitch/update-scev.ll +++ test/Transforms/SimpleLoopUnswitch/update-scev.ll @@ -1,4 +1,5 @@ ; RUN: opt -passes='print,loop(unswitch,loop-instsimplify),print' -enable-nontrivial-unswitch -S < %s 2>%t.scev | FileCheck %s +; RUN: opt -enable-mssa-loop-dependency=true -verify-memoryssa -passes='print,loop(unswitch,loop-instsimplify),print' -enable-nontrivial-unswitch -S < %s 2>%t.scev | FileCheck %s ; RUN: FileCheck %s --check-prefix=SCEV < %t.scev target triple = "x86_64-unknown-linux-gnu"