llvm-project/polly/lib/Analysis/ScopPass.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

170 lines
5.5 KiB
C++
Raw Normal View History

//===- ScopPass.cpp - The base class of Passes that operate on Polly IR ---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the definitions of the ScopPass members.
//
//===----------------------------------------------------------------------===//
#include "polly/ScopPass.h"
#include "polly/ScopInfo.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/GlobalsModRef.h"
Make dependency between certain analysis passes transitive (reapply) LazyBlockFrequenceInfoPass, LazyBranchProbabilityInfoPass and LoopAccessLegacyAnalysis all cache pointers to their nestled required analysis passes. One need to use addRequiredTransitive to describe that the nestled passes can't be freed until those analysis passes no longer are used themselves. There is still a bit of a mess considering the getLazyBPIAnalysisUsage and getLazyBFIAnalysisUsage functions. Those functions are used from both Transform, CodeGen and Analysis passes. I figure it is OK to use addRequiredTransitive also when being used from Transform and CodeGen passes. On the other hand, I figure we must do it when used from other Analysis passes. So using addRequiredTransitive should be more correct here. An alternative solution would be to add a bool option in those functions to let the user tell if it is a analysis pass or not. Since those lazy passes will be obsolete when new PM has conquered the world I figure we can leave it like this right now. Intention with the patch is to fix PR49950. It at least solves the problem for the reproducer in PR49950. However, that reproducer need five passes in a specific order, so there are lots of various "solutions" that could avoid the crash without actually fixing the root cause. This is a reapply of commit 3655f0757f2b4b, that was reverted in 33ff3c20498ef5c2057 due to problems with assertions in the polly lit tests. That problem is supposed to be solved by also adjusting ScopPass to explicitly preserve LazyBlockFrequencyInfo and LazyBranchProbabilityInfo (it already preserved OptimizationRemarkEmitter which depends on those lazy passes). Differential Revision: https://reviews.llvm.org/D100958
2021-05-05 01:08:58 +08:00
#include "llvm/Analysis/LazyBlockFrequencyInfo.h"
#include "llvm/Analysis/LazyBranchProbabilityInfo.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>();
Make dependency between certain analysis passes transitive (reapply) LazyBlockFrequenceInfoPass, LazyBranchProbabilityInfoPass and LoopAccessLegacyAnalysis all cache pointers to their nestled required analysis passes. One need to use addRequiredTransitive to describe that the nestled passes can't be freed until those analysis passes no longer are used themselves. There is still a bit of a mess considering the getLazyBPIAnalysisUsage and getLazyBFIAnalysisUsage functions. Those functions are used from both Transform, CodeGen and Analysis passes. I figure it is OK to use addRequiredTransitive also when being used from Transform and CodeGen passes. On the other hand, I figure we must do it when used from other Analysis passes. So using addRequiredTransitive should be more correct here. An alternative solution would be to add a bool option in those functions to let the user tell if it is a analysis pass or not. Since those lazy passes will be obsolete when new PM has conquered the world I figure we can leave it like this right now. Intention with the patch is to fix PR49950. It at least solves the problem for the reproducer in PR49950. However, that reproducer need five passes in a specific order, so there are lots of various "solutions" that could avoid the crash without actually fixing the root cause. This is a reapply of commit 3655f0757f2b4b, that was reverted in 33ff3c20498ef5c2057 due to problems with assertions in the polly lit tests. That problem is supposed to be solved by also adjusting ScopPass to explicitly preserve LazyBlockFrequencyInfo and LazyBranchProbabilityInfo (it already preserved OptimizationRemarkEmitter which depends on those lazy passes). Differential Revision: https://reviews.llvm.org/D100958
2021-05-05 01:08:58 +08:00
AU.addPreserved<LazyBlockFrequencyInfoPass>();
AU.addPreserved<LazyBranchProbabilityInfoPass>();
AU.addPreserved<RegionInfoPass>();
AU.addPreserved<ScopInfoRegionPass>();
AU.addPreserved<TargetTransformInfoWrapperPass>();
}
namespace polly {
[Polly][PM][WIP] Polly pass registration Summary: This patch is a first attempt at registering Polly passes with the LLVM tools. Tool plugins are still unsupported, but this registration is usable from the tools if Polly is linked into them (albeit requiring minimal patches to those tools). Registration requires a small amount of machinery (the owning analysis proxies), necessary for injecting ScopAnalysisManager objects into the calling tools. This patch is marked WIP because the registration is incomplete. Parsing manual pipelines is fully supported, but default pass injection into the O3 pipeline is lacking, mostly because there is opportunity for some redesign here, I believe. The first point of order would be insertion points. I think it makes sense to run before the vectorizers. Running Polly Early, however, is weird. Mostly because it actually is the default (which to me is unexpected), and because Polly runs it's own O1 pipeline. Why not instead insert it at an appropriate place somewhere after simplification happend? Running after the loop optimizers seems intuitive, but it also seems wasteful, since multiple consecutive loops might well be a single scop, and we don't need to run for all of them. My second request for comments would be regarding all those smallish helper passes we have, like PollyViewer, PollyPrinter, PollyImportJScop. Right now these are controlled by command line options, deciding whether they should be part of the Polly pipeline. What is your opinion on treating them like real passes, and have the user write an appropriate pipeline if they want to use any of them? Reviewers: grosser, Meinersbur, bollu Reviewed By: grosser Subscribers: llvm-commits, pollydev Tags: #polly Differential Revision: https://reviews.llvm.org/D35458 llvm-svn: 309826
2017-08-02 23:52:25 +08:00
template class OwningInnerAnalysisManagerProxy<ScopAnalysisManager, Function>;
}
[Polly][PM][WIP] Polly pass registration Summary: This patch is a first attempt at registering Polly passes with the LLVM tools. Tool plugins are still unsupported, but this registration is usable from the tools if Polly is linked into them (albeit requiring minimal patches to those tools). Registration requires a small amount of machinery (the owning analysis proxies), necessary for injecting ScopAnalysisManager objects into the calling tools. This patch is marked WIP because the registration is incomplete. Parsing manual pipelines is fully supported, but default pass injection into the O3 pipeline is lacking, mostly because there is opportunity for some redesign here, I believe. The first point of order would be insertion points. I think it makes sense to run before the vectorizers. Running Polly Early, however, is weird. Mostly because it actually is the default (which to me is unexpected), and because Polly runs it's own O1 pipeline. Why not instead insert it at an appropriate place somewhere after simplification happend? Running after the loop optimizers seems intuitive, but it also seems wasteful, since multiple consecutive loops might well be a single scop, and we don't need to run for all of them. My second request for comments would be regarding all those smallish helper passes we have, like PollyViewer, PollyPrinter, PollyImportJScop. Right now these are controlled by command line options, deciding whether they should be part of the Polly pipeline. What is your opinion on treating them like real passes, and have the user write an appropriate pipeline if they want to use any of them? Reviewers: grosser, Meinersbur, bollu Reviewed By: grosser Subscribers: llvm-commits, pollydev Tags: #polly Differential Revision: https://reviews.llvm.org/D35458 llvm-svn: 309826
2017-08-02 23:52:25 +08:00
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