[LoopPredication] Preserve MemorySSA

Since LICM has now unconditionally moved to MemorySSA based form, all
passes that run in same LPM as LICM need to preserve MemorySSA (i.e. our
downstream pipeline).

Added loop-mssa to all tests and perform -verify-memoryssa within
LoopPredication itself.

Differential Revision: https://reviews.llvm.org/D108724
This commit is contained in:
Anna Thomas 2021-08-25 16:19:18 -04:00
parent 15acca5ccd
commit 55bdb14026
11 changed files with 38 additions and 17 deletions

View File

@ -183,6 +183,8 @@
#include "llvm/Analysis/GuardUtils.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/IR/Function.h"
@ -255,6 +257,7 @@ class LoopPredication {
ScalarEvolution *SE;
LoopInfo *LI;
BranchProbabilityInfo *BPI;
MemorySSAUpdater *MSSAU;
Loop *L;
const DataLayout *DL;
@ -308,10 +311,10 @@ class LoopPredication {
bool predicateLoopExits(Loop *L, SCEVExpander &Rewriter);
public:
LoopPredication(AliasAnalysis *AA, DominatorTree *DT,
ScalarEvolution *SE, LoopInfo *LI,
BranchProbabilityInfo *BPI)
: AA(AA), DT(DT), SE(SE), LI(LI), BPI(BPI) {};
LoopPredication(AliasAnalysis *AA, DominatorTree *DT, ScalarEvolution *SE,
LoopInfo *LI, BranchProbabilityInfo *BPI,
MemorySSAUpdater *MSSAU)
: AA(AA), DT(DT), SE(SE), LI(LI), BPI(BPI), MSSAU(MSSAU){};
bool runOnLoop(Loop *L);
};
@ -325,6 +328,7 @@ public:
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<BranchProbabilityInfoWrapperPass>();
getLoopAnalysisUsage(AU);
AU.addPreserved<MemorySSAWrapperPass>();
}
bool runOnLoop(Loop *L, LPPassManager &LPM) override {
@ -333,10 +337,14 @@ public:
auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
auto *MSSAWP = getAnalysisIfAvailable<MemorySSAWrapperPass>();
std::unique_ptr<MemorySSAUpdater> MSSAU;
if (MSSAWP)
MSSAU = std::make_unique<MemorySSAUpdater>(&MSSAWP->getMSSA());
BranchProbabilityInfo &BPI =
getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
auto *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
LoopPredication LP(AA, DT, SE, LI, &BPI);
LoopPredication LP(AA, DT, SE, LI, &BPI, MSSAU ? MSSAU.get() : nullptr);
return LP.runOnLoop(L);
}
};
@ -363,11 +371,18 @@ PreservedAnalyses LoopPredicationPass::run(Loop &L, LoopAnalysisManager &AM,
// pass. Function analyses need to be preserved across loop transformations
// but BPI is not preserved, hence a newly built one is needed.
BranchProbabilityInfo BPI(*F, AR.LI, &AR.TLI, &AR.DT, nullptr);
LoopPredication LP(&AR.AA, &AR.DT, &AR.SE, &AR.LI, &BPI);
std::unique_ptr<MemorySSAUpdater> MSSAU;
if (AR.MSSA)
MSSAU = std::make_unique<MemorySSAUpdater>(AR.MSSA);
LoopPredication LP(&AR.AA, &AR.DT, &AR.SE, &AR.LI, &BPI,
MSSAU ? MSSAU.get() : nullptr);
if (!LP.runOnLoop(&L))
return PreservedAnalyses::all();
return getLoopPassPreservedAnalyses();
auto PA = getLoopPassPreservedAnalyses();
if (AR.MSSA)
PA.preserve<MemorySSAAnalysis>();
return PA;
}
Optional<LoopICmp>
@ -809,7 +824,7 @@ bool LoopPredication::widenGuardConditions(IntrinsicInst *Guard,
Value *AllChecks = Builder.CreateAnd(Checks);
auto *OldCond = Guard->getOperand(0);
Guard->setOperand(0, AllChecks);
RecursivelyDeleteTriviallyDeadInstructions(OldCond);
RecursivelyDeleteTriviallyDeadInstructions(OldCond, nullptr /* TLI */, MSSAU);
LLVM_DEBUG(dbgs() << "Widened checks = " << NumWidened << "\n");
return true;
@ -835,7 +850,7 @@ bool LoopPredication::widenWidenableBranchGuardConditions(
Value *AllChecks = Builder.CreateAnd(Checks);
auto *OldCond = BI->getCondition();
BI->setCondition(AllChecks);
RecursivelyDeleteTriviallyDeadInstructions(OldCond);
RecursivelyDeleteTriviallyDeadInstructions(OldCond, nullptr /* TLI */, MSSAU);
assert(isGuardAsWidenableBranch(BI) &&
"Stopped being a guard after transform?");
@ -1242,5 +1257,8 @@ bool LoopPredication::runOnLoop(Loop *Loop) {
for (auto *Guard : GuardsAsWidenableBranches)
Changed |= widenWidenableBranchGuardConditions(Guard, Expander);
Changed |= predicateLoopExits(L, Expander);
if (MSSAU && VerifyMemorySSA)
MSSAU->getMemorySSA()->verifyMemorySSA();
return Changed;
}

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -loop-predication < %s 2>&1 | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,loop(loop-predication)' < %s 2>&1 | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)' -verify-memoryssa < %s 2>&1 | FileCheck %s
declare void @llvm.experimental.guard(i1, ...)

View File

@ -1,7 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -loop-predication -loop-predication-predicate-widenable-branches-to-deopt=true < %s 2>&1 | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,loop(loop-predication)' -loop-predication-predicate-widenable-branches-to-deopt=true < %s 2>&1 | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,require<branch-prob>,loop(loop-predication)' -loop-predication-predicate-widenable-branches-to-deopt=true < %s 2>&1 | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)' -verify-memoryssa -loop-predication-predicate-widenable-branches-to-deopt=true < %s 2>&1 | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,require<branch-prob>,loop-mssa(loop-predication)' -verify-memoryssa -loop-predication-predicate-widenable-branches-to-deopt=true < %s 2>&1 | FileCheck %s
declare void @llvm.experimental.guard(i1, ...)

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -basic-aa -loop-predication < %s 2>&1 | FileCheck %s
; RUN: opt -S -aa-pipeline=basic-aa -passes='require<aa>,require<scalar-evolution>,loop(loop-predication)' < %s 2>&1 | FileCheck %s
; RUN: opt -S -aa-pipeline=basic-aa -passes='require<aa>,require<scalar-evolution>,loop-mssa(loop-predication)' -verify-memoryssa < %s 2>&1 | FileCheck %s
declare void @llvm.experimental.guard(i1, ...)

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -loop-predication < %s 2>&1 | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,loop(loop-predication)' < %s 2>&1 | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)' -verify-memoryssa < %s 2>&1 | FileCheck %s
declare void @llvm.experimental.guard(i1, ...)

View File

@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -loop-predication -S | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)' -verify-memoryssa < %s 2>&1 | FileCheck %s
declare void @prevent_merging()

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -loop-predication -loop-predication-skip-profitability-checks=false < %s 2>&1 | FileCheck %s
; RUN: opt -S -loop-predication-skip-profitability-checks=false -passes='require<scalar-evolution>,require<branch-prob>,loop(loop-predication)' < %s 2>&1 | FileCheck %s
; RUN: opt -S -loop-predication-skip-profitability-checks=false -passes='require<scalar-evolution>,require<branch-prob>,loop-mssa(loop-predication)' -verify-memoryssa < %s 2>&1 | FileCheck %s
; latch block exits to a speculation block. BPI already knows (without prof
; data) that deopt is very rarely

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -loop-predication -loop-predication-enable-count-down-loop=true < %s 2>&1 | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,loop(loop-predication)' -loop-predication-enable-count-down-loop=true < %s 2>&1 | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)' -loop-predication-enable-count-down-loop=true < %s 2>&1 | FileCheck %s
declare void @llvm.experimental.guard(i1, ...)

View File

@ -1,4 +1,5 @@
; RUN: opt < %s -loop-predication -S | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)' -verify-memoryssa < %s 2>&1 | FileCheck %s
;; This is a simplified copy of @unswitch_exit_form test that should trigger loop-predication
;; activity and properly bail out when discovering that widenable check does not lead to deopt.

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -loop-predication < %s 2>&1 | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,loop(loop-predication)' < %s 2>&1 | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)' -verify-memoryssa < %s 2>&1 | FileCheck %s
declare void @llvm.experimental.guard(i1, ...)

View File

@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -loop-predication -loop-predication-enable-iv-truncation=true < %s 2>&1 | FileCheck %s
; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)' -verify-memoryssa < %s 2>&1 | FileCheck %s
declare void @llvm.experimental.guard(i1, ...)
declare i32 @length(i8*)