[LoopDeletion] Teach LoopDeletion to preserve MemorySSA if available.

If MemorySSA analysis is analysis, LoopDeletion now preserves it.
This commit is contained in:
Alina Sbirlea 2020-01-21 16:56:39 -08:00
parent eec36909c1
commit efb130fc93
3 changed files with 49 additions and 17 deletions

View File

@ -41,6 +41,7 @@ class DataLayout;
class Loop;
class LoopInfo;
class MemoryAccess;
class MemorySSA;
class MemorySSAUpdater;
class OptimizationRemarkEmitter;
class PredicatedScalarEvolution;
@ -144,12 +145,12 @@ bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
/// - The loop needs to have a Preheader
/// - A unique dedicated exit block must exist
///
/// This also updates the relevant analysis information in \p DT, \p SE, and \p
/// LI if pointers to those are provided.
/// This also updates the relevant analysis information in \p DT, \p SE, \p LI
/// and \p MSSA if pointers to those are provided.
/// It also updates the loop PM if an updater struct is provided.
void deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
LoopInfo *LI);
LoopInfo *LI, MemorySSA *MSSA = nullptr);
/// Try to promote memory values to scalars by sinking stores out of
/// the loop and moving loads to before the loop. We do this by looping over

View File

@ -18,6 +18,7 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/InitializePasses.h"
@ -134,7 +135,8 @@ static bool isLoopNeverExecuted(Loop *L) {
/// is unable to delete it due to hoisting trivially loop invariant
/// instructions out of the loop.
static LoopDeletionResult deleteLoopIfDead(Loop *L, DominatorTree &DT,
ScalarEvolution &SE, LoopInfo &LI) {
ScalarEvolution &SE, LoopInfo &LI,
MemorySSA *MSSA) {
assert(L->isLCSSAForm(DT) && "Expected LCSSA!");
// We can only remove the loop if there is a preheader that we can branch from
@ -164,7 +166,7 @@ static LoopDeletionResult deleteLoopIfDead(Loop *L, DominatorTree &DT,
std::fill(P.incoming_values().begin(), P.incoming_values().end(),
UndefValue::get(P.getType()));
}
deleteDeadLoop(L, &DT, &SE, &LI);
deleteDeadLoop(L, &DT, &SE, &LI, MSSA);
++NumDeleted;
return LoopDeletionResult::Deleted;
}
@ -200,7 +202,7 @@ static LoopDeletionResult deleteLoopIfDead(Loop *L, DominatorTree &DT,
}
LLVM_DEBUG(dbgs() << "Loop is invariant, delete it!");
deleteDeadLoop(L, &DT, &SE, &LI);
deleteDeadLoop(L, &DT, &SE, &LI, MSSA);
++NumDeleted;
return LoopDeletionResult::Deleted;
@ -213,14 +215,17 @@ PreservedAnalyses LoopDeletionPass::run(Loop &L, LoopAnalysisManager &AM,
LLVM_DEBUG(dbgs() << "Analyzing Loop for deletion: ");
LLVM_DEBUG(L.dump());
std::string LoopName = L.getName();
auto Result = deleteLoopIfDead(&L, AR.DT, AR.SE, AR.LI);
auto Result = deleteLoopIfDead(&L, AR.DT, AR.SE, AR.LI, AR.MSSA);
if (Result == LoopDeletionResult::Unmodified)
return PreservedAnalyses::all();
if (Result == LoopDeletionResult::Deleted)
Updater.markLoopAsDeleted(L, LoopName);
return getLoopPassPreservedAnalyses();
auto PA = getLoopPassPreservedAnalyses();
if (AR.MSSA)
PA.preserve<MemorySSAAnalysis>();
return PA;
}
namespace {
@ -235,6 +240,7 @@ public:
bool runOnLoop(Loop *L, LPPassManager &) override;
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addPreserved<MemorySSAWrapperPass>();
getLoopAnalysisUsage(AU);
}
};
@ -255,11 +261,15 @@ bool LoopDeletionLegacyPass::runOnLoop(Loop *L, LPPassManager &LPM) {
DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
ScalarEvolution &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
auto *MSSAAnalysis = getAnalysisIfAvailable<MemorySSAWrapperPass>();
MemorySSA *MSSA = nullptr;
if (MSSAAnalysis)
MSSA = &MSSAAnalysis->getMSSA();
LLVM_DEBUG(dbgs() << "Analyzing Loop for deletion: ");
LLVM_DEBUG(L->dump());
LoopDeletionResult Result = deleteLoopIfDead(L, DT, SE, LI);
LoopDeletionResult Result = deleteLoopIfDead(L, DT, SE, LI, MSSA);
if (Result == LoopDeletionResult::Deleted)
LPM.markLoopAsDeleted(*L);

View File

@ -506,13 +506,16 @@ llvm::collectChildrenInLoop(DomTreeNode *N, const Loop *CurLoop) {
return Worklist;
}
void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT = nullptr,
ScalarEvolution *SE = nullptr,
LoopInfo *LI = nullptr) {
void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
LoopInfo *LI, MemorySSA *MSSA) {
assert((!DT || L->isLCSSAForm(*DT)) && "Expected LCSSA!");
auto *Preheader = L->getLoopPreheader();
assert(Preheader && "Preheader should exist!");
std::unique_ptr<MemorySSAUpdater> MSSAU;
if (MSSA)
MSSAU = std::make_unique<MemorySSAUpdater>(MSSA);
// Now that we know the removal is safe, remove the loop by changing the
// branch from the preheader to go to the single exit block.
//
@ -585,18 +588,33 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT = nullptr,
"Should have exactly one value and that's from the preheader!");
}
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
if (DT) {
DTU.applyUpdates({{DominatorTree::Insert, Preheader, ExitBlock}});
if (MSSA) {
MSSAU->applyUpdates({{DominatorTree::Insert, Preheader, ExitBlock}}, *DT);
if (VerifyMemorySSA)
MSSA->verifyMemorySSA();
}
}
// Disconnect the loop body by branching directly to its exit.
Builder.SetInsertPoint(Preheader->getTerminator());
Builder.CreateBr(ExitBlock);
// Remove the old branch.
Preheader->getTerminator()->eraseFromParent();
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
if (DT) {
// Update the dominator tree by informing it about the new edge from the
// preheader to the exit and the removed edge.
DTU.applyUpdates({{DominatorTree::Insert, Preheader, ExitBlock},
{DominatorTree::Delete, Preheader, L->getHeader()}});
DTU.applyUpdates({{DominatorTree::Delete, Preheader, L->getHeader()}});
if (MSSA) {
MSSAU->applyUpdates({{DominatorTree::Delete, Preheader, L->getHeader()}},
*DT);
if (VerifyMemorySSA)
MSSA->verifyMemorySSA();
SmallSetVector<BasicBlock *, 8> DeadBlockSet(L->block_begin(),
L->block_end());
MSSAU->removeBlocks(DeadBlockSet);
}
}
// Use a map to unique and a vector to guarantee deterministic ordering.
@ -657,6 +675,9 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT = nullptr,
for (auto *Block : L->blocks())
Block->dropAllReferences();
if (MSSA && VerifyMemorySSA)
MSSA->verifyMemorySSA();
if (LI) {
// Erase the instructions and the blocks without having to worry
// about ordering because we already dropped the references.