1313//
1414// ===----------------------------------------------------------------------===//
1515
16- #include " polly/LinkAllPasses .h"
16+ #include " polly/ScopInliner .h"
1717#include " polly/ScopDetection.h"
18+ #include " polly/ScopInliner.h"
1819#include " llvm/Analysis/CallGraph.h"
1920#include " llvm/Analysis/CallGraphSCCPass.h"
21+ #include " llvm/Analysis/OptimizationRemarkEmitter.h"
22+ #include " llvm/Analysis/RegionInfo.h"
23+ #include " llvm/IR/Dominators.h"
2024#include " llvm/IR/PassManager.h"
2125#include " llvm/Passes/PassBuilder.h"
2226#include " llvm/Transforms/IPO/AlwaysInliner.h"
@@ -28,13 +32,77 @@ using namespace llvm;
2832using namespace polly ;
2933
3034namespace {
31- class ScopInliner final : public CallGraphSCCPass {
35+
36+ // / Inliner implementation that works with both, LPM (using SCC_t=CallGraph) and
37+ // / NPM (using SCC_t=LazyCallGraph::SCC)
38+ template <typename SCC_t> bool runScopInlinerImpl (Function *F, SCC_t &SCC) {
39+ // We do not try to inline non-trivial SCCs because this would lead to
40+ // "infinite" inlining if we are not careful.
41+ if (SCC.size () > 1 )
42+ return false ;
43+ assert (SCC.size () == 1 && " found empty SCC" );
44+
45+ // If the function is a nullptr, or the function is a declaration.
46+ if (!F)
47+ return false ;
48+ if (F->isDeclaration ()) {
49+ POLLY_DEBUG (dbgs () << " Skipping " << F->getName ()
50+ << " because it is a declaration.\n " );
51+ return false ;
52+ }
53+
54+ PassBuilder PB;
55+ // Populate analysis managers and register Polly-specific analyses.
56+ LoopAnalysisManager LAM;
57+ FunctionAnalysisManager FAM;
58+ CGSCCAnalysisManager CGAM;
59+ ModuleAnalysisManager MAM;
60+ PB.registerModuleAnalyses (MAM);
61+ PB.registerCGSCCAnalyses (CGAM);
62+ PB.registerFunctionAnalyses (FAM);
63+ PB.registerLoopAnalyses (LAM);
64+ PB.crossRegisterProxies (LAM, FAM, CGAM, MAM);
65+
66+ auto &DT = FAM.getResult <DominatorTreeAnalysis>(*F);
67+ auto &SE = FAM.getResult <ScalarEvolutionAnalysis>(*F);
68+ auto &LI = FAM.getResult <LoopAnalysis>(*F);
69+ auto &RI = FAM.getResult <RegionInfoAnalysis>(*F);
70+ auto &AA = FAM.getResult <AAManager>(*F);
71+ auto &ORE = FAM.getResult <OptimizationRemarkEmitterAnalysis>(*F);
72+ ScopDetection SD (DT, SE, LI, RI, AA, ORE);
73+ SD.detect (*F);
74+
75+ const bool HasScopAsTopLevelRegion =
76+ SD.ValidRegions .contains (RI.getTopLevelRegion ());
77+
78+ bool Changed = false ;
79+ if (HasScopAsTopLevelRegion) {
80+ POLLY_DEBUG (dbgs () << " Skipping " << F->getName ()
81+ << " has scop as top level region" );
82+ F->addFnAttr (llvm::Attribute::AlwaysInline);
83+
84+ ModulePassManager MPM;
85+ MPM.addPass (AlwaysInlinerPass ());
86+ Module *M = F->getParent ();
87+ assert (M && " Function has illegal module" );
88+ PreservedAnalyses PA = MPM.run (*M, MAM);
89+ if (!PA.areAllPreserved ())
90+ Changed = true ;
91+ } else {
92+ POLLY_DEBUG (dbgs () << F->getName ()
93+ << " does NOT have scop as top level region\n " );
94+ }
95+
96+ return Changed;
97+ }
98+
99+ class ScopInlinerWrapperPass final : public CallGraphSCCPass {
32100 using llvm::Pass::doInitialization;
33101
34102public:
35103 static char ID;
36104
37- ScopInliner () : CallGraphSCCPass(ID) {}
105+ ScopInlinerWrapperPass () : CallGraphSCCPass(ID) {}
38106
39107 bool doInitialization (CallGraph &CG) override {
40108 if (!polly::PollyAllowFullFunction) {
@@ -50,79 +118,48 @@ class ScopInliner final : public CallGraphSCCPass {
50118 }
51119
52120 bool runOnSCC (CallGraphSCC &SCC) override {
53- // We do not try to inline non-trivial SCCs because this would lead to
54- // "infinite" inlining if we are not careful.
55- if (SCC.size () > 1 )
56- return false ;
57- assert (SCC.size () == 1 && " found empty SCC" );
58121 Function *F = (*SCC.begin ())->getFunction ();
59-
60- // If the function is a nullptr, or the function is a declaration.
61- if (!F)
62- return false ;
63- if (F->isDeclaration ()) {
64- POLLY_DEBUG (dbgs () << " Skipping " << F->getName ()
65- << " because it is a declaration.\n " );
66- return false ;
67- }
68-
69- PassBuilder PB;
70- // Populate analysis managers and register Polly-specific analyses.
71- LoopAnalysisManager LAM;
72- FunctionAnalysisManager FAM;
73- CGSCCAnalysisManager CGAM;
74- ModuleAnalysisManager MAM;
75- FAM.registerPass ([] { return ScopAnalysis (); });
76- PB.registerModuleAnalyses (MAM);
77- PB.registerCGSCCAnalyses (CGAM);
78- PB.registerFunctionAnalyses (FAM);
79- PB.registerLoopAnalyses (LAM);
80- PB.crossRegisterProxies (LAM, FAM, CGAM, MAM);
81-
82- RegionInfo &RI = FAM.getResult <RegionInfoAnalysis>(*F);
83- ScopDetection &SD = FAM.getResult <ScopAnalysis>(*F);
84-
85- const bool HasScopAsTopLevelRegion =
86- SD.ValidRegions .contains (RI.getTopLevelRegion ());
87-
88- bool Changed = false ;
89- if (HasScopAsTopLevelRegion) {
90- POLLY_DEBUG (dbgs () << " Skipping " << F->getName ()
91- << " has scop as top level region" );
92- F->addFnAttr (llvm::Attribute::AlwaysInline);
93-
94- ModulePassManager MPM;
95- MPM.addPass (AlwaysInlinerPass ());
96- Module *M = F->getParent ();
97- assert (M && " Function has illegal module" );
98- PreservedAnalyses PA = MPM.run (*M, MAM);
99- if (!PA.areAllPreserved ())
100- Changed = true ;
101- } else {
102- POLLY_DEBUG (dbgs () << F->getName ()
103- << " does NOT have scop as top level region\n " );
104- }
105-
106- return Changed;
122+ return runScopInlinerImpl (F, SCC);
107123 };
108124
109125 void getAnalysisUsage (AnalysisUsage &AU) const override {
110126 CallGraphSCCPass::getAnalysisUsage (AU);
111127 }
112128};
113129} // namespace
114- char ScopInliner ::ID;
130+ char ScopInlinerWrapperPass ::ID;
115131
116- Pass *polly::createScopInlinerPass () {
117- ScopInliner *pass = new ScopInliner ();
132+ Pass *polly::createScopInlinerWrapperPass () {
133+ ScopInlinerWrapperPass *pass = new ScopInlinerWrapperPass ();
118134 return pass;
119135}
120136
121137INITIALIZE_PASS_BEGIN (
122- ScopInliner , " polly-scop-inliner" ,
138+ ScopInlinerWrapperPass , " polly-scop-inliner" ,
123139 " inline functions based on how much of the function is a scop." , false ,
124140 false )
125141INITIALIZE_PASS_END(
126- ScopInliner , " polly-scop-inliner" ,
142+ ScopInlinerWrapperPass , " polly-scop-inliner" ,
127143 " inline functions based on how much of the function is a scop." , false ,
128144 false )
145+
146+ polly::ScopInlinerPass::ScopInlinerPass() {
147+ if (!polly::PollyAllowFullFunction) {
148+ report_fatal_error (
149+ " Aborting from ScopInliner because it only makes sense to run with "
150+ " -polly-allow-full-function. "
151+ " The heurtistic for ScopInliner checks that the full function is a "
152+ " Scop, which happens if and only if polly-allow-full-function is "
153+ " enabled. "
154+ " If not, the entry block is not included in the Scop" );
155+ }
156+ }
157+
158+ PreservedAnalyses polly::ScopInlinerPass::run (llvm::LazyCallGraph::SCC &SCC,
159+ llvm::CGSCCAnalysisManager &AM,
160+ llvm::LazyCallGraph &CG,
161+ llvm::CGSCCUpdateResult &UR) {
162+ Function *F = &SCC.begin ()->getFunction ();
163+ bool Changed = runScopInlinerImpl (F, SCC);
164+ return Changed ? PreservedAnalyses::none () : PreservedAnalyses::all ();
165+ }
0 commit comments