; CHECK-O: Running pass: PostOrderFunctionAttrsPass on (main)
; CHECK-O: Invalidating all non-preserved analyses for: (main)
; CHECK-O: Clearing all analysis results for: main
-; CHECK-O: Invalidating analysis: FunctionAnalysisManagerCGSCCProxy on (main)
; CHECK-O3: Running pass: ArgumentPromotionPass on (main)
-; CHECK-O2: Running pass: CGSCCToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
-; CHECK-O: Running analysis: FunctionAnalysisManagerCGSCCProxy on (main)
; CHECK-O3: Running analysis: TargetIRAnalysis on main
; CHECK-O: Running analysis: PassInstrumentationAnalysis on main
; CHECK-O3: Running pass: CGSCCToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
static void getModuleAAResultImpl(Function &F, FunctionAnalysisManager &AM,
AAResults &AAResults) {
auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
- auto &MAM = MAMProxy.getManager();
- if (auto *R = MAM.template getCachedResult<AnalysisT>(*F.getParent())) {
+ if (auto *R =
+ MAMProxy.template getCachedResult<AnalysisT>(*F.getParent())) {
AAResults.addAAResult(*R);
MAMProxy
.template registerOuterAnalysisInvalidation<AnalysisT, AAManager>();
public:
class Result {
public:
+ explicit Result() : FAM(nullptr) {}
explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
+ void updateFAM(FunctionAnalysisManager &FAM) { this->FAM = &FAM; }
/// Accessor for the analysis manager.
- FunctionAnalysisManager &getManager() { return *FAM; }
+ FunctionAnalysisManager &getManager() {
+ assert(FAM);
+ return *FAM;
+ }
bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA,
CGSCCAnalysisManager::Invalidator &Inv);
/// update result struct for the overall CGSCC walk.
LazyCallGraph::SCC &updateCGAndAnalysisManagerForFunctionPass(
LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
- CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR);
+ CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
+ FunctionAnalysisManager &FAM);
/// Helper to update the call graph after running a CGSCC pass.
///
/// update result struct for the overall CGSCC walk.
LazyCallGraph::SCC &updateCGAndAnalysisManagerForCGSCCPass(
LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N,
- CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR);
+ CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
+ FunctionAnalysisManager &FAM);
/// Adaptor that maps from a SCC to its functions.
///
auto PAC = PA.getChecker<LazyCallGraphAnalysis>();
if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Module>>()) {
CurrentC = &updateCGAndAnalysisManagerForFunctionPass(CG, *CurrentC, *N,
- AM, UR);
+ AM, UR, FAM);
assert(
CG.lookupSCC(*N) == CurrentC &&
"Current SCC not updated to the SCC containing the current node!");
// Update the analysis manager with each run and intersect the total set
// of preserved analyses so we're ready to iterate.
AM.invalidate(*C, PassPA);
+
PA.intersect(std::move(PassPA));
}
// Get the call graph for this module.
LazyCallGraph &CG = AM.getResult<LazyCallGraphAnalysis>(M);
+ // Get Function analysis manager from its proxy.
+ FunctionAnalysisManager &FAM =
+ AM.getCachedResult<FunctionAnalysisManagerModuleProxy>(M)->getManager();
+
// We keep worklists to allow us to push more work onto the pass manager as
// the passes are run.
SmallPriorityWorklist<LazyCallGraph::RefSCC *, 1> RCWorklist;
continue;
}
- // Ensure we can proxy analysis updates from from the CGSCC analysis
- // manager into the Function analysis manager by getting a proxy here.
- // FIXME: This seems like a bit of a hack. We should find a cleaner
- // or more costructive way to ensure this happens.
- (void)CGAM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG);
+ // Ensure we can proxy analysis updates from the CGSCC analysis manager
+ // into the the Function analysis manager by getting a proxy here.
+ // This also needs to update the FunctionAnalysisManager, as this may be
+ // the first time we see this SCC.
+ CGAM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG).updateFAM(
+ FAM);
// Each time we visit a new SCC pulled off the worklist,
// a transformation of a child SCC may have also modified this parent
C = UR.UpdatedC ? UR.UpdatedC : C;
RC = UR.UpdatedRC ? UR.UpdatedRC : RC;
+ if (UR.UpdatedC) {
+ // If we're updating the SCC, also update the FAM inside the proxy's
+ // result.
+ CGAM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG).updateFAM(
+ FAM);
+ }
+
// If the CGSCC pass wasn't able to provide a valid updated SCC,
// the current SCC may simply need to be skipped if invalid.
if (UR.InvalidatedSCCs.count(C)) {
return &static_cast<ResultModelT *>(ResultConcept)->Result;
}
+ /// Verify that the given Result cannot be invalidated, assert otherwise.
+ template <typename PassT>
+ void verifyNotInvalidated(IRUnitT &IR, typename PassT::Result *Result) const {
+ PreservedAnalyses PA = PreservedAnalyses::none();
+ SmallDenseMap<AnalysisKey *, bool, 8> IsResultInvalidated;
+ Invalidator Inv(IsResultInvalidated, AnalysisResults);
+ assert(!Result->invalidate(IR, PA, Inv) &&
+ "Cached result cannot be invalidated");
+ }
+
/// Register an analysis pass with the manager.
///
/// The parameter is a callable whose result is an analysis pass. This allows
public:
explicit Result(const AnalysisManagerT &OuterAM) : OuterAM(&OuterAM) {}
- const AnalysisManagerT &getManager() const { return *OuterAM; }
+ /// Get a cached analysis. If the analysis can be invalidated, this will
+ /// assert.
+ template <typename PassT, typename IRUnitTParam>
+ typename PassT::Result *getCachedResult(IRUnitTParam &IR) const {
+ typename PassT::Result *Res =
+ OuterAM->template getCachedResult<PassT>(IR);
+ if (Res)
+ OuterAM->template verifyNotInvalidated<PassT>(IR, Res);
+ return Res;
+ }
+
+ /// Method provided for unit testing, not intended for general use.
+ template <typename PassT, typename IRUnitTParam>
+ bool cachedResultExists(IRUnitTParam &IR) const {
+ typename PassT::Result *Res =
+ OuterAM->template getCachedResult<PassT>(IR);
+ return Res != nullptr;
+ }
/// When invalidation occurs, remove any registered invalidation events.
bool invalidate(
LazyCallGraph::SCC *SCC = nullptr;
CGSCCAnalysisManager *AM = nullptr;
CGSCCUpdateResult *UR = nullptr;
+ FunctionAnalysisManager *FAM = nullptr;
///}
public:
this->SCC = &SCC;
this->AM = &AM;
this->UR = &UR;
+ FAM =
+ &AM.getResult<FunctionAnalysisManagerCGSCCProxy>(SCC, LCG).getManager();
}
///}
// a pointer that we can update.
LazyCallGraph::SCC *C = &InitialC;
+ // Get Function analysis manager from its proxy.
+ FunctionAnalysisManager &FAM =
+ AM.getCachedResult<FunctionAnalysisManagerCGSCCProxy>(*C)->getManager();
+
for (auto &Pass : Passes) {
if (DebugLogging)
dbgs() << "Running pass: " << Pass->name() << " on " << *C << "\n";
// Update the SCC if necessary.
C = UR.UpdatedC ? UR.UpdatedC : C;
+ if (UR.UpdatedC) {
+ // If C is updated, also create a proxy and update FAM inside the result.
+ auto *ResultFAMCP =
+ &AM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, G);
+ ResultFAMCP->updateFAM(FAM);
+ }
// If the CGSCC pass wasn't able to provide a valid updated SCC, the
// current SCC may simply need to be skipped if invalid.
FunctionAnalysisManagerCGSCCProxy::run(LazyCallGraph::SCC &C,
CGSCCAnalysisManager &AM,
LazyCallGraph &CG) {
- // Collect the FunctionAnalysisManager from the Module layer and use that to
- // build the proxy result.
- //
- // This allows us to rely on the FunctionAnalysisMangaerModuleProxy to
- // invalidate the function analyses.
- auto &MAM = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
+ // Note: unconditionally getting checking that the proxy exists may get it at
+ // this point. There are cases when this is being run unnecessarily, but
+ // it is cheap and having the assertion in place is more valuable.
+ auto &MAMProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
Module &M = *C.begin()->getFunction().getParent();
- auto *FAMProxy = MAM.getCachedResult<FunctionAnalysisManagerModuleProxy>(M);
- assert(FAMProxy && "The CGSCC pass manager requires that the FAM module "
- "proxy is run on the module prior to entering the CGSCC "
- "walk.");
-
- // Note that we special-case invalidation handling of this proxy in the CGSCC
- // analysis manager's Module proxy. This avoids the need to do anything
- // special here to recompute all of this if ever the FAM's module proxy goes
- // away.
- return Result(FAMProxy->getManager());
+ bool ProxyExists =
+ MAMProxy.cachedResultExists<FunctionAnalysisManagerModuleProxy>(M);
+ assert(ProxyExists &&
+ "The CGSCC pass manager requires that the FAM module proxy is run "
+ "on the module prior to entering the CGSCC walk");
+ (void)ProxyExists;
+
+ // We just return an empty result. The caller will use the updateFAM interface
+ // to correctly register the relevant FunctionAnalysisManager based on the
+ // context in which this proxy is run.
+ return Result();
}
bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate(
if (PA.areAllPreserved())
return false; // This is still a valid proxy.
- // If this proxy isn't marked as preserved, then even if the result remains
- // valid, the key itself may no longer be valid, so we clear everything.
+ // All updates to preserve valid results are done below, so we don't need to
+ // invalidate this proxy.
//
// Note that in order to preserve this proxy, a module pass must ensure that
// the FAM has been completely updated to handle the deletion of functions.
for (LazyCallGraph::Node &N : C)
FAM->clear(N.getFunction(), N.getFunction().getName());
- return true;
+ return false;
}
// Directly check if the relevant set is preserved.
} // end namespace llvm
-/// When a new SCC is created for the graph and there might be function
-/// analysis results cached for the functions now in that SCC two forms of
-/// updates are required.
+/// When a new SCC is created for the graph we first update the
+/// FunctionAnalysisManager in the Proxy's result.
+/// As there might be function analysis results cached for the functions now in
+/// that SCC, two forms of updates are required.
///
/// First, a proxy from the SCC to the FunctionAnalysisManager needs to be
/// created so that any subsequent invalidation events to the SCC are
/// function analyses so that they don't retain stale handles.
static void updateNewSCCFunctionAnalyses(LazyCallGraph::SCC &C,
LazyCallGraph &G,
- CGSCCAnalysisManager &AM) {
- // Get the relevant function analysis manager.
- auto &FAM =
- AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, G).getManager();
+ CGSCCAnalysisManager &AM,
+ FunctionAnalysisManager &FAM) {
+ AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, G).updateFAM(FAM);
// Now walk the functions in this SCC and invalidate any function analysis
// results that might have outer dependencies on an SCC analysis.
// If we had a cached FAM proxy originally, we will want to create more of
// them for each SCC that was split off.
- bool NeedFAMProxy =
- AM.getCachedResult<FunctionAnalysisManagerCGSCCProxy>(*OldC) != nullptr;
+ FunctionAnalysisManager *FAM = nullptr;
+ if (auto *FAMProxy =
+ AM.getCachedResult<FunctionAnalysisManagerCGSCCProxy>(*OldC))
+ FAM = &FAMProxy->getManager();
// We need to propagate an invalidation call to all but the newly current SCC
// because the outer pass manager won't do that for us after splitting them.
AM.invalidate(*OldC, PA);
// Ensure the now-current SCC's function analyses are updated.
- if (NeedFAMProxy)
- updateNewSCCFunctionAnalyses(*C, G, AM);
+ if (FAM)
+ updateNewSCCFunctionAnalyses(*C, G, AM, *FAM);
for (SCC &NewC : llvm::reverse(make_range(std::next(NewSCCRange.begin()),
NewSCCRange.end()))) {
LLVM_DEBUG(dbgs() << "Enqueuing a newly formed SCC:" << NewC << "\n");
// Ensure new SCCs' function analyses are updated.
- if (NeedFAMProxy)
- updateNewSCCFunctionAnalyses(NewC, G, AM);
+ if (FAM)
+ updateNewSCCFunctionAnalyses(NewC, G, AM, *FAM);
// Also propagate a normal invalidation to the new SCC as only the current
// will get one from the pass manager infrastructure.
static LazyCallGraph::SCC &updateCGAndAnalysisManagerForPass(
LazyCallGraph &G, LazyCallGraph::SCC &InitialC, LazyCallGraph::Node &N,
- CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, bool FunctionPass) {
+ CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
+ FunctionAnalysisManager &FAM, bool FunctionPass) {
using Node = LazyCallGraph::Node;
using Edge = LazyCallGraph::Edge;
using SCC = LazyCallGraph::SCC;
// analysis manager, we need to create a proxy in the new current SCC as
// the invalidated SCCs had their functions moved.
if (HasFunctionAnalysisProxy)
- AM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, G);
+ AM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, G).updateFAM(FAM);
// Any analyses cached for this SCC are no longer precise as the shape
// has changed by introducing this cycle. However, we have taken care to
LazyCallGraph::SCC &llvm::updateCGAndAnalysisManagerForFunctionPass(
LazyCallGraph &G, LazyCallGraph::SCC &InitialC, LazyCallGraph::Node &N,
- CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR) {
- return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR,
+ CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
+ FunctionAnalysisManager &FAM) {
+ return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR, FAM,
/* FunctionPass */ true);
}
LazyCallGraph::SCC &llvm::updateCGAndAnalysisManagerForCGSCCPass(
LazyCallGraph &G, LazyCallGraph::SCC &InitialC, LazyCallGraph::Node &N,
- CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR) {
- return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR,
+ CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
+ FunctionAnalysisManager &FAM) {
+ return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR, FAM,
/* FunctionPass */ false);
}
static void updateCallGraphAfterCoroutineSplit(
LazyCallGraph::Node &N, const coro::Shape &Shape,
const SmallVectorImpl<Function *> &Clones, LazyCallGraph::SCC &C,
- LazyCallGraph &CG, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR) {
+ LazyCallGraph &CG, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR,
+ FunctionAnalysisManager &FAM) {
if (!Shape.CoroBegin)
return;
// update of its own. Function passes run by the adaptor are not permitted to
// add new edges of any kind to the graph, and the new edges inserted by this
// pass would be misattributed to that unrelated function pass.
- updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR);
+ updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR, FAM);
}
// When we see the coroutine the first time, we insert an indirect call to a
// non-zero number of nodes, so we assume that here and grab the first
// node's function's module.
Module &M = *C.begin()->getFunction().getParent();
+ auto &FAM =
+ AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
+
if (!declaresCoroSplitIntrinsics(M))
return PreservedAnalyses::all();
SmallVector<Function *, 4> Clones;
const coro::Shape Shape = splitCoroutine(F, Clones);
- updateCallGraphAfterCoroutineSplit(*N, Shape, Clones, C, CG, AM, UR);
+ updateCallGraphAfterCoroutineSplit(*N, Shape, Clones, C, CG, AM, UR, FAM);
}
if (PrepareFn)
PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
CGSCCAnalysisManager &AM, LazyCallGraph &CG,
CGSCCUpdateResult &UR) {
- const ModuleAnalysisManager &MAM =
- AM.getResult<ModuleAnalysisManagerCGSCCProxy>(InitialC, CG).getManager();
+ const auto &MAMProxy =
+ AM.getResult<ModuleAnalysisManagerCGSCCProxy>(InitialC, CG);
bool Changed = false;
assert(InitialC.size() > 0 && "Cannot handle an empty SCC!");
Module &M = *InitialC.begin()->getFunction().getParent();
- ProfileSummaryInfo *PSI = MAM.getCachedResult<ProfileSummaryAnalysis>(M);
+ ProfileSummaryInfo *PSI = MAMProxy.getCachedResult<ProfileSummaryAnalysis>(M);
if (!ImportedFunctionsStats &&
InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) {
LLVM_DEBUG(dbgs() << "Inlining calls in: " << F.getName() << "\n");
- // Get a FunctionAnalysisManager via a proxy for this particular node. We
- // do this each time we visit a node as the SCC may have changed and as
- // we're going to mutate this particular function we want to make sure the
- // proxy is in place to forward any invalidation events. We can use the
- // manager we get here for looking up results for functions other than this
- // node however because those functions aren't going to be mutated by this
- // pass.
- FunctionAnalysisManager &FAM =
- AM.getResult<FunctionAnalysisManagerCGSCCProxy>(*C, CG).getManager();
-
// Get the remarks emission analysis for the caller.
auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
// essentially do all of the same things as a function pass and we can
// re-use the exact same logic for updating the call graph to reflect the
// change.
+
+ // Inside the update, we also update the FunctionAnalysisManager in the
+ // proxy for this particular SCC. We do this as the SCC may have changed and
+ // as we're going to mutate this particular function we want to make sure
+ // the proxy is in place to forward any invalidation events.
LazyCallGraph::SCC *OldC = C;
- C = &updateCGAndAnalysisManagerForFunctionPass(CG, *C, N, AM, UR);
+ C = &updateCGAndAnalysisManagerForFunctionPass(CG, *C, N, AM, UR, FAM);
LLVM_DEBUG(dbgs() << "Updated inlining SCC: " << *C << "\n");
RC = &C->getOuterRefSCC();
// Get the necessary information out of the call graph and nuke the
// function there. Also, cclear out any cached analyses.
auto &DeadC = *CG.lookupSCC(*CG.lookup(*DeadF));
- FunctionAnalysisManager &FAM =
- AM.getResult<FunctionAnalysisManagerCGSCCProxy>(DeadC, CG).getManager();
FAM.clear(*DeadF, DeadF->getName());
AM.clear(DeadC, DeadC.getName());
auto &DeadRC = DeadC.getOuterRefSCC();
auto *LI = AM.getCachedResult<LoopAnalysis>(F);
auto *AA = &AM.getResult<AAManager>(F);
- const ModuleAnalysisManager &MAM =
- AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
+ auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
ProfileSummaryInfo *PSI =
- MAM.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
+ MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
auto *BFI = (PSI && PSI->hasProfileSummary()) ?
&AM.getResult<BlockFrequencyAnalysis>(F) : nullptr;
PreservedAnalyses AddressSanitizerPass::run(Function &F,
AnalysisManager<Function> &AM) {
auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
- auto &MAM = MAMProxy.getManager();
Module &M = *F.getParent();
- if (auto *R = MAM.getCachedResult<ASanGlobalsMetadataAnalysis>(M)) {
+ if (auto *R = MAMProxy.getCachedResult<ASanGlobalsMetadataAnalysis>(M)) {
const TargetLibraryInfo *TLI = &AM.getResult<TargetLibraryAnalysis>(F);
AddressSanitizer Sanitizer(M, R, CompileKernel, Recover, UseAfterScope);
if (Sanitizer.instrumentFunction(F, TLI))
auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
- auto &MAM = MAMProxy.getManager();
- auto &PSI = *MAM.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
+ auto &PSI = *MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
auto &RI = FAM.getResult<RegionInfoAnalysis>(F);
auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
bool Changed = CHR(F, BFI, DT, PSI, RI, ORE).run();
auto BFI = ConstHoistWithBlockFrequency
? &AM.getResult<BlockFrequencyAnalysis>(F)
: nullptr;
- auto &MAM = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
- auto *PSI = MAM.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
+ auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+ auto *PSI = MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
if (!runImpl(F, TTI, DT, BFI, F.getEntryBlock(), PSI))
return PreservedAnalyses::all();
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
auto &AA = AM.getResult<AAManager>(F);
auto &AC = AM.getResult<AssumptionAnalysis>(F);
- auto &MAM = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
- auto *PSI = MAM.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
+ auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+ auto *PSI = MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
auto *BFI = (PSI && PSI->hasProfileSummary()) ?
&AM.getResult<BlockFrequencyAnalysis>(F) : nullptr;
MemorySSA *MSSA = EnableMSSALoopDependency
if (auto *LAMProxy = AM.getCachedResult<LoopAnalysisManagerFunctionProxy>(F))
LAM = &LAMProxy->getManager();
- const ModuleAnalysisManager &MAM =
- AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
+ auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
ProfileSummaryInfo *PSI =
- MAM.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
+ MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
auto *BFI = (PSI && PSI->hasProfileSummary()) ?
&AM.getResult<BlockFrequencyAnalysis>(F) : nullptr;
} else if (LCG) {
LazyCallGraph::Node &N = LCG->get(Fn);
LazyCallGraph::SCC *C = LCG->lookupSCC(N);
- updateCGAndAnalysisManagerForCGSCCPass(*LCG, *C, N, *AM, *UR);
+ updateCGAndAnalysisManagerForCGSCCPass(*LCG, *C, N, *AM, *UR, *FAM);
}
}
LoopStandardAnalysisResults AR = {AA, AC, DT, LI, SE, TLI, TTI, MSSA};
return LAM.getResult<LoopAccessAnalysis>(L, AR);
};
- const ModuleAnalysisManager &MAM =
- AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
+ auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
ProfileSummaryInfo *PSI =
- MAM.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
+ MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
LoopVectorizeResult Result =
runImpl(F, SE, LI, TTI, DT, BFI, &TLI, DB, AA, AC, GetLAA, ORE, PSI);
if (!Result.MadeAnyChange)
LazyCallGraph &CG, CGSCCUpdateResult &UR) {
++SCCPassRunCount1;
- const ModuleAnalysisManager &MAM =
- AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
- FunctionAnalysisManager &FAM =
- AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
+ // Note: The proper way to get to a module pass from a CGSCC pass is
+ // through the ModuleAnalysisManagerCGSCCProxy:
+ // ```
+ // const auto &MAMProxy =
+ // AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
+ // ```
+ // However getting a stateful analysis is incorrect usage, and the call
+ // to getCachedResult below asserts:
+ // ```
+ // if (TestModuleAnalysis::Result *TMA =
+ // MAMProxy.getCachedResult<TestModuleAnalysis>(
+ // *C.begin()->getFunction().getParent()))
+ // AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
+ // ```
+ // For the purposes of this unittest, use the above MAM directly.
if (TestModuleAnalysis::Result *TMA =
MAM.getCachedResult<TestModuleAnalysis>(
*C.begin()->getFunction().getParent()))
AnalyzedModuleFunctionCount1 += TMA->FunctionCount;
+ FunctionAnalysisManager &FAM =
+ AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
TestSCCAnalysis::Result &AR = AM.getResult<TestSCCAnalysis>(C, CG);
AnalyzedSCCFunctionCount1 += AR.FunctionCount;
for (LazyCallGraph::Node &N : C) {
// required module pass above.
CGSCCPassManager CGPM1(/*DebugLogging*/ true);
int CountFoundModuleAnalysis1 = 0;
- CGPM1.addPass(
- LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
- LazyCallGraph &CG, CGSCCUpdateResult &UR) {
- const auto &MAM =
- AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
- auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
- *C.begin()->getFunction().getParent());
-
- if (TMA)
- ++CountFoundModuleAnalysis1;
-
- return PreservedAnalyses::all();
- }));
+ CGPM1.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C,
+ CGSCCAnalysisManager &AM, LazyCallGraph &CG,
+ CGSCCUpdateResult &UR) {
+ const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
+ if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
+ *C.begin()->getFunction().getParent()))
+ ++CountFoundModuleAnalysis1;
+
+ return PreservedAnalyses::all();
+ }));
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
// The second CGSCC run checks that the module analysis got preserved the
CGPM2.addPass(
LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
LazyCallGraph &CG, CGSCCUpdateResult &UR) {
- const auto &MAM =
- AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
- auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
- *C.begin()->getFunction().getParent());
-
- if (TMA)
+ const auto &MAMProxy =
+ AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
+ if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
+ *C.begin()->getFunction().getParent()))
++CountFoundModuleAnalysis2;
// Only fail to preserve analyses on one SCC and make sure that gets
// should have been invalidated by the above CGSCC run.
CGSCCPassManager CGPM3(/*DebugLogging*/ true);
int CountFoundModuleAnalysis3 = 0;
- CGPM3.addPass(
- LambdaSCCPass([&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
- LazyCallGraph &CG, CGSCCUpdateResult &UR) {
- const auto &MAM =
- AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG).getManager();
- auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(
- *C.begin()->getFunction().getParent());
-
- if (TMA)
- ++CountFoundModuleAnalysis3;
+ CGPM3.addPass(LambdaSCCPass([&](LazyCallGraph::SCC &C,
+ CGSCCAnalysisManager &AM, LazyCallGraph &CG,
+ CGSCCUpdateResult &UR) {
+ const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
+ if (MAMProxy.cachedResultExists<TestModuleAnalysis>(
+ *C.begin()->getFunction().getParent()))
+ ++CountFoundModuleAnalysis3;
- return PreservedAnalyses::none();
- }));
+ return PreservedAnalyses::none();
+ }));
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
MPM.run(*M, MAM);
// Start true and mark false if we ever failed to find a module analysis
// because we expect this to succeed for each SCC.
bool FoundModuleAnalysis1 = true;
- FPM1.addPass(
- LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
- const auto &MAM =
- AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
- auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
+ FPM1.addPass(LambdaFunctionPass([&](Function &F,
+ FunctionAnalysisManager &AM) {
+ const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+ if (!MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
+ FoundModuleAnalysis1 = false;
- if (!TMA)
- FoundModuleAnalysis1 = false;
-
- return PreservedAnalyses::all();
- }));
+ return PreservedAnalyses::all();
+ }));
CGSCCPassManager CGPM1(/*DebugLogging*/ true);
CGPM1.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM1)));
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM1)));
// Again, start true and mark false if we ever failed to find a module analysis
// because we expect this to succeed for each SCC.
bool FoundModuleAnalysis2 = true;
- FPM2.addPass(
- LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
- const auto &MAM =
- AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
- auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
-
- if (!TMA)
- FoundModuleAnalysis2 = false;
-
- // Only fail to preserve analyses on one SCC and make sure that gets
- // propagated.
- return F.getName() == "h2" ? PreservedAnalyses::none()
- : PreservedAnalyses::all();
- }));
+ FPM2.addPass(LambdaFunctionPass([&](Function &F,
+ FunctionAnalysisManager &AM) {
+ const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+ if (!MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
+ FoundModuleAnalysis2 = false;
+
+ // Only fail to preserve analyses on one SCC and make sure that gets
+ // propagated.
+ return F.getName() == "h2" ? PreservedAnalyses::none()
+ : PreservedAnalyses::all();
+ }));
CGSCCPassManager CGPM2(/*DebugLogging*/ true);
CGPM2.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM2)));
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM2)));
// Start false and mark true if we ever *succeeded* to find a module
// analysis, as we expect this to fail for every function.
bool FoundModuleAnalysis3 = false;
- FPM3.addPass(
- LambdaFunctionPass([&](Function &F, FunctionAnalysisManager &AM) {
- const auto &MAM =
- AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
- auto *TMA = MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
+ FPM3.addPass(LambdaFunctionPass([&](Function &F,
+ FunctionAnalysisManager &AM) {
+ const auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+ if (MAMProxy.cachedResultExists<TestModuleAnalysis>(*F.getParent()))
+ FoundModuleAnalysis3 = true;
- if (TMA)
- FoundModuleAnalysis3 = true;
-
- return PreservedAnalyses::none();
- }));
+ return PreservedAnalyses::none();
+ }));
CGSCCPassManager CGPM3(/*DebugLogging*/ true);
CGPM3.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM3)));
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM3)));
}
};
- TestIndirectSCCAnalysis(int &Runs) : Runs(Runs) {}
+ TestIndirectSCCAnalysis(int &Runs, ModuleAnalysisManager &MAM)
+ : Runs(Runs), MAM(MAM) {}
/// Run the analysis pass over the function and return a result.
Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
auto &SCCDep = AM.getResult<TestSCCAnalysis>(C, CG);
auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C, CG);
- const ModuleAnalysisManager &MAM = ModuleProxy.getManager();
// For the test, we insist that the module analysis starts off in the
- // cache.
+ // cache. Getting a cached result that isn't stateless triggers an assert.
+ // auto &MDep = *ModuleProxy.getCachedResult<TestModuleAnalysis>(
+ // *C.begin()->getFunction().getParent());
+ // Use MAM, for the purposes of this unittest.
auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(
*C.begin()->getFunction().getParent());
// Register the dependency as module analysis dependencies have to be
static AnalysisKey Key;
int &Runs;
+ ModuleAnalysisManager &MAM;
};
AnalysisKey TestIndirectSCCAnalysis::Key;
}
};
- TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
+ TestIndirectFunctionAnalysis(int &Runs, ModuleAnalysisManager &MAM,
+ CGSCCAnalysisManager &CGAM)
+ : Runs(Runs), MAM(MAM), CGAM(CGAM) {}
/// Run the analysis pass over the function and return a result.
Result run(Function &F, FunctionAnalysisManager &AM) {
auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
- const ModuleAnalysisManager &MAM = ModuleProxy.getManager();
// For the test, we insist that the module analysis starts off in the
- // cache.
+ // cache. Getting a cached result that isn't stateless triggers an assert.
+ // Use MAM, for the purposes of this unittest.
auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
// Register the dependency as module analysis dependencies have to be
// pre-registered on the proxy.
ModuleProxy.registerOuterAnalysisInvalidation<
TestModuleAnalysis, TestIndirectFunctionAnalysis>();
- // For thet test we assume this is run inside a CGSCC pass manager.
+ // For the test we assume this is run inside a CGSCC pass manager.
+ // Use MAM, for the purposes of this unittest.
const LazyCallGraph &CG =
*MAM.getCachedResult<LazyCallGraphAnalysis>(*F.getParent());
auto &CGSCCProxy = AM.getResult<CGSCCAnalysisManagerFunctionProxy>(F);
- const CGSCCAnalysisManager &CGAM = CGSCCProxy.getManager();
// For the test, we insist that the CGSCC analysis starts off in the cache.
+ // Getting a cached result that isn't stateless triggers an assert.
+ // Use CGAM, for the purposes of this unittest.
auto &SCCDep =
*CGAM.getCachedResult<TestSCCAnalysis>(*CG.lookupSCC(*CG.lookup(F)));
// Register the dependency as CGSCC analysis dependencies have to be
static AnalysisKey Key;
int &Runs;
+ ModuleAnalysisManager &MAM;
+ CGSCCAnalysisManager &CGAM;
};
AnalysisKey TestIndirectFunctionAnalysis::Key;
DoublyIndirectSCCAnalysisRuns = 0;
CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
CGAM.registerPass(
- [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
+ [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns, MAM); });
CGAM.registerPass([&] {
return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
});
int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
FAM.registerPass([&] {
- return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
+ return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns, MAM,
+ CGAM);
});
ModulePassManager MPM(/*DebugLogging*/ true);
DoublyIndirectSCCAnalysisRuns = 0;
CGAM.registerPass([&] { return TestSCCAnalysis(SCCAnalysisRuns); });
CGAM.registerPass(
- [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns); });
+ [&] { return TestIndirectSCCAnalysis(IndirectSCCAnalysisRuns, MAM); });
CGAM.registerPass([&] {
return TestDoublyIndirectSCCAnalysis(DoublyIndirectSCCAnalysisRuns);
});
int FunctionAnalysisRuns = 0, IndirectFunctionAnalysisRuns = 0;
FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
FAM.registerPass([&] {
- return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns);
+ return TestIndirectFunctionAnalysis(IndirectFunctionAnalysisRuns, MAM,
+ CGAM);
});
ModulePassManager MPM(/*DebugLogging*/ true);
// Now update the call graph.
auto &NewC =
- updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR);
+ updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM);
assert(&NewC != &C && "Should get a new SCC due to update!");
(void)&NewC;
// Now update the call graph.
auto &NewC =
- updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR);
+ updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM);
assert(&NewC != &C && "Should get a new SCC due to update!");
(void)&NewC;
if (C.getName() != "(h3, h1, h2)")
return;
+ auto &FAM =
+ AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
Function *FnX = M->getFunction("x");
Function *FnH1 = M->getFunction("h1");
Function *FnH2 = M->getFunction("h2");
auto &H2N = *llvm::find_if(
C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
ASSERT_NO_FATAL_FAILURE(
- updateCGAndAnalysisManagerForCGSCCPass(CG, C, H2N, AM, UR));
+ updateCGAndAnalysisManagerForCGSCCPass(CG, C, H2N, AM, UR, FAM));
}));
ModulePassManager MPM(/*DebugLogging*/ true);
if (C.getName() != "(h3, h1, h2)")
return;
+ auto &FAM =
+ AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
Function *FnX = M->getFunction("x");
Function *FnH1 = M->getFunction("h1");
Function *FnH2 = M->getFunction("h2");
auto &H2N = *llvm::find_if(
C, [](LazyCallGraph::Node &N) { return N.getName() == "h2"; });
- ASSERT_DEATH(updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR),
- "Any new calls should be modeled as");
+ ASSERT_DEATH(
+ updateCGAndAnalysisManagerForFunctionPass(CG, C, H2N, AM, UR, FAM),
+ "Any new calls should be modeled as");
}));
ModulePassManager MPM(/*DebugLogging*/ true);
if (C.getName() != "(f)")
return;
+ auto &FAM =
+ AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
Function *FnF = M->getFunction("f");
Function *FnH2 = M->getFunction("h2");
ASSERT_NE(FnF, nullptr);
auto &FN = *llvm::find_if(
C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
ASSERT_NO_FATAL_FAILURE(
- updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR));
+ updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM));
}));
ModulePassManager MPM(/*DebugLogging*/ true);
if (C.getName() != "(f)")
return;
+ auto &FAM =
+ AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
Function *FnF = M->getFunction("f");
Function *FnH2 = M->getFunction("h2");
ASSERT_NE(FnF, nullptr);
auto &FN = *llvm::find_if(
C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
- ASSERT_DEATH(updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR),
- "Any new calls should be modeled as");
+ ASSERT_DEATH(
+ updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR, FAM),
+ "Any new calls should be modeled as");
}));
ModulePassManager MPM(/*DebugLogging*/ true);
if (C.getName() != "(f)")
return;
+ auto &FAM =
+ AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
Function *FnF = M->getFunction("f");
Function *FnewF = Function::Create(FnF->getFunctionType(),
FnF->getLinkage(), "newF", *M);
C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
ASSERT_NO_FATAL_FAILURE(
- updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR));
+ updateCGAndAnalysisManagerForCGSCCPass(CG, C, FN, AM, UR, FAM));
}));
ModulePassManager MPM(/*DebugLogging*/ true);
if (C.getName() != "(f)")
return;
+ auto &FAM =
+ AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
Function *FnF = M->getFunction("f");
Function *FnewF =
Function::Create(FnF->getFunctionType(), FnF->getLinkage(), "newF", *M);
auto &FN = *llvm::find_if(
C, [](LazyCallGraph::Node &N) { return N.getName() == "f"; });
- ASSERT_DEATH(updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR),
- "Any new calls should be modeled as");
+ ASSERT_DEATH(
+ updateCGAndAnalysisManagerForFunctionPass(CG, C, FN, AM, UR, FAM),
+ "Any new calls should be modeled as");
}));
ModulePassManager MPM(/*DebugLogging*/ true);
CGPM.addPass(LambdaSCCPassNoPreserve(
[&](LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
CGSCCUpdateResult &UR) {
+ auto &FAM =
+ AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
+
for (auto &N : C) {
auto &F = N.getFunction();
if (F.getName() != "f")
"f.ref", &*F.begin()->begin());
ASSERT_NO_FATAL_FAILURE(
- updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR))
+ updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR, FAM))
<< "Updating the call graph with a demoted, self-referential "
"call edge 'f -> f', and a newly inserted ref edge 'f -> g', "
"caused a fatal failure";
struct TestFunctionPass : PassInfoMixin<TestFunctionPass> {
TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
- int &AnalyzedFunctionCount,
+ int &AnalyzedFunctionCount, ModuleAnalysisManager &MAM,
bool OnlyUseCachedResults = false)
: RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
- AnalyzedFunctionCount(AnalyzedFunctionCount),
+ AnalyzedFunctionCount(AnalyzedFunctionCount), MAM(MAM),
OnlyUseCachedResults(OnlyUseCachedResults) {}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
++RunCount;
- const ModuleAnalysisManager &MAM =
- AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
+ // Getting a cached result that isn't stateless through the proxy will
+ // trigger an assert:
+ // auto &ModuleProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+ // Use MAM, for the purposes of this unittest.
if (TestModuleAnalysis::Result *TMA =
- MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()))
+ MAM.getCachedResult<TestModuleAnalysis>(*F.getParent())) {
AnalyzedFunctionCount += TMA->FunctionCount;
+ }
if (OnlyUseCachedResults) {
// Hack to force the use of the cached interface.
int &RunCount;
int &AnalyzedInstrCount;
int &AnalyzedFunctionCount;
+ ModuleAnalysisManager &MAM;
bool OnlyUseCachedResults;
};
{
// Pointless scope to test move assignment.
FunctionPassManager NestedFPM(/*DebugLogging*/ true);
- NestedFPM.addPass(TestFunctionPass(
- FunctionPassRunCount1, AnalyzedInstrCount1, AnalyzedFunctionCount1));
+ NestedFPM.addPass(TestFunctionPass(FunctionPassRunCount1,
+ AnalyzedInstrCount1,
+ AnalyzedFunctionCount1, MAM));
FPM = std::move(NestedFPM);
}
NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
{
FunctionPassManager FPM(/*DebugLogging*/ true);
FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
- AnalyzedFunctionCount2));
+ AnalyzedFunctionCount2, MAM));
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
}
{
FunctionPassManager FPM(/*DebugLogging*/ true);
FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
- AnalyzedFunctionCount3));
+ AnalyzedFunctionCount3, MAM));
FPM.addPass(TestInvalidationFunctionPass("f"));
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
}
{
FunctionPassManager FPM;
FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
- AnalyzedFunctionCount4));
+ AnalyzedFunctionCount4, MAM));
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
}
FunctionPassManager FPM(/*DebugLogging*/ true);
FPM.addPass(TestInvalidationFunctionPass("f"));
FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
- AnalyzedFunctionCount5,
+ AnalyzedFunctionCount5, MAM,
/*OnlyUseCachedResults=*/true));
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
}
}
};
- TestIndirectFunctionAnalysis(int &Runs) : Runs(Runs) {}
+ TestIndirectFunctionAnalysis(int &Runs, ModuleAnalysisManager &MAM)
+ : Runs(Runs), MAM(MAM) {}
/// Run the analysis pass over the function and return a result.
Result run(Function &F, FunctionAnalysisManager &AM) {
++Runs;
auto &FDep = AM.getResult<TestFunctionAnalysis>(F);
- auto &Proxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
- const ModuleAnalysisManager &MAM = Proxy.getManager();
+ auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
// For the test, we insist that the module analysis starts off in the
- // cache.
+ // cache. Getting a cached result that isn't stateless trigger an assert.
+ // Use MAM, for the purposes of this unittest.
auto &MDep = *MAM.getCachedResult<TestModuleAnalysis>(*F.getParent());
// And register the dependency as module analysis dependencies have to be
// pre-registered on the proxy.
- Proxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
- TestIndirectFunctionAnalysis>();
+ MAMProxy.registerOuterAnalysisInvalidation<TestModuleAnalysis,
+ TestIndirectFunctionAnalysis>();
return Result(FDep, MDep);
}
static AnalysisKey Key;
int &Runs;
+ ModuleAnalysisManager &MAM;
};
AnalysisKey TestIndirectFunctionAnalysis::Key;
TEST_F(PassManagerTest, IndirectAnalysisInvalidation) {
FunctionAnalysisManager FAM(/*DebugLogging*/ true);
+ ModuleAnalysisManager MAM(/*DebugLogging*/ true);
int FunctionAnalysisRuns = 0, ModuleAnalysisRuns = 0,
IndirectAnalysisRuns = 0, DoublyIndirectAnalysisRuns = 0;
FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
FAM.registerPass(
- [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns); });
+ [&] { return TestIndirectFunctionAnalysis(IndirectAnalysisRuns, MAM); });
FAM.registerPass([&] {
return TestDoublyIndirectFunctionAnalysis(DoublyIndirectAnalysisRuns);
});
- ModuleAnalysisManager MAM(/*DebugLogging*/ true);
MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
.WillByDefault(Invoke([&](Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR) {
auto &FAMP = AM.getResult<FunctionAnalysisManagerLoopProxy>(L, AR);
- auto &FAM = FAMP.getManager();
Function &F = *L.getHeader()->getParent();
- if (FAM.getCachedResult<FunctionAnalysis>(F))
+ // This call will assert when trying to get the actual analysis if the
+ // FunctionAnalysis can be invalidated. Only check its existence.
+ // Alternatively, use FAM above, for the purposes of this unittest.
+ if (FAMP.cachedResultExists<FunctionAnalysis>(F))
FAMP.registerOuterAnalysisInvalidation<FunctionAnalysis,
LoopAnalysis>();
return MLAHandle.getResult();