408 changes: 365 additions & 43 deletions llvm/include/llvm/Analysis/LoopPassManager.h

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion llvm/include/llvm/Transforms/Scalar/IndVarSimplify.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ namespace llvm {

class IndVarSimplifyPass : public PassInfoMixin<IndVarSimplifyPass> {
public:
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U);
};
}

Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/Transforms/Scalar/LICM.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ namespace llvm {
/// Performs Loop Invariant Code Motion Pass.
class LICMPass : public PassInfoMixin<LICMPass> {
public:
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U);
};
} // end namespace llvm

Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/Transforms/Scalar/LoopDeletion.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ namespace llvm {
class LoopDeletionPass : public PassInfoMixin<LoopDeletionPass> {
public:
LoopDeletionPass() {}
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U);
bool runImpl(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
LoopInfo &loopInfo);

Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ namespace llvm {
/// Performs Loop Idiom Recognize Pass.
class LoopIdiomRecognizePass : public PassInfoMixin<LoopIdiomRecognizePass> {
public:
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U);
};
} // end namespace llvm

Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/Transforms/Scalar/LoopInstSimplify.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ namespace llvm {
/// Performs Loop Inst Simplify Pass.
class LoopInstSimplifyPass : public PassInfoMixin<LoopInstSimplifyPass> {
public:
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U);
};
} // end namespace llvm

Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/Transforms/Scalar/LoopRotation.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ namespace llvm {
class LoopRotatePass : public PassInfoMixin<LoopRotatePass> {
public:
LoopRotatePass(bool EnableHeaderDuplication = true);
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U);

private:
const bool EnableHeaderDuplication;
Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ namespace llvm {
/// Performs basic CFG simplifications to assist other loop passes.
class LoopSimplifyCFGPass : public PassInfoMixin<LoopSimplifyCFGPass> {
public:
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U);
};
} // end namespace llvm

Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/Transforms/Scalar/LoopStrengthReduce.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ namespace llvm {
/// Performs Loop Strength Reduce Pass.
class LoopStrengthReducePass : public PassInfoMixin<LoopStrengthReducePass> {
public:
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U);
};
} // end namespace llvm

Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/Transforms/Scalar/LoopUnrollPass.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ struct LoopUnrollPass : public PassInfoMixin<LoopUnrollPass> {
Optional<bool> ProvidedRuntime;
Optional<bool> ProvidedUpperBound;

PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM);
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U);
};
} // end namespace llvm

Expand Down
18 changes: 7 additions & 11 deletions llvm/lib/Analysis/IVUsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,15 @@ using namespace llvm;

AnalysisKey IVUsersAnalysis::Key;

IVUsers IVUsersAnalysis::run(Loop &L, LoopAnalysisManager &AM) {
const auto &FAM =
AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
Function *F = L.getHeader()->getParent();

return IVUsers(&L, FAM.getCachedResult<AssumptionAnalysis>(*F),
FAM.getCachedResult<LoopAnalysis>(*F),
FAM.getCachedResult<DominatorTreeAnalysis>(*F),
FAM.getCachedResult<ScalarEvolutionAnalysis>(*F));
IVUsers IVUsersAnalysis::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR) {
return IVUsers(&L, &AR.AC, &AR.LI, &AR.DT, &AR.SE);
}

PreservedAnalyses IVUsersPrinterPass::run(Loop &L, LoopAnalysisManager &AM) {
AM.getResult<IVUsersAnalysis>(L).print(OS);
PreservedAnalyses IVUsersPrinterPass::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR,
LPMUpdater &U) {
AM.getResult<IVUsersAnalysis>(L, AR).print(OS);
return PreservedAnalyses::all();
}

Expand Down
29 changes: 7 additions & 22 deletions llvm/lib/Analysis/LoopAccessAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2120,31 +2120,16 @@ INITIALIZE_PASS_END(LoopAccessLegacyAnalysis, LAA_NAME, laa_name, false, true)

AnalysisKey LoopAccessAnalysis::Key;

LoopAccessInfo LoopAccessAnalysis::run(Loop &L, LoopAnalysisManager &AM) {
const FunctionAnalysisManager &FAM =
AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
Function &F = *L.getHeader()->getParent();
auto *SE = FAM.getCachedResult<ScalarEvolutionAnalysis>(F);
auto *TLI = FAM.getCachedResult<TargetLibraryAnalysis>(F);
auto *AA = FAM.getCachedResult<AAManager>(F);
auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(F);
auto *LI = FAM.getCachedResult<LoopAnalysis>(F);
if (!SE)
report_fatal_error(
"ScalarEvolution must have been cached at a higher level");
if (!AA)
report_fatal_error("AliasAnalysis must have been cached at a higher level");
if (!DT)
report_fatal_error("DominatorTree must have been cached at a higher level");
if (!LI)
report_fatal_error("LoopInfo must have been cached at a higher level");
return LoopAccessInfo(&L, SE, TLI, AA, DT, LI);
LoopAccessInfo LoopAccessAnalysis::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR) {
return LoopAccessInfo(&L, &AR.SE, &AR.TLI, &AR.AA, &AR.DT, &AR.LI);
}

PreservedAnalyses LoopAccessInfoPrinterPass::run(Loop &L,
LoopAnalysisManager &AM) {
PreservedAnalyses
LoopAccessInfoPrinterPass::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &) {
Function &F = *L.getHeader()->getParent();
auto &LAI = AM.getResult<LoopAccessAnalysis>(L);
auto &LAI = AM.getResult<LoopAccessAnalysis>(L, AR);
OS << "Loop access info in function '" << F.getName() << "':\n";
OS.indent(2) << L.getHeader()->getName() << ":\n";
LAI.print(OS, 4);
Expand Down
7 changes: 1 addition & 6 deletions llvm/lib/Analysis/LoopInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -689,18 +689,13 @@ PreservedAnalyses LoopPrinterPass::run(Function &F,
return PreservedAnalyses::all();
}

PrintLoopPass::PrintLoopPass() : OS(dbgs()) {}
PrintLoopPass::PrintLoopPass(raw_ostream &OS, const std::string &Banner)
: OS(OS), Banner(Banner) {}

PreservedAnalyses PrintLoopPass::run(Loop &L, AnalysisManager<Loop> &) {
void llvm::printLoop(Loop &L, raw_ostream &OS, const std::string &Banner) {
OS << Banner;
for (auto *Block : L.blocks())
if (Block)
Block->print(OS);
else
OS << "Printing <null> block";
return PreservedAnalyses::all();
}

//===----------------------------------------------------------------------===//
Expand Down
10 changes: 5 additions & 5 deletions llvm/lib/Analysis/LoopPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ namespace {
/// PrintLoopPass - Print a Function corresponding to a Loop.
///
class PrintLoopPassWrapper : public LoopPass {
PrintLoopPass P;
raw_ostream &OS;
std::string Banner;

public:
static char ID;
PrintLoopPassWrapper() : LoopPass(ID) {}
PrintLoopPassWrapper() : LoopPass(ID), OS(dbgs()) {}
PrintLoopPassWrapper(raw_ostream &OS, const std::string &Banner)
: LoopPass(ID), P(OS, Banner) {}
: LoopPass(ID), OS(OS), Banner(Banner) {}

void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
Expand All @@ -49,8 +50,7 @@ class PrintLoopPassWrapper : public LoopPass {
[](BasicBlock *BB) { return BB; });
if (BBI != L->blocks().end() &&
isFunctionInPrintList((*BBI)->getParent()->getName())) {
LoopAnalysisManager DummyLAM;
P.run(*L, DummyLAM);
printLoop(*L, OS, Banner);
}
return false;
}
Expand Down
188 changes: 178 additions & 10 deletions llvm/lib/Analysis/LoopPassManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,191 @@ using namespace llvm;
// Explicit template instantiations and specialization defininitions for core
// template typedefs.
namespace llvm {
template class PassManager<Loop>;
template class AnalysisManager<Loop>;
template class AllAnalysesOn<Loop>;
template class AnalysisManager<Loop, LoopStandardAnalysisResults &>;
template class PassManager<Loop, LoopAnalysisManager,
LoopStandardAnalysisResults &, LPMUpdater &>;
template class InnerAnalysisManagerProxy<LoopAnalysisManager, Function>;
template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>;
template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop,
LoopStandardAnalysisResults &>;

/// Explicitly specialize the pass manager's run method to handle loop nest
/// structure updates.
template <>
PreservedAnalyses
PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
LPMUpdater &>::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U) {
PreservedAnalyses PA = PreservedAnalyses::all();

if (DebugLogging)
dbgs() << "Starting Loop pass manager run.\n";

for (auto &Pass : Passes) {
if (DebugLogging)
dbgs() << "Running pass: " << Pass->name() << " on " << L;

PreservedAnalyses PassPA = Pass->run(L, AM, AR, U);

// If the loop was deleted, abort the run and return to the outer walk.
if (U.skipCurrentLoop()) {
PA.intersect(std::move(PassPA));
break;
}

// Update the analysis manager as each pass runs and potentially
// invalidates analyses.
AM.invalidate(L, PassPA);

// Finally, we intersect the final preserved analyses to compute the
// aggregate preserved set for this pass manager.
PA.intersect(std::move(PassPA));

// FIXME: Historically, the pass managers all called the LLVM context's
// yield function here. We don't have a generic way to acquire the
// context and it isn't yet clear what the right pattern is for yielding
// in the new pass manager so it is currently omitted.
// ...getContext().yield();
}

// Invalidation for the current loop should be handled above, and other loop
// analysis results shouldn't be impacted by runs over this loop. Therefore,
// the remaining analysis results in the AnalysisManager are preserved. We
// mark this with a set so that we don't need to inspect each one
// individually.
// FIXME: This isn't correct! This loop and all nested loops' analyses should
// be preserved, but unrolling should invalidate the parent loop's analyses.
PA.preserveSet<AllAnalysesOn<Loop>>();

if (DebugLogging)
dbgs() << "Finished Loop pass manager run.\n";

return PA;
}

bool LoopAnalysisManagerFunctionProxy::Result::invalidate(
Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &Inv) {
// If this proxy isn't marked as preserved, the set of Function objects in
// the module may have changed. We therefore can't call
// InnerAM->invalidate(), because any pointers to Functions it has may be
// stale.
// First compute the sequence of IR units covered by this proxy. We will want
// to visit this in postorder, but because this is a tree structure we can do
// this by building a preorder sequence and walking it in reverse.
SmallVector<Loop *, 4> PreOrderLoops, PreOrderWorklist;
// Note that we want to walk the roots in reverse order because we will end
// up reversing the preorder sequence. However, it happens that the loop nest
// roots are in reverse order within the LoopInfo object. So we just walk
// forward here.
// FIXME: If we change the order of LoopInfo we will want to add a reverse
// here.
for (Loop *RootL : *LI) {
assert(PreOrderWorklist.empty() &&
"Must start with an empty preorder walk worklist.");
PreOrderWorklist.push_back(RootL);
do {
Loop *L = PreOrderWorklist.pop_back_val();
PreOrderWorklist.append(L->begin(), L->end());
PreOrderLoops.push_back(L);
} while (!PreOrderWorklist.empty());
}

// If this proxy or the loop info is going to be invalidated, we also need
// to clear all the keys coming from that analysis. We also completely blow
// away the loop analyses if any of the standard analyses provided by the
// loop pass manager go away so that loop analyses can freely use these
// without worrying about declaring dependencies on them etc.
// FIXME: It isn't clear if this is the right tradeoff. We could instead make
// loop analyses declare any dependencies on these and use the more general
// invalidation logic below to act on that.
auto PAC = PA.getChecker<LoopAnalysisManagerFunctionProxy>();
if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Loop>>())
InnerAM->clear();
if (!(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>()) ||
Inv.invalidate<AAManager>(F, PA) ||
Inv.invalidate<AssumptionAnalysis>(F, PA) ||
Inv.invalidate<DominatorTreeAnalysis>(F, PA) ||
Inv.invalidate<LoopAnalysis>(F, PA) ||
Inv.invalidate<ScalarEvolutionAnalysis>(F, PA)) {
// Note that the LoopInfo may be stale at this point, however the loop
// objects themselves remain the only viable keys that could be in the
// analysis manager's cache. So we just walk the keys and forcibly clear
// those results. Note that the order doesn't matter here as this will just
// directly destroy the results without calling methods on them.
for (Loop *L : PreOrderLoops)
InnerAM->clear(*L);

// We also need to null out the inner AM so that when the object gets
// destroyed as invalid we don't try to clear the inner AM again. At that
// point we won't be able to reliably walk the loops for this function and
// only clear results associated with those loops the way we do here.
// FIXME: Making InnerAM null at this point isn't very nice. Most analyses
// try to remain valid during invalidation. Maybe we should add an
// `IsClean` flag?
InnerAM = nullptr;

// Now return true to indicate this *is* invalid and a fresh proxy result
// needs to be built. This is especially important given the null InnerAM.
return true;
}

// Directly check if the relevant set is preserved so we can short circuit
// invalidating loops.
bool AreLoopAnalysesPreserved =
PA.allAnalysesInSetPreserved<AllAnalysesOn<Loop>>();

// Since we have a valid LoopInfo we can actually leave the cached results in
// the analysis manager associated with the Loop keys, but we need to
// propagate any necessary invalidation logic into them. We'd like to
// invalidate things in roughly the same order as they were put into the
// cache and so we walk the preorder list in reverse to form a valid
// postorder.
for (Loop *L : reverse(PreOrderLoops)) {
Optional<PreservedAnalyses> InnerPA;

// Check to see whether the preserved set needs to be adjusted based on
// function-level analysis invalidation triggering deferred invalidation
// for this loop.
if (auto *OuterProxy =
InnerAM->getCachedResult<FunctionAnalysisManagerLoopProxy>(*L))
for (const auto &OuterInvalidationPair :
OuterProxy->getOuterInvalidations()) {
AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first;
const auto &InnerAnalysisIDs = OuterInvalidationPair.second;
if (Inv.invalidate(OuterAnalysisID, F, PA)) {
if (!InnerPA)
InnerPA = PA;
for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)
InnerPA->abandon(InnerAnalysisID);
}
}

// Check if we needed a custom PA set. If so we'll need to run the inner
// invalidation.
if (InnerPA) {
InnerAM->invalidate(*L, *InnerPA);
continue;
}

// FIXME: Proper suppor for invalidation isn't yet implemented for the LPM.
// Otherwise we only need to do invalidation if the original PA set didn't
// preserve all Loop analyses.
if (!AreLoopAnalysesPreserved)
InnerAM->invalidate(*L, PA);
}

// Return false to indicate that this result is still a valid proxy.
return false;
}

template <>
LoopAnalysisManagerFunctionProxy::Result
LoopAnalysisManagerFunctionProxy::run(Function &F,
FunctionAnalysisManager &AM) {
return Result(*InnerAM, AM.getResult<LoopAnalysis>(F));
}
}

PreservedAnalyses llvm::getLoopPassPreservedAnalyses() {
PreservedAnalyses PA;
PA.preserve<AssumptionAnalysis>();
PA.preserve<DominatorTreeAnalysis>();
PA.preserve<LoopAnalysis>();
PA.preserve<LoopAnalysisManagerFunctionProxy>();
PA.preserve<ScalarEvolutionAnalysis>();
// TODO: What we really want to do here is preserve an AA category, but that
// concept doesn't exist yet.
Expand All @@ -57,3 +214,14 @@ PreservedAnalyses llvm::getLoopPassPreservedAnalyses() {
PA.preserve<SCEVAA>();
return PA;
}

PrintLoopPass::PrintLoopPass() : OS(dbgs()) {}
PrintLoopPass::PrintLoopPass(raw_ostream &OS, const std::string &Banner)
: OS(OS), Banner(Banner) {}

PreservedAnalyses PrintLoopPass::run(Loop &L, LoopAnalysisManager &,
LoopStandardAnalysisResults &,
LPMUpdater &) {
printLoop(L, OS, Banner);
return PreservedAnalyses::all();
}
12 changes: 9 additions & 3 deletions llvm/lib/Passes/PassBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "llvm/Analysis/LazyValueInfo.h"
#include "llvm/Analysis/LoopAccessAnalysis.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPassManager.h"
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
#include "llvm/Analysis/ModuleSummaryAnalysis.h"
#include "llvm/Analysis/OptimizationDiagnosticInfo.h"
Expand Down Expand Up @@ -220,7 +221,8 @@ class NoOpFunctionAnalysis : public AnalysisInfoMixin<NoOpFunctionAnalysis> {

/// \brief No-op loop pass which does nothing.
struct NoOpLoopPass {
PreservedAnalyses run(Loop &L, LoopAnalysisManager &) {
PreservedAnalyses run(Loop &L, LoopAnalysisManager &,
LoopStandardAnalysisResults &, LPMUpdater &) {
return PreservedAnalyses::all();
}
static StringRef name() { return "NoOpLoopPass"; }
Expand All @@ -233,7 +235,9 @@ class NoOpLoopAnalysis : public AnalysisInfoMixin<NoOpLoopAnalysis> {

public:
struct Result {};
Result run(Loop &, LoopAnalysisManager &) { return Result(); }
Result run(Loop &, LoopAnalysisManager &, LoopStandardAnalysisResults &) {
return Result();
}
static StringRef name() { return "NoOpLoopAnalysis"; }
};

Expand Down Expand Up @@ -1019,7 +1023,9 @@ bool PassBuilder::parseLoopPass(LoopPassManager &LPM, const PipelineElement &E,
#define LOOP_ANALYSIS(NAME, CREATE_PASS) \
if (Name == "require<" NAME ">") { \
LPM.addPass(RequireAnalysisPass< \
std::remove_reference<decltype(CREATE_PASS)>::type, Loop>()); \
std::remove_reference<decltype(CREATE_PASS)>::type, Loop, \
LoopAnalysisManager, LoopStandardAnalysisResults &, \
LPMUpdater &>()); \
return true; \
} \
if (Name == "invalidate<" NAME ">") { \
Expand Down
18 changes: 4 additions & 14 deletions llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2482,23 +2482,13 @@ bool IndVarSimplify::run(Loop *L) {
return Changed;
}

PreservedAnalyses IndVarSimplifyPass::run(Loop &L, LoopAnalysisManager &AM) {
auto &FAM = AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
PreservedAnalyses IndVarSimplifyPass::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR,
LPMUpdater &) {
Function *F = L.getHeader()->getParent();
const DataLayout &DL = F->getParent()->getDataLayout();

auto *LI = FAM.getCachedResult<LoopAnalysis>(*F);
auto *SE = FAM.getCachedResult<ScalarEvolutionAnalysis>(*F);
auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F);

assert((LI && SE && DT) &&
"Analyses required for indvarsimplify not available!");

// Optional analyses.
auto *TTI = FAM.getCachedResult<TargetIRAnalysis>(*F);
auto *TLI = FAM.getCachedResult<TargetLibraryAnalysis>(*F);

IndVarSimplify IVS(LI, SE, DT, DL, TLI, TTI);
IndVarSimplify IVS(&AR.LI, &AR.SE, &AR.DT, DL, &AR.TLI, &AR.TTI);
if (!IVS.run(&L))
return PreservedAnalyses::all();

Expand Down
19 changes: 8 additions & 11 deletions llvm/lib/Transforms/Scalar/LICM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,23 +185,20 @@ struct LegacyLICMPass : public LoopPass {
};
}

PreservedAnalyses LICMPass::run(Loop &L, LoopAnalysisManager &AM) {
PreservedAnalyses LICMPass::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &) {
const auto &FAM =
AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
AM.getResult<FunctionAnalysisManagerLoopProxy>(L, AR).getManager();
Function *F = L.getHeader()->getParent();

auto *AA = FAM.getCachedResult<AAManager>(*F);
auto *LI = FAM.getCachedResult<LoopAnalysis>(*F);
auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F);
auto *TLI = FAM.getCachedResult<TargetLibraryAnalysis>(*F);
auto *SE = FAM.getCachedResult<ScalarEvolutionAnalysis>(*F);
auto *ORE = FAM.getCachedResult<OptimizationRemarkEmitterAnalysis>(*F);
assert((AA && LI && DT && TLI && SE && ORE) &&
"Analyses for LICM not available");
// FIXME: This should probably be optional rather than required.
if (!ORE)
report_fatal_error("LICM: OptimizationRemarkEmitterAnalysis not "
"cached at a higher level");

LoopInvariantCodeMotion LICM;

if (!LICM.runOnLoop(&L, AA, LI, DT, TLI, SE, ORE, true))
if (!LICM.runOnLoop(&L, &AR.AA, &AR.LI, &AR.DT, &AR.TLI, &AR.SE, ORE, true))
return PreservedAnalyses::all();

// FIXME: There is no setPreservesCFG in the new PM. When that becomes
Expand Down
13 changes: 4 additions & 9 deletions llvm/lib/Transforms/Scalar/LoopDeletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,15 +215,10 @@ bool LoopDeletionPass::runImpl(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
return Changed;
}

PreservedAnalyses LoopDeletionPass::run(Loop &L, LoopAnalysisManager &AM) {
auto &FAM = AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
Function *F = L.getHeader()->getParent();

auto &DT = *FAM.getCachedResult<DominatorTreeAnalysis>(*F);
auto &SE = *FAM.getCachedResult<ScalarEvolutionAnalysis>(*F);
auto &LI = *FAM.getCachedResult<LoopAnalysis>(*F);

bool Changed = runImpl(&L, DT, SE, LI);
PreservedAnalyses LoopDeletionPass::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR,
LPMUpdater &) {
bool Changed = runImpl(&L, AR.DT, AR.SE, AR.LI);
if (!Changed)
return PreservedAnalyses::all();

Expand Down
10 changes: 9 additions & 1 deletion llvm/lib/Transforms/Scalar/LoopDistribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -946,10 +946,18 @@ PreservedAnalyses LoopDistributePass::run(Function &F,
auto &SE = AM.getResult<ScalarEvolutionAnalysis>(F);
auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F);

// We don't directly need these analyses but they're required for loop
// analyses so provide them below.
auto &AA = AM.getResult<AAManager>(F);
auto &AC = AM.getResult<AssumptionAnalysis>(F);
auto &TTI = AM.getResult<TargetIRAnalysis>(F);
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);

auto &LAM = AM.getResult<LoopAnalysisManagerFunctionProxy>(F).getManager();
std::function<const LoopAccessInfo &(Loop &)> GetLAA =
[&](Loop &L) -> const LoopAccessInfo & {
return LAM.getResult<LoopAccessAnalysis>(L);
LoopStandardAnalysisResults AR = {AA, AC, DT, LI, SE, TLI, TTI};
return LAM.getResult<LoopAccessAnalysis>(L, AR);
};

bool Changed = runImpl(F, &LI, &DT, &SE, &ORE, GetLAA);
Expand Down
20 changes: 4 additions & 16 deletions llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,24 +186,12 @@ class LoopIdiomRecognizeLegacyPass : public LoopPass {
};
} // End anonymous namespace.

PreservedAnalyses LoopIdiomRecognizePass::run(Loop &L,
LoopAnalysisManager &AM) {
const auto &FAM =
AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
Function *F = L.getHeader()->getParent();

// Use getCachedResult because Loop pass cannot trigger a function analysis.
auto *AA = FAM.getCachedResult<AAManager>(*F);
auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F);
auto *LI = FAM.getCachedResult<LoopAnalysis>(*F);
auto *SE = FAM.getCachedResult<ScalarEvolutionAnalysis>(*F);
auto *TLI = FAM.getCachedResult<TargetLibraryAnalysis>(*F);
const auto *TTI = FAM.getCachedResult<TargetIRAnalysis>(*F);
PreservedAnalyses LoopIdiomRecognizePass::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR,
LPMUpdater &) {
const auto *DL = &L.getHeader()->getModule()->getDataLayout();
assert((AA && DT && LI && SE && TLI && TTI && DL) &&
"Analyses for Loop Idiom Recognition not available");

LoopIdiomRecognize LIR(AA, DT, LI, SE, TLI, TTI, DL);
LoopIdiomRecognize LIR(&AR.AA, &AR.DT, &AR.LI, &AR.SE, &AR.TLI, &AR.TTI, DL);
if (!LIR.runOnLoop(&L))
return PreservedAnalyses::all();

Expand Down
18 changes: 4 additions & 14 deletions llvm/lib/Transforms/Scalar/LoopInstSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,20 +183,10 @@ class LoopInstSimplifyLegacyPass : public LoopPass {
};
}

PreservedAnalyses LoopInstSimplifyPass::run(Loop &L,
LoopAnalysisManager &AM) {
const auto &FAM =
AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
Function *F = L.getHeader()->getParent();

// Use getCachedResult because Loop pass cannot trigger a function analysis.
auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F);
auto *LI = FAM.getCachedResult<LoopAnalysis>(*F);
auto *AC = FAM.getCachedResult<AssumptionAnalysis>(*F);
const auto *TLI = FAM.getCachedResult<TargetLibraryAnalysis>(*F);
assert((LI && AC && TLI) && "Analyses for Loop Inst Simplify not available");

if (!SimplifyLoopInst(&L, DT, LI, AC, TLI))
PreservedAnalyses LoopInstSimplifyPass::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR,
LPMUpdater &) {
if (!SimplifyLoopInst(&L, &AR.DT, &AR.LI, &AR.AC, &AR.TLI))
return PreservedAnalyses::all();

return getLoopPassPreservedAnalyses();
Expand Down
17 changes: 4 additions & 13 deletions llvm/lib/Transforms/Scalar/LoopRotation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,20 +625,11 @@ bool LoopRotate::processLoop(Loop *L) {
LoopRotatePass::LoopRotatePass(bool EnableHeaderDuplication)
: EnableHeaderDuplication(EnableHeaderDuplication) {}

PreservedAnalyses LoopRotatePass::run(Loop &L, LoopAnalysisManager &AM) {
auto &FAM = AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
Function *F = L.getHeader()->getParent();

auto *LI = FAM.getCachedResult<LoopAnalysis>(*F);
const auto *TTI = FAM.getCachedResult<TargetIRAnalysis>(*F);
auto *AC = FAM.getCachedResult<AssumptionAnalysis>(*F);
assert((LI && TTI && AC) && "Analyses for loop rotation not available");

// Optional analyses.
auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F);
auto *SE = FAM.getCachedResult<ScalarEvolutionAnalysis>(*F);
PreservedAnalyses LoopRotatePass::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR,
LPMUpdater &) {
int Threshold = EnableHeaderDuplication ? DefaultRotationThreshold : 0;
LoopRotate LR(Threshold, LI, TTI, AC, DT, SE);
LoopRotate LR(Threshold, &AR.LI, &AR.TTI, &AR.AC, &AR.DT, &AR.SE);

bool Changed = LR.processLoop(&L);
if (!Changed)
Expand Down
14 changes: 4 additions & 10 deletions llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,10 @@ static bool simplifyLoopCFG(Loop &L, DominatorTree &DT, LoopInfo &LI) {
return Changed;
}

PreservedAnalyses LoopSimplifyCFGPass::run(Loop &L, LoopAnalysisManager &AM) {
const auto &FAM =
AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
Function *F = L.getHeader()->getParent();

auto *LI = FAM.getCachedResult<LoopAnalysis>(*F);
auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F);
assert((LI && DT) && "Analyses for LoopSimplifyCFG not available");

if (!simplifyLoopCFG(L, *DT, *LI))
PreservedAnalyses LoopSimplifyCFGPass::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR,
LPMUpdater &) {
if (!simplifyLoopCFG(L, AR.DT, AR.LI))
return PreservedAnalyses::all();
return getLoopPassPreservedAnalyses();
}
Expand Down
20 changes: 5 additions & 15 deletions llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5052,21 +5052,11 @@ bool LoopStrengthReduce::runOnLoop(Loop *L, LPPassManager & /*LPM*/) {
return ReduceLoopStrength(L, IU, SE, DT, LI, TTI);
}

PreservedAnalyses LoopStrengthReducePass::run(Loop &L,
LoopAnalysisManager &AM) {
const auto &FAM =
AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
Function *F = L.getHeader()->getParent();

auto &IU = AM.getResult<IVUsersAnalysis>(L);
auto *SE = FAM.getCachedResult<ScalarEvolutionAnalysis>(*F);
auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F);
auto *LI = FAM.getCachedResult<LoopAnalysis>(*F);
auto *TTI = FAM.getCachedResult<TargetIRAnalysis>(*F);
assert((SE && DT && LI && TTI) &&
"Analyses for Loop Strength Reduce not available");

if (!ReduceLoopStrength(&L, IU, *SE, *DT, *LI, *TTI))
PreservedAnalyses LoopStrengthReducePass::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR,
LPMUpdater &) {
if (!ReduceLoopStrength(&L, AM.getResult<IVUsersAnalysis>(L, AR), AR.SE,
AR.DT, AR.LI, AR.TTI))
return PreservedAnalyses::all();

return getLoopPassPreservedAnalyses();
Expand Down
36 changes: 9 additions & 27 deletions llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1111,41 +1111,23 @@ Pass *llvm::createSimpleLoopUnrollPass() {
return llvm::createLoopUnrollPass(-1, -1, 0, 0, 0);
}

PreservedAnalyses LoopUnrollPass::run(Loop &L, LoopAnalysisManager &AM) {
PreservedAnalyses LoopUnrollPass::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR,
LPMUpdater &) {
const auto &FAM =
AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager();
AM.getResult<FunctionAnalysisManagerLoopProxy>(L, AR).getManager();
Function *F = L.getHeader()->getParent();


DominatorTree *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F);
LoopInfo *LI = FAM.getCachedResult<LoopAnalysis>(*F);
ScalarEvolution *SE = FAM.getCachedResult<ScalarEvolutionAnalysis>(*F);
auto *TTI = FAM.getCachedResult<TargetIRAnalysis>(*F);
auto *AC = FAM.getCachedResult<AssumptionAnalysis>(*F);
auto *ORE = FAM.getCachedResult<OptimizationRemarkEmitterAnalysis>(*F);
if (!DT)
report_fatal_error(
"LoopUnrollPass: DominatorTreeAnalysis not cached at a higher level");
if (!LI)
report_fatal_error(
"LoopUnrollPass: LoopAnalysis not cached at a higher level");
if (!SE)
report_fatal_error(
"LoopUnrollPass: ScalarEvolutionAnalysis not cached at a higher level");
if (!TTI)
report_fatal_error(
"LoopUnrollPass: TargetIRAnalysis not cached at a higher level");
if (!AC)
report_fatal_error(
"LoopUnrollPass: AssumptionAnalysis not cached at a higher level");
// FIXME: This should probably be optional rather than required.
if (!ORE)
report_fatal_error("LoopUnrollPass: OptimizationRemarkEmitterAnalysis not "
"cached at a higher level");

bool Changed =
tryToUnrollLoop(&L, *DT, LI, SE, *TTI, *AC, *ORE, /*PreserveLCSSA*/ true,
ProvidedCount, ProvidedThreshold, ProvidedAllowPartial,
ProvidedRuntime, ProvidedUpperBound);
bool Changed = tryToUnrollLoop(&L, AR.DT, &AR.LI, &AR.SE, AR.TTI, AR.AC, *ORE,
/*PreserveLCSSA*/ true, ProvidedCount,
ProvidedThreshold, ProvidedAllowPartial,
ProvidedRuntime, ProvidedUpperBound);

if (!Changed)
return PreservedAnalyses::all();
Expand Down
7 changes: 4 additions & 3 deletions llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7641,7 +7641,7 @@ PreservedAnalyses LoopVectorizePass::run(Function &F,
auto &TTI = AM.getResult<TargetIRAnalysis>(F);
auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
auto &BFI = AM.getResult<BlockFrequencyAnalysis>(F);
auto *TLI = AM.getCachedResult<TargetLibraryAnalysis>(F);
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
auto &AA = AM.getResult<AAManager>(F);
auto &AC = AM.getResult<AssumptionAnalysis>(F);
auto &DB = AM.getResult<DemandedBitsAnalysis>(F);
Expand All @@ -7650,10 +7650,11 @@ PreservedAnalyses LoopVectorizePass::run(Function &F,
auto &LAM = AM.getResult<LoopAnalysisManagerFunctionProxy>(F).getManager();
std::function<const LoopAccessInfo &(Loop &)> GetLAA =
[&](Loop &L) -> const LoopAccessInfo & {
return LAM.getResult<LoopAccessAnalysis>(L);
LoopStandardAnalysisResults AR = {AA, AC, DT, LI, SE, TLI, TTI};
return LAM.getResult<LoopAccessAnalysis>(L, AR);
};
bool Changed =
runImpl(F, SE, LI, TTI, DT, BFI, TLI, DB, AA, AC, GetLAA, ORE);
runImpl(F, SE, LI, TTI, DT, BFI, &TLI, DB, AA, AC, GetLAA, ORE);
if (!Changed)
return PreservedAnalyses::all();
PreservedAnalyses PA;
Expand Down
11 changes: 6 additions & 5 deletions llvm/test/Other/loop-pass-ordering.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
; / \ \
; loop.0.0 loop.0.1 loop.1.0
;
; CHECK: Running pass: NoOpLoopPass on loop.1.0
; CHECK: Running pass: NoOpLoopPass on loop.1
; CHECK: Running pass: NoOpLoopPass on loop.0.0
; CHECK: Running pass: NoOpLoopPass on loop.0.1
; CHECK: Running pass: NoOpLoopPass on loop.0
; CHECK: Running pass: NoOpLoopPass on Loop at depth 2 containing: %loop.0.0
; CHECK: Running pass: NoOpLoopPass on Loop at depth 2 containing: %loop.0.1
; CHECK: Running pass: NoOpLoopPass on Loop at depth 1 containing: %loop.0
; CHECK: Running pass: NoOpLoopPass on Loop at depth 2 containing: %loop.1.0
; CHECK: Running pass: NoOpLoopPass on Loop at depth 1 containing: %loop.1

define void @f() {
entry:
br label %loop.0
Expand Down
27 changes: 14 additions & 13 deletions llvm/test/Other/new-pass-manager.ll
Original file line number Diff line number Diff line change
Expand Up @@ -433,12 +433,12 @@
; CHECK-O: Running pass: TailCallElimPass
; CHECK-O: Running pass: SimplifyCFGPass
; CHECK-O: Running pass: ReassociatePass
; CHECK-O: Starting llvm::Loop pass manager run.
; CHECK-O: Finished llvm::Loop pass manager run.
; CHECK-O: Starting Loop pass manager run.
; CHECK-O: Finished Loop pass manager run.
; CHECK-O: Running pass: SimplifyCFGPass
; CHECK-O: Running pass: InstCombinePass
; CHECK-O: Starting llvm::Loop pass manager run.
; CHECK-O: Finished llvm::Loop pass manager run.
; CHECK-O: Starting Loop pass manager run.
; CHECK-O: Finished Loop pass manager run.
; CHECK-O: Running pass: MemCpyOptPass
; CHECK-O: Running pass: SCCPPass
; CHECK-O: Running pass: BDCEPass
Expand Down Expand Up @@ -544,20 +544,21 @@
; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: DominatorTreeAnalysis
; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: AAManager
; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: TargetLibraryAnalysis
; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: ScalarEvolutionAnalysis
; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: AssumptionAnalysis
; CHECK-REPEAT-LOOP-PASS-NEXT: Starting llvm::Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: ScalarEvolutionAnalysis
; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: TargetIRAnalysis
; CHECK-REPEAT-LOOP-PASS-NEXT: Starting Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: RepeatedPass
; CHECK-REPEAT-LOOP-PASS-NEXT: Starting llvm::Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Starting Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: NoOpLoopPass
; CHECK-REPEAT-LOOP-PASS-NEXT: Finished llvm::Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Starting llvm::Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Finished Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Starting Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: NoOpLoopPass
; CHECK-REPEAT-LOOP-PASS-NEXT: Finished llvm::Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Starting llvm::Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Finished Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Starting Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: NoOpLoopPass
; CHECK-REPEAT-LOOP-PASS-NEXT: Finished llvm::Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Finished llvm::Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Finished Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Finished Loop pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Finished llvm::Function pass manager run
; CHECK-REPEAT-LOOP-PASS-NEXT: Finished llvm::Module pass manager run

Expand Down
8 changes: 4 additions & 4 deletions llvm/test/Other/pass-pipeline-parsing.ll
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,10 @@
; CHECK-TWO-NOOP-LOOP: Running pass: ModuleToFunctionPassAdaptor
; CHECK-TWO-NOOP-LOOP: Starting llvm::Function pass manager run
; CHECK-TWO-NOOP-LOOP: Running pass: FunctionToLoopPassAdaptor
; CHECK-TWO-NOOP-LOOP: Starting llvm::Loop pass manager run
; CHECK-TWO-NOOP-LOOP: Starting Loop pass manager run
; CHECK-TWO-NOOP-LOOP: Running pass: NoOpLoopPass
; CHECK-TWO-NOOP-LOOP: Running pass: NoOpLoopPass
; CHECK-TWO-NOOP-LOOP: Finished llvm::Loop pass manager run
; CHECK-TWO-NOOP-LOOP: Finished Loop pass manager run
; CHECK-TWO-NOOP-LOOP: Finished llvm::Function pass manager run
; CHECK-TWO-NOOP-LOOP: Finished llvm::Module pass manager run

Expand All @@ -167,9 +167,9 @@
; CHECK-NESTED-FP-LP: Running pass: ModuleToFunctionPassAdaptor
; CHECK-NESTED-FP-LP: Starting llvm::Function pass manager run
; CHECK-NESTED-FP-LP: Running pass: FunctionToLoopPassAdaptor
; CHECK-NESTED-FP-LP: Starting llvm::Loop pass manager run
; CHECK-NESTED-FP-LP: Starting Loop pass manager run
; CHECK-NESTED-FP-LP: Running pass: NoOpLoopPass
; CHECK-NESTED-FP-LP: Finished llvm::Loop pass manager run
; CHECK-NESTED-FP-LP: Finished Loop pass manager run
; CHECK-NESTED-FP-LP: Finished llvm::Function pass manager run
; CHECK-NESTED-FP-LP: Finished llvm::Module pass manager run

Expand Down
1,439 changes: 1,332 additions & 107 deletions llvm/unittests/Analysis/LoopPassManagerTest.cpp

Large diffs are not rendered by default.