This patch adds both a ScopAnalysisManager and a ScopPassManager. The ScopAnalysisManager is itself a Function-Analysis, and manages analyses on Scops. The ScopPassManager takes care of building Scop pass pipelines. This patch is marked WIP because I've left two FIXMEs which I need to think about some more. Both of these deal with invalidation: Deferred invalidation is currently not implemented. Deferred invalidation deals with analyses which cache references to other analysis results. If these results are invalidated, invalidation needs to be propagated into the caching analyses. The ScopPassManager as implemented assumes that ScopPasses do not affect other Scops in any way. There has been some discussion about this on other patch threads, however it makes sense to reiterate this for this specific patch. I'm uploading this patch even though it's incomplete to encourage discussion and give you an impression of how this is going to work. Differential Revision: https://reviews.llvm.org/D33192 llvm-svn: 303062
138 lines
4.2 KiB
C++
138 lines
4.2 KiB
C++
//===- ScopPass.cpp - The base class of Passes that operate on Polly IR ---===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains the definitions of the ScopPass members.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "polly/ScopPass.h"
|
|
#include "polly/ScopInfo.h"
|
|
|
|
#include "llvm/Analysis/AssumptionCache.h"
|
|
|
|
using namespace llvm;
|
|
using namespace polly;
|
|
|
|
bool ScopPass::runOnRegion(Region *R, RGPassManager &RGM) {
|
|
S = nullptr;
|
|
|
|
if ((S = getAnalysis<ScopInfoRegionPass>().getScop()))
|
|
return runOnScop(*S);
|
|
|
|
return false;
|
|
}
|
|
|
|
void ScopPass::print(raw_ostream &OS, const Module *M) const {
|
|
if (S)
|
|
printScop(OS, *S);
|
|
}
|
|
|
|
void ScopPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
AU.addRequired<ScopInfoRegionPass>();
|
|
AU.setPreservesAll();
|
|
}
|
|
|
|
namespace llvm {
|
|
|
|
template class PassManager<Scop, ScopAnalysisManager,
|
|
ScopStandardAnalysisResults &, SPMUpdater &>;
|
|
template class InnerAnalysisManagerProxy<ScopAnalysisManager, Function>;
|
|
template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Scop,
|
|
ScopStandardAnalysisResults &>;
|
|
|
|
template <>
|
|
PreservedAnalyses
|
|
PassManager<Scop, ScopAnalysisManager, ScopStandardAnalysisResults &,
|
|
SPMUpdater &>::run(Scop &S, ScopAnalysisManager &AM,
|
|
ScopStandardAnalysisResults &AR, SPMUpdater &U) {
|
|
auto PA = PreservedAnalyses::all();
|
|
for (auto &Pass : Passes) {
|
|
auto PassPA = Pass->run(S, AM, AR, U);
|
|
|
|
AM.invalidate(S, PassPA);
|
|
PA.intersect(std::move(PassPA));
|
|
}
|
|
|
|
// All analyses for 'this' Scop have been invalidated above.
|
|
// If ScopPasses affect break other scops they have to propagate this
|
|
// information through the updater
|
|
PA.preserveSet<AllAnalysesOn<Scop>>();
|
|
return PA;
|
|
}
|
|
|
|
bool ScopAnalysisManagerFunctionProxy::Result::invalidate(
|
|
Function &F, const PreservedAnalyses &PA,
|
|
FunctionAnalysisManager::Invalidator &Inv) {
|
|
|
|
// First, check whether our ScopInfo is about to be invalidated
|
|
auto PAC = PA.getChecker<ScopAnalysisManagerFunctionProxy>();
|
|
if (!(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>() ||
|
|
Inv.invalidate<ScopAnalysis>(F, PA) ||
|
|
Inv.invalidate<ScalarEvolutionAnalysis>(F, PA) ||
|
|
Inv.invalidate<LoopAnalysis>(F, PA) ||
|
|
Inv.invalidate<AAManager>(F, PA) ||
|
|
Inv.invalidate<DominatorTreeAnalysis>(F, PA) ||
|
|
Inv.invalidate<AssumptionAnalysis>(F, PA))) {
|
|
|
|
// As everything depends on ScopInfo, we must drop all existing results
|
|
for (auto &S : *SI)
|
|
if (auto *scop = S.second.get())
|
|
if (InnerAM)
|
|
InnerAM->clear(*scop);
|
|
|
|
InnerAM = nullptr;
|
|
return true; // Invalidate the proxy result as well.
|
|
}
|
|
|
|
bool allPreserved = PA.allAnalysesInSetPreserved<AllAnalysesOn<Scop>>();
|
|
|
|
// Invalidate all non-preserved analyses
|
|
// Even if all analyses were preserved, we still need to run deferred
|
|
// invalidation
|
|
for (auto &S : *SI) {
|
|
Optional<PreservedAnalyses> InnerPA;
|
|
auto *scop = S.second.get();
|
|
if (!scop)
|
|
continue;
|
|
|
|
if (auto *OuterProxy =
|
|
InnerAM->getCachedResult<FunctionAnalysisManagerScopProxy>(*scop)) {
|
|
for (const auto &InvPair : OuterProxy->getOuterInvalidations()) {
|
|
auto *OuterAnalysisID = InvPair.first;
|
|
const auto &InnerAnalysisIDs = InvPair.second;
|
|
|
|
if (Inv.invalidate(OuterAnalysisID, F, PA)) {
|
|
if (!InnerPA)
|
|
InnerPA = PA;
|
|
for (auto *InnerAnalysisID : InnerAnalysisIDs)
|
|
InnerPA->abandon(InnerAnalysisID);
|
|
}
|
|
}
|
|
|
|
if (InnerPA) {
|
|
InnerAM->invalidate(*scop, *InnerPA);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (!allPreserved)
|
|
InnerAM->invalidate(*scop, PA);
|
|
}
|
|
|
|
return false; // This proxy is still valid
|
|
}
|
|
|
|
template <>
|
|
ScopAnalysisManagerFunctionProxy::Result
|
|
ScopAnalysisManagerFunctionProxy::run(Function &F,
|
|
FunctionAnalysisManager &FAM) {
|
|
return Result(*InnerAM, FAM.getResult<ScopInfoAnalysis>(F));
|
|
}
|
|
} // namespace llvm
|