Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,163 @@
//===--------- PolyhedralInfo.cpp - Create Scops from LLVM IR-------------===//
///
/// The LLVM Compiler Infrastructure
///
/// This file is distributed under the University of Illinois Open Source
/// License. See LICENSE.TXT for details.
///
//===----------------------------------------------------------------------===//
///
/// An interface to the Polyhedral analysis engine(Polly) of LLVM.
///
/// This pass provides an interface to the polyhedral analysis performed by
/// Polly.
///
/// This interface provides basic interface like isParallel, isVectorizable
/// that can be used in LLVM transformation passes.
///
/// Work in progress, this file is subject to change.
//===----------------------------------------------------------------------===//
#include "polly/PolyhedralInfo.h"
#include "polly/DependenceInfo.h"
#include "polly/LinkAllPasses.h"
#include "polly/Options.h"
#include "polly/ScopInfo.h"
#include "polly/Support/GICHelper.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Support/Debug.h"
#include <isl/map.h>
#include <isl/union_map.h>
using namespace llvm;
using namespace polly;
#define DEBUG_TYPE "polyhedral-info"
static cl::opt<bool> CheckParallel("polly-check-parallel",
cl::desc("Check for parallel loops"),
cl::Hidden, cl::init(false), cl::ZeroOrMore,
cl::cat(PollyCategory));
static cl::opt<bool> CheckVectorizable("polly-check-vectorizable",
cl::desc("Check for vectorizable loops"),
cl::Hidden, cl::init(false),
cl::ZeroOrMore, cl::cat(PollyCategory));
void PolyhedralInfo::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequiredTransitive<DependenceInfoWrapperPass>();
AU.addRequired<LoopInfoWrapperPass>();
AU.addRequiredTransitive<ScopInfoWrapperPass>();
AU.setPreservesAll();
}
bool PolyhedralInfo::runOnFunction(Function &F) {
DI = &getAnalysis<DependenceInfoWrapperPass>();
SI = getAnalysis<ScopInfoWrapperPass>().getSI();
return false;
}
void PolyhedralInfo::print(raw_ostream &OS, const Module *) const {
auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
for (auto *TopLevelLoop : LI) {
for (auto *L : depth_first(TopLevelLoop)) {
OS.indent(2) << L->getHeader()->getName() << ":\t";
if (CheckParallel && isParallel(L))
OS << "Loop is parallel.\n";
else if (CheckParallel)
OS << "Loop is not parallel.\n";
}
}
}
bool PolyhedralInfo::checkParallel(Loop *L, isl_pw_aff **MinDepDistPtr) const {
bool IsParallel;
const Scop *S = getScopContainingLoop(L);
if (!S)
return false;
const Dependences &D =
DI->getDependences(const_cast<Scop *>(S), Dependences::AL_Access);
if (!D.hasValidDependences())
return false;
DEBUG(dbgs() << "Loop :\t" << L->getHeader()->getName() << ":\n");
isl_union_map *Deps =
D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_WAW |
Dependences::TYPE_WAR | Dependences::TYPE_RED);
DEBUG(dbgs() << "Dependences :\t" << stringFromIslObj(Deps) << "\n");
isl_union_map *Schedule = getScheduleForLoop(S, L);
DEBUG(dbgs() << "Schedule: \t" << stringFromIslObj(Schedule) << "\n");
IsParallel = D.isParallel(Schedule, Deps, MinDepDistPtr);
isl_union_map_free(Schedule);
return IsParallel;
}
bool PolyhedralInfo::isParallel(Loop *L) const { return checkParallel(L); }
const Scop *PolyhedralInfo::getScopContainingLoop(Loop *L) const {
assert((SI) && "ScopInfoWrapperPass is required by PolyhedralInfo pass!\n");
for (auto &It : *SI) {
Region *R = It.first;
if (R->contains(L))
return It.second.get();
}
return nullptr;
}
// Given a Loop and the containing SCoP, we compute the partial schedule
// by taking union of individual schedules of each ScopStmt within the loop
// and projecting out the inner dimensions from the range of the schedule.
// for (i = 0; i < n; i++)
// for (j = 0; j < n; j++)
// A[j] = 1; //Stmt
//
// The original schedule will be
// Stmt[i0, i1] -> [i0, i1]
// The schedule for the outer loop will be
// Stmt[i0, i1] -> [i0]
// The schedule for the inner loop will be
// Stmt[i0, i1] -> [i0, i1]
__isl_give isl_union_map *PolyhedralInfo::getScheduleForLoop(const Scop *S,
Loop *L) const {
isl_union_map *Schedule = isl_union_map_empty(S->getParamSpace().release());
int CurrDim = S->getRelativeLoopDepth(L);
DEBUG(dbgs() << "Relative loop depth:\t" << CurrDim << "\n");
assert(CurrDim >= 0 && "Loop in region should have at least depth one");
for (auto &SS : *S) {
if (L->contains(SS.getSurroundingLoop())) {
unsigned int MaxDim = SS.getNumIterators();
DEBUG(dbgs() << "Maximum depth of Stmt:\t" << MaxDim << "\n");
isl_map *ScheduleMap = SS.getSchedule().release();
assert(
ScheduleMap &&
"Schedules that contain extension nodes require special handling.");
ScheduleMap = isl_map_project_out(ScheduleMap, isl_dim_out, CurrDim + 1,
MaxDim - CurrDim - 1);
ScheduleMap = isl_map_set_tuple_id(ScheduleMap, isl_dim_in,
SS.getDomainId().release());
Schedule =
isl_union_map_union(Schedule, isl_union_map_from_map(ScheduleMap));
}
}
Schedule = isl_union_map_coalesce(Schedule);
return Schedule;
}
char PolyhedralInfo::ID = 0;
Pass *polly::createPolyhedralInfoPass() { return new PolyhedralInfo(); }
INITIALIZE_PASS_BEGIN(PolyhedralInfo, "polyhedral-info",
"Polly - Interface to polyhedral analysis engine", false,
false);
INITIALIZE_PASS_DEPENDENCY(DependenceInfoWrapperPass);
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
INITIALIZE_PASS_DEPENDENCY(ScopInfoWrapperPass);
INITIALIZE_PASS_END(PolyhedralInfo, "polyhedral-info",
"Polly - Interface to polyhedral analysis engine", false,
false)

View File

@@ -0,0 +1,105 @@
//===- PruneUnprofitable.cpp ----------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Mark a SCoP as unfeasible if not deemed profitable to optimize.
//
//===----------------------------------------------------------------------===//
#include "polly/PruneUnprofitable.h"
#include "polly/ScopDetection.h"
#include "polly/ScopInfo.h"
#include "polly/ScopPass.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace polly;
#define DEBUG_TYPE "polly-prune-unprofitable"
namespace {
STATISTIC(ScopsProcessed,
"Number of SCoPs considered for unprofitability pruning");
STATISTIC(ScopsPruned, "Number of pruned SCoPs because it they cannot be "
"optimized in a significant way");
STATISTIC(ScopsSurvived, "Number of SCoPs after pruning");
STATISTIC(NumPrunedLoops, "Number of pruned loops");
STATISTIC(NumPrunedBoxedLoops, "Number of pruned boxed loops");
STATISTIC(NumPrunedAffineLoops, "Number of pruned affine loops");
STATISTIC(NumLoopsInScop, "Number of loops in scops after pruning");
STATISTIC(NumBoxedLoops, "Number of boxed loops in SCoPs after pruning");
STATISTIC(NumAffineLoops, "Number of affine loops in SCoPs after pruning");
class PruneUnprofitable : public ScopPass {
private:
void updateStatistics(Scop &S, bool Pruned) {
auto ScopStats = S.getStatistics();
if (Pruned) {
ScopsPruned++;
NumPrunedLoops += ScopStats.NumAffineLoops + ScopStats.NumBoxedLoops;
NumPrunedBoxedLoops += ScopStats.NumBoxedLoops;
NumPrunedAffineLoops += ScopStats.NumAffineLoops;
} else {
ScopsSurvived++;
NumLoopsInScop += ScopStats.NumAffineLoops + ScopStats.NumBoxedLoops;
NumBoxedLoops += ScopStats.NumBoxedLoops;
NumAffineLoops += ScopStats.NumAffineLoops;
}
}
public:
static char ID;
explicit PruneUnprofitable() : ScopPass(ID) {}
PruneUnprofitable(const PruneUnprofitable &) = delete;
PruneUnprofitable &operator=(const PruneUnprofitable &) = delete;
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<ScopInfoRegionPass>();
AU.setPreservesAll();
}
bool runOnScop(Scop &S) override {
if (PollyProcessUnprofitable) {
DEBUG(dbgs() << "NOTE: -polly-process-unprofitable active, won't prune "
"anything\n");
return false;
}
ScopsProcessed++;
if (!S.isProfitable(true)) {
DEBUG(dbgs() << "SCoP pruned because it probably cannot be optimized in "
"a significant way\n");
S.invalidate(PROFITABLE, DebugLoc());
updateStatistics(S, true);
} else {
updateStatistics(S, false);
}
return false;
}
};
} // namespace
char PruneUnprofitable::ID;
Pass *polly::createPruneUnprofitablePass() { return new PruneUnprofitable(); }
INITIALIZE_PASS_BEGIN(PruneUnprofitable, "polly-prune-unprofitable",
"Polly - Prune unprofitable SCoPs", false, false)
INITIALIZE_PASS_END(PruneUnprofitable, "polly-prune-unprofitable",
"Polly - Prune unprofitable SCoPs", false, false)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,266 @@
//===- GraphPrinter.cpp - Create a DOT output describing the Scop. --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Create a DOT output describing the Scop.
//
// For each function a dot file is created that shows the control flow graph of
// the function and highlights the detected Scops.
//
//===----------------------------------------------------------------------===//
#include "polly/LinkAllPasses.h"
#include "polly/ScopDetection.h"
#include "polly/Support/ScopLocation.h"
#include "llvm/Analysis/DOTGraphTraitsPass.h"
#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Analysis/RegionIterator.h"
#include "llvm/Support/CommandLine.h"
using namespace polly;
using namespace llvm;
static cl::opt<std::string>
ViewFilter("polly-view-only",
cl::desc("Only view functions that match this pattern"),
cl::Hidden, cl::init(""), cl::ZeroOrMore);
static cl::opt<bool> ViewAll("polly-view-all",
cl::desc("Also show functions without any scops"),
cl::Hidden, cl::init(false), cl::ZeroOrMore);
namespace llvm {
template <>
struct GraphTraits<ScopDetection *> : public GraphTraits<RegionInfo *> {
static NodeRef getEntryNode(ScopDetection *SD) {
return GraphTraits<RegionInfo *>::getEntryNode(SD->getRI());
}
static nodes_iterator nodes_begin(ScopDetection *SD) {
return nodes_iterator::begin(getEntryNode(SD));
}
static nodes_iterator nodes_end(ScopDetection *SD) {
return nodes_iterator::end(getEntryNode(SD));
}
};
template <>
struct GraphTraits<ScopDetectionWrapperPass *>
: public GraphTraits<ScopDetection *> {
static NodeRef getEntryNode(ScopDetectionWrapperPass *P) {
return GraphTraits<ScopDetection *>::getEntryNode(&P->getSD());
}
static nodes_iterator nodes_begin(ScopDetectionWrapperPass *P) {
return nodes_iterator::begin(getEntryNode(P));
}
static nodes_iterator nodes_end(ScopDetectionWrapperPass *P) {
return nodes_iterator::end(getEntryNode(P));
}
};
template <> struct DOTGraphTraits<RegionNode *> : public DefaultDOTGraphTraits {
DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
std::string getNodeLabel(RegionNode *Node, RegionNode *Graph) {
if (!Node->isSubRegion()) {
BasicBlock *BB = Node->getNodeAs<BasicBlock>();
if (isSimple())
return DOTGraphTraits<const Function *>::getSimpleNodeLabel(
BB, BB->getParent());
else
return DOTGraphTraits<const Function *>::getCompleteNodeLabel(
BB, BB->getParent());
}
return "Not implemented";
}
};
template <>
struct DOTGraphTraits<ScopDetectionWrapperPass *>
: public DOTGraphTraits<RegionNode *> {
DOTGraphTraits(bool isSimple = false)
: DOTGraphTraits<RegionNode *>(isSimple) {}
static std::string getGraphName(ScopDetectionWrapperPass *SD) {
return "Scop Graph";
}
std::string getEdgeAttributes(RegionNode *srcNode,
GraphTraits<RegionInfo *>::ChildIteratorType CI,
ScopDetectionWrapperPass *P) {
RegionNode *destNode = *CI;
auto *SD = &P->getSD();
if (srcNode->isSubRegion() || destNode->isSubRegion())
return "";
// In case of a backedge, do not use it to define the layout of the nodes.
BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>();
BasicBlock *destBB = destNode->getNodeAs<BasicBlock>();
RegionInfo *RI = SD->getRI();
Region *R = RI->getRegionFor(destBB);
while (R && R->getParent())
if (R->getParent()->getEntry() == destBB)
R = R->getParent();
else
break;
if (R && R->getEntry() == destBB && R->contains(srcBB))
return "constraint=false";
return "";
}
std::string getNodeLabel(RegionNode *Node, ScopDetectionWrapperPass *P) {
return DOTGraphTraits<RegionNode *>::getNodeLabel(
Node, reinterpret_cast<RegionNode *>(
P->getSD().getRI()->getTopLevelRegion()));
}
static std::string escapeString(std::string String) {
std::string Escaped;
for (const auto &C : String) {
if (C == '"')
Escaped += '\\';
Escaped += C;
}
return Escaped;
}
// Print the cluster of the subregions. This groups the single basic blocks
// and adds a different background color for each group.
static void printRegionCluster(const ScopDetection *SD, const Region *R,
raw_ostream &O, unsigned depth = 0) {
O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void *>(R)
<< " {\n";
unsigned LineBegin, LineEnd;
std::string FileName;
getDebugLocation(R, LineBegin, LineEnd, FileName);
std::string Location;
if (LineBegin != (unsigned)-1) {
Location = escapeString(FileName + ":" + std::to_string(LineBegin) + "-" +
std::to_string(LineEnd) + "\n");
}
std::string ErrorMessage = SD->regionIsInvalidBecause(R);
ErrorMessage = escapeString(ErrorMessage);
O.indent(2 * (depth + 1))
<< "label = \"" << Location << ErrorMessage << "\";\n";
if (SD->isMaxRegionInScop(*R)) {
O.indent(2 * (depth + 1)) << "style = filled;\n";
// Set color to green.
O.indent(2 * (depth + 1)) << "color = 3";
} else {
O.indent(2 * (depth + 1)) << "style = solid;\n";
int color = (R->getDepth() * 2 % 12) + 1;
// We do not want green again.
if (color == 3)
color = 6;
O.indent(2 * (depth + 1)) << "color = " << color << "\n";
}
for (const auto &SubRegion : *R)
printRegionCluster(SD, SubRegion.get(), O, depth + 1);
RegionInfo *RI = R->getRegionInfo();
for (const auto &BB : R->blocks())
if (RI->getRegionFor(BB) == R)
O.indent(2 * (depth + 1))
<< "Node"
<< static_cast<void *>(RI->getTopLevelRegion()->getBBNode(BB))
<< ";\n";
O.indent(2 * depth) << "}\n";
}
static void
addCustomGraphFeatures(const ScopDetectionWrapperPass *SD,
GraphWriter<ScopDetectionWrapperPass *> &GW) {
raw_ostream &O = GW.getOStream();
O << "\tcolorscheme = \"paired12\"\n";
printRegionCluster(&SD->getSD(), SD->getSD().getRI()->getTopLevelRegion(),
O, 4);
}
};
} // end namespace llvm
struct ScopViewer
: public DOTGraphTraitsViewer<ScopDetectionWrapperPass, false> {
static char ID;
ScopViewer()
: DOTGraphTraitsViewer<ScopDetectionWrapperPass, false>("scops", ID) {}
bool processFunction(Function &F, ScopDetectionWrapperPass &SD) override {
if (ViewFilter != "" && !F.getName().count(ViewFilter))
return false;
if (ViewAll)
return true;
// Check that at least one scop was detected.
return std::distance(SD.getSD().begin(), SD.getSD().end()) > 0;
}
};
char ScopViewer::ID = 0;
struct ScopOnlyViewer
: public DOTGraphTraitsViewer<ScopDetectionWrapperPass, true> {
static char ID;
ScopOnlyViewer()
: DOTGraphTraitsViewer<ScopDetectionWrapperPass, true>("scopsonly", ID) {}
};
char ScopOnlyViewer::ID = 0;
struct ScopPrinter
: public DOTGraphTraitsPrinter<ScopDetectionWrapperPass, false> {
static char ID;
ScopPrinter()
: DOTGraphTraitsPrinter<ScopDetectionWrapperPass, false>("scops", ID) {}
};
char ScopPrinter::ID = 0;
struct ScopOnlyPrinter
: public DOTGraphTraitsPrinter<ScopDetectionWrapperPass, true> {
static char ID;
ScopOnlyPrinter()
: DOTGraphTraitsPrinter<ScopDetectionWrapperPass, true>("scopsonly", ID) {
}
};
char ScopOnlyPrinter::ID = 0;
static RegisterPass<ScopViewer> X("view-scops",
"Polly - View Scops of function");
static RegisterPass<ScopOnlyViewer>
Y("view-scops-only",
"Polly - View Scops of function (with no function bodies)");
static RegisterPass<ScopPrinter> M("dot-scops",
"Polly - Print Scops of function");
static RegisterPass<ScopOnlyPrinter>
N("dot-scops-only",
"Polly - Print Scops of function (with no function bodies)");
Pass *polly::createDOTViewerPass() { return new ScopViewer(); }
Pass *polly::createDOTOnlyViewerPass() { return new ScopOnlyViewer(); }
Pass *polly::createDOTPrinterPass() { return new ScopPrinter(); }
Pass *polly::createDOTOnlyPrinterPass() { return new ScopOnlyPrinter(); }

View File

@@ -0,0 +1 @@
d2bc71fb6d527df34b7d2041bf88e426996a13c6

View File

@@ -0,0 +1,168 @@
//===- 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"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
#include "llvm/Analysis/TargetTransformInfo.h"
using namespace llvm;
using namespace polly;
bool ScopPass::runOnRegion(Region *R, RGPassManager &RGM) {
S = nullptr;
if (skipRegion(*R))
return false;
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.addPreserved<AAResultsWrapperPass>();
AU.addPreserved<BasicAAWrapperPass>();
AU.addPreserved<LoopInfoWrapperPass>();
AU.addPreserved<DominatorTreeWrapperPass>();
AU.addPreserved<GlobalsAAWrapperPass>();
AU.addPreserved<ScopDetectionWrapperPass>();
AU.addPreserved<ScalarEvolutionWrapperPass>();
AU.addPreserved<SCEVAAWrapperPass>();
AU.addPreserved<OptimizationRemarkEmitterWrapperPass>();
AU.addPreserved<RegionInfoPass>();
AU.addPreserved<ScopInfoRegionPass>();
AU.addPreserved<TargetTransformInfoWrapperPass>();
}
namespace polly {
template class OwningInnerAnalysisManagerProxy<ScopAnalysisManager, Function>;
}
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<ScopInfoAnalysis>(F, PA) ||
Inv.invalidate<ScalarEvolutionAnalysis>(F, PA) ||
Inv.invalidate<LoopAnalysis>(F, PA) ||
Inv.invalidate<DominatorTreeAnalysis>(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, scop->getName());
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
namespace polly {
template <>
OwningScopAnalysisManagerFunctionProxy::Result
OwningScopAnalysisManagerFunctionProxy::run(Function &F,
FunctionAnalysisManager &FAM) {
return Result(InnerAM, FAM.getResult<ScopInfoAnalysis>(F));
}
} // namespace polly