13
13
//
14
14
// ===----------------------------------------------------------------------===//
15
15
16
- #include " polly/LinkAllPasses .h"
16
+ #include " polly/ScopInliner .h"
17
17
#include " polly/ScopDetection.h"
18
+ #include " polly/ScopInliner.h"
18
19
#include " llvm/Analysis/CallGraph.h"
19
20
#include " llvm/Analysis/CallGraphSCCPass.h"
21
+ #include " llvm/Analysis/OptimizationRemarkEmitter.h"
22
+ #include " llvm/Analysis/RegionInfo.h"
23
+ #include " llvm/IR/Dominators.h"
20
24
#include " llvm/IR/PassManager.h"
21
25
#include " llvm/Passes/PassBuilder.h"
22
26
#include " llvm/Transforms/IPO/AlwaysInliner.h"
@@ -28,13 +32,77 @@ using namespace llvm;
28
32
using namespace polly ;
29
33
30
34
namespace {
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 {
32
100
using llvm::Pass::doInitialization;
33
101
34
102
public:
35
103
static char ID;
36
104
37
- ScopInliner () : CallGraphSCCPass(ID) {}
105
+ ScopInlinerWrapperPass () : CallGraphSCCPass(ID) {}
38
106
39
107
bool doInitialization (CallGraph &CG) override {
40
108
if (!polly::PollyAllowFullFunction) {
@@ -50,79 +118,48 @@ class ScopInliner final : public CallGraphSCCPass {
50
118
}
51
119
52
120
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" );
58
121
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);
107
123
};
108
124
109
125
void getAnalysisUsage (AnalysisUsage &AU) const override {
110
126
CallGraphSCCPass::getAnalysisUsage (AU);
111
127
}
112
128
};
113
129
} // namespace
114
- char ScopInliner ::ID;
130
+ char ScopInlinerWrapperPass ::ID;
115
131
116
- Pass *polly::createScopInlinerPass () {
117
- ScopInliner *pass = new ScopInliner ();
132
+ Pass *polly::createScopInlinerWrapperPass () {
133
+ ScopInlinerWrapperPass *pass = new ScopInlinerWrapperPass ();
118
134
return pass;
119
135
}
120
136
121
137
INITIALIZE_PASS_BEGIN (
122
- ScopInliner , " polly-scop-inliner" ,
138
+ ScopInlinerWrapperPass , " polly-scop-inliner" ,
123
139
" inline functions based on how much of the function is a scop." , false ,
124
140
false )
125
141
INITIALIZE_PASS_END(
126
- ScopInliner , " polly-scop-inliner" ,
142
+ ScopInlinerWrapperPass , " polly-scop-inliner" ,
127
143
" inline functions based on how much of the function is a scop." , false ,
128
144
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