diff --git a/llvm/lib/Transforms/Scalar/GuardWidening.cpp b/llvm/lib/Transforms/Scalar/GuardWidening.cpp --- a/llvm/lib/Transforms/Scalar/GuardWidening.cpp +++ b/llvm/lib/Transforms/Scalar/GuardWidening.cpp @@ -46,6 +46,7 @@ #include "llvm/Analysis/GuardUtils.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/MemorySSAUpdater.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/ConstantRange.h" @@ -105,8 +106,10 @@ } // Eliminates the guard instruction properly. -static void eliminateGuard(Instruction *GuardInst) { +static void eliminateGuard(Instruction *GuardInst, MemorySSAUpdater *MSSAU) { GuardInst->eraseFromParent(); + if (MSSAU) + MSSAU->removeMemoryAccess(GuardInst); ++GuardsEliminated; } @@ -114,6 +117,7 @@ DominatorTree &DT; PostDominatorTree *PDT; LoopInfo &LI; + MemorySSAUpdater *MSSAU; /// Together, these describe the region of interest. This might be all of /// the blocks within a function, or only a given loop's blocks and preheader. @@ -269,12 +273,12 @@ } public: - explicit GuardWideningImpl(DominatorTree &DT, PostDominatorTree *PDT, - LoopInfo &LI, DomTreeNode *Root, + LoopInfo &LI, MemorySSAUpdater *MSSAU, + DomTreeNode *Root, std::function BlockFilter) - : DT(DT), PDT(PDT), LI(LI), Root(Root), BlockFilter(BlockFilter) - {} + : DT(DT), PDT(PDT), LI(LI), MSSAU(MSSAU), Root(Root), + BlockFilter(BlockFilter) {} /// The entry point for this pass. bool run(); @@ -313,7 +317,7 @@ if (!WidenedGuards.count(I)) { assert(isa(getCondition(I)) && "Should be!"); if (isSupportedGuardInstruction(I)) - eliminateGuard(I); + eliminateGuard(I, MSSAU); else { assert(isa(I) && "Eliminated something other than guard or branch?"); @@ -766,12 +770,18 @@ auto &DT = AM.getResult(F); auto &LI = AM.getResult(F); auto &PDT = AM.getResult(F); - if (!GuardWideningImpl(DT, &PDT, LI, DT.getRootNode(), - [](BasicBlock*) { return true; } ).run()) + auto *MSSAA = AM.getCachedResult(F); + std::unique_ptr MSSAU; + if (MSSAA) + MSSAU = std::make_unique(&MSSAA->getMSSA()); + if (!GuardWideningImpl(DT, &PDT, LI, MSSAU ? MSSAU.get() : nullptr, + DT.getRootNode(), [](BasicBlock *) { return true; }) + .run()) return PreservedAnalyses::all(); PreservedAnalyses PA; PA.preserveSet(); + PA.preserve(); return PA; } @@ -784,11 +794,17 @@ auto BlockFilter = [&](BasicBlock *BB) { return BB == RootBB || L.contains(BB); }; - if (!GuardWideningImpl(AR.DT, nullptr, AR.LI, AR.DT.getNode(RootBB), - BlockFilter).run()) + std::unique_ptr MSSAU; + if (AR.MSSA) + MSSAU = std::make_unique(AR.MSSA); + if (!GuardWideningImpl(AR.DT, nullptr, AR.LI, MSSAU ? MSSAU.get() : nullptr, + AR.DT.getNode(RootBB), BlockFilter).run()) return PreservedAnalyses::all(); - return getLoopPassPreservedAnalyses(); + auto PA = getLoopPassPreservedAnalyses(); + if (AR.MSSA) + PA.preserve(); + return PA; } namespace { @@ -805,8 +821,14 @@ auto &DT = getAnalysis().getDomTree(); auto &LI = getAnalysis().getLoopInfo(); auto &PDT = getAnalysis().getPostDomTree(); - return GuardWideningImpl(DT, &PDT, LI, DT.getRootNode(), - [](BasicBlock*) { return true; } ).run(); + auto *MSSAWP = getAnalysisIfAvailable(); + std::unique_ptr MSSAU; + if (MSSAWP) + MSSAU = std::make_unique(&MSSAWP->getMSSA()); + return GuardWideningImpl(DT, &PDT, LI, MSSAU ? MSSAU.get() : nullptr, + DT.getRootNode(), + [](BasicBlock *) { return true; }) + .run(); } void getAnalysisUsage(AnalysisUsage &AU) const override { @@ -814,6 +836,7 @@ AU.addRequired(); AU.addRequired(); AU.addRequired(); + AU.addPreserved(); } }; @@ -833,13 +856,18 @@ auto &LI = getAnalysis().getLoopInfo(); auto *PDTWP = getAnalysisIfAvailable(); auto *PDT = PDTWP ? &PDTWP->getPostDomTree() : nullptr; + auto *MSSAWP = getAnalysisIfAvailable(); + std::unique_ptr MSSAU; + if (MSSAWP) + MSSAU = std::make_unique(&MSSAWP->getMSSA()); + BasicBlock *RootBB = L->getLoopPredecessor(); if (!RootBB) RootBB = L->getHeader(); auto BlockFilter = [&](BasicBlock *BB) { return BB == RootBB || L->contains(BB); }; - return GuardWideningImpl(DT, PDT, LI, + return GuardWideningImpl(DT, PDT, LI, MSSAU ? MSSAU.get() : nullptr, DT.getNode(RootBB), BlockFilter).run(); } @@ -847,6 +875,7 @@ AU.setPreservesCFG(); getLoopAnalysisUsage(AU); AU.addPreserved(); + AU.addPreserved(); } }; } diff --git a/llvm/test/Transforms/GuardWidening/basic-loop.ll b/llvm/test/Transforms/GuardWidening/basic-loop.ll --- a/llvm/test/Transforms/GuardWidening/basic-loop.ll +++ b/llvm/test/Transforms/GuardWidening/basic-loop.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -loop-guard-widening -enable-new-pm=0 < %s | FileCheck %s -; RUN: opt -S -passes="loop(guard-widening)" < %s | FileCheck %s +; RUN: opt -S -loop-guard-widening -verify-memoryssa -enable-new-pm=0 < %s | FileCheck %s +; RUN: opt -S -passes="loop-mssa(guard-widening)" -verify-memoryssa < %s | FileCheck %s declare void @llvm.experimental.guard(i1,...) diff --git a/llvm/test/Transforms/GuardWidening/loop-schedule.ll b/llvm/test/Transforms/GuardWidening/loop-schedule.ll --- a/llvm/test/Transforms/GuardWidening/loop-schedule.ll +++ b/llvm/test/Transforms/GuardWidening/loop-schedule.ll @@ -1,13 +1,13 @@ -; RUN: opt -S -licm -loop-guard-widening -licm -debug-pass=Structure -enable-new-pm=0 < %s 2>&1 | FileCheck %s --check-prefixes=LPM,CHECK -; RUN: opt -S -passes='licm,guard-widening,licm' -debug-pass-manager < %s 2>&1 | FileCheck %s --check-prefixes=NPM,CHECK +; RUN: opt -S -licm -loop-guard-widening -licm -verify-memoryssa -debug-pass=Structure -enable-new-pm=0 < %s 2>&1 | FileCheck %s --check-prefixes=LPM,CHECK +; RUN: opt -S -passes='licm,guard-widening,licm' -verify-memoryssa -debug-pass-manager < %s 2>&1 | FileCheck %s --check-prefixes=NPM,CHECK ; Main point of this test is to check the scheduling -- there should be ; no analysis passes needed between LICM and LoopGuardWidening ; LPM: Loop Pass Manager ; LPM: Loop Invariant Code Motion -; LPM: Widen guards (within a single loop, as a loop pass) -; LPM: Loop Invariant Code Motion +; LPM-NEXT: Widen guards (within a single loop, as a loop pass) +; LPM-NEXT: Loop Invariant Code Motion ; NPM: LICMPass ; NPM-NEXT: GuardWideningPass