aboutsummaryrefslogtreecommitdiff
path: root/polly/lib/Transform
diff options
context:
space:
mode:
Diffstat (limited to 'polly/lib/Transform')
-rw-r--r--polly/lib/Transform/ScopInliner.cpp159
1 files changed, 98 insertions, 61 deletions
diff --git a/polly/lib/Transform/ScopInliner.cpp b/polly/lib/Transform/ScopInliner.cpp
index b78206c..c04ba34 100644
--- a/polly/lib/Transform/ScopInliner.cpp
+++ b/polly/lib/Transform/ScopInliner.cpp
@@ -13,10 +13,14 @@
//
//===----------------------------------------------------------------------===//
-#include "polly/LinkAllPasses.h"
+#include "polly/ScopInliner.h"
#include "polly/ScopDetection.h"
+#include "polly/ScopInliner.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
+#include "llvm/Analysis/OptimizationRemarkEmitter.h"
+#include "llvm/Analysis/RegionInfo.h"
+#include "llvm/IR/Dominators.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Transforms/IPO/AlwaysInliner.h"
@@ -28,13 +32,77 @@ using namespace llvm;
using namespace polly;
namespace {
-class ScopInliner final : public CallGraphSCCPass {
+
+/// Inliner implementation that works with both, LPM (using SCC_t=CallGraph) and
+/// NPM (using SCC_t=LazyCallGraph::SCC)
+template <typename SCC_t> bool runScopInlinerImpl(Function *F, SCC_t &SCC) {
+ // We do not try to inline non-trivial SCCs because this would lead to
+ // "infinite" inlining if we are not careful.
+ if (SCC.size() > 1)
+ return false;
+ assert(SCC.size() == 1 && "found empty SCC");
+
+ // If the function is a nullptr, or the function is a declaration.
+ if (!F)
+ return false;
+ if (F->isDeclaration()) {
+ POLLY_DEBUG(dbgs() << "Skipping " << F->getName()
+ << "because it is a declaration.\n");
+ return false;
+ }
+
+ PassBuilder PB;
+ // Populate analysis managers and register Polly-specific analyses.
+ LoopAnalysisManager LAM;
+ FunctionAnalysisManager FAM;
+ CGSCCAnalysisManager CGAM;
+ ModuleAnalysisManager MAM;
+ PB.registerModuleAnalyses(MAM);
+ PB.registerCGSCCAnalyses(CGAM);
+ PB.registerFunctionAnalyses(FAM);
+ PB.registerLoopAnalyses(LAM);
+ PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+ auto &DT = FAM.getResult<DominatorTreeAnalysis>(*F);
+ auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(*F);
+ auto &LI = FAM.getResult<LoopAnalysis>(*F);
+ auto &RI = FAM.getResult<RegionInfoAnalysis>(*F);
+ auto &AA = FAM.getResult<AAManager>(*F);
+ auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(*F);
+ ScopDetection SD(DT, SE, LI, RI, AA, ORE);
+ SD.detect(*F);
+
+ const bool HasScopAsTopLevelRegion =
+ SD.ValidRegions.contains(RI.getTopLevelRegion());
+
+ bool Changed = false;
+ if (HasScopAsTopLevelRegion) {
+ POLLY_DEBUG(dbgs() << "Skipping " << F->getName()
+ << " has scop as top level region");
+ F->addFnAttr(llvm::Attribute::AlwaysInline);
+
+ ModulePassManager MPM;
+ MPM.addPass(AlwaysInlinerPass());
+ Module *M = F->getParent();
+ assert(M && "Function has illegal module");
+ PreservedAnalyses PA = MPM.run(*M, MAM);
+ if (!PA.areAllPreserved())
+ Changed = true;
+ } else {
+ POLLY_DEBUG(dbgs() << F->getName()
+ << " does NOT have scop as top level region\n");
+ }
+
+ return Changed;
+}
+
+class ScopInlinerWrapperPass final : public CallGraphSCCPass {
using llvm::Pass::doInitialization;
public:
static char ID;
- ScopInliner() : CallGraphSCCPass(ID) {}
+ ScopInlinerWrapperPass() : CallGraphSCCPass(ID) {}
bool doInitialization(CallGraph &CG) override {
if (!polly::PollyAllowFullFunction) {
@@ -50,60 +118,8 @@ public:
}
bool runOnSCC(CallGraphSCC &SCC) override {
- // We do not try to inline non-trivial SCCs because this would lead to
- // "infinite" inlining if we are not careful.
- if (SCC.size() > 1)
- return false;
- assert(SCC.size() == 1 && "found empty SCC");
Function *F = (*SCC.begin())->getFunction();
-
- // If the function is a nullptr, or the function is a declaration.
- if (!F)
- return false;
- if (F->isDeclaration()) {
- POLLY_DEBUG(dbgs() << "Skipping " << F->getName()
- << "because it is a declaration.\n");
- return false;
- }
-
- PassBuilder PB;
- // Populate analysis managers and register Polly-specific analyses.
- LoopAnalysisManager LAM;
- FunctionAnalysisManager FAM;
- CGSCCAnalysisManager CGAM;
- ModuleAnalysisManager MAM;
- FAM.registerPass([] { return ScopAnalysis(); });
- PB.registerModuleAnalyses(MAM);
- PB.registerCGSCCAnalyses(CGAM);
- PB.registerFunctionAnalyses(FAM);
- PB.registerLoopAnalyses(LAM);
- PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
-
- RegionInfo &RI = FAM.getResult<RegionInfoAnalysis>(*F);
- ScopDetection &SD = FAM.getResult<ScopAnalysis>(*F);
-
- const bool HasScopAsTopLevelRegion =
- SD.ValidRegions.contains(RI.getTopLevelRegion());
-
- bool Changed = false;
- if (HasScopAsTopLevelRegion) {
- POLLY_DEBUG(dbgs() << "Skipping " << F->getName()
- << " has scop as top level region");
- F->addFnAttr(llvm::Attribute::AlwaysInline);
-
- ModulePassManager MPM;
- MPM.addPass(AlwaysInlinerPass());
- Module *M = F->getParent();
- assert(M && "Function has illegal module");
- PreservedAnalyses PA = MPM.run(*M, MAM);
- if (!PA.areAllPreserved())
- Changed = true;
- } else {
- POLLY_DEBUG(dbgs() << F->getName()
- << " does NOT have scop as top level region\n");
- }
-
- return Changed;
+ return runScopInlinerImpl(F, SCC);
};
void getAnalysisUsage(AnalysisUsage &AU) const override {
@@ -111,18 +127,39 @@ public:
}
};
} // namespace
-char ScopInliner::ID;
+char ScopInlinerWrapperPass::ID;
-Pass *polly::createScopInlinerPass() {
- ScopInliner *pass = new ScopInliner();
+Pass *polly::createScopInlinerWrapperPass() {
+ ScopInlinerWrapperPass *pass = new ScopInlinerWrapperPass();
return pass;
}
INITIALIZE_PASS_BEGIN(
- ScopInliner, "polly-scop-inliner",
+ ScopInlinerWrapperPass, "polly-scop-inliner",
"inline functions based on how much of the function is a scop.", false,
false)
INITIALIZE_PASS_END(
- ScopInliner, "polly-scop-inliner",
+ ScopInlinerWrapperPass, "polly-scop-inliner",
"inline functions based on how much of the function is a scop.", false,
false)
+
+polly::ScopInlinerPass::ScopInlinerPass() {
+ if (!polly::PollyAllowFullFunction) {
+ report_fatal_error(
+ "Aborting from ScopInliner because it only makes sense to run with "
+ "-polly-allow-full-function. "
+ "The heurtistic for ScopInliner checks that the full function is a "
+ "Scop, which happens if and only if polly-allow-full-function is "
+ " enabled. "
+ " If not, the entry block is not included in the Scop");
+ }
+}
+
+PreservedAnalyses polly::ScopInlinerPass::run(llvm::LazyCallGraph::SCC &SCC,
+ llvm::CGSCCAnalysisManager &AM,
+ llvm::LazyCallGraph &CG,
+ llvm::CGSCCUpdateResult &UR) {
+ Function *F = &SCC.begin()->getFunction();
+ bool Changed = runScopInlinerImpl(F, SCC);
+ return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
+}