@@ -28,16 +28,13 @@ using namespace llvm;
28
28
29
29
#define DEBUG_TYPE " inline"
30
30
31
- PreservedAnalyses AlwaysInlinerPass::run (Module &M,
32
- ModuleAnalysisManager &MAM) {
33
- // Add inline assumptions during code generation.
34
- FunctionAnalysisManager &FAM =
35
- MAM.getResult <FunctionAnalysisManagerModuleProxy>(M).getManager ();
36
- auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
37
- return FAM.getResult <AssumptionAnalysis>(F);
38
- };
39
- auto &PSI = MAM.getResult <ProfileSummaryAnalysis>(M);
31
+ namespace {
40
32
33
+ bool AlwaysInlineImpl (
34
+ Module &M, bool InsertLifetime, ProfileSummaryInfo &PSI,
35
+ function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
36
+ function_ref<AAResults &(Function &)> GetAAR,
37
+ function_ref<BlockFrequencyInfo &(Function &)> GetBFI) {
41
38
SmallSetVector<CallBase *, 16 > Calls;
42
39
bool Changed = false ;
43
40
SmallVector<Function *, 16 > InlinedFunctions;
@@ -65,14 +62,12 @@ PreservedAnalyses AlwaysInlinerPass::run(Module &M,
65
62
DebugLoc DLoc = CB->getDebugLoc ();
66
63
BasicBlock *Block = CB->getParent ();
67
64
68
- InlineFunctionInfo IFI (
69
- /* cg=*/ nullptr , GetAssumptionCache, &PSI,
70
- &FAM.getResult <BlockFrequencyAnalysis>(*Caller),
71
- &FAM.getResult <BlockFrequencyAnalysis>(F));
65
+ InlineFunctionInfo IFI (GetAssumptionCache, &PSI,
66
+ GetBFI ? &GetBFI (*Caller) : nullptr ,
67
+ GetBFI ? &GetBFI (F) : nullptr );
72
68
73
- InlineResult Res =
74
- InlineFunction (*CB, IFI, /* MergeAttributes=*/ true ,
75
- &FAM.getResult <AAManager>(F), InsertLifetime);
69
+ InlineResult Res = InlineFunction (*CB, IFI, /* MergeAttributes=*/ true ,
70
+ &GetAAR (F), InsertLifetime);
76
71
if (!Res.isSuccess ()) {
77
72
ORE.emit ([&]() {
78
73
return OptimizationRemarkMissed (DEBUG_TYPE, " NotInlined" , DLoc,
@@ -127,95 +122,76 @@ PreservedAnalyses AlwaysInlinerPass::run(Module &M,
127
122
}
128
123
}
129
124
130
- return Changed ? PreservedAnalyses::none () : PreservedAnalyses::all () ;
125
+ return Changed;
131
126
}
132
127
133
- namespace {
134
-
135
- // / Inliner pass which only handles "always inline" functions.
136
- // /
137
- // / Unlike the \c AlwaysInlinerPass, this uses the more heavyweight \c Inliner
138
- // / base class to provide several facilities such as array alloca merging.
139
- class AlwaysInlinerLegacyPass : public LegacyInlinerBase {
128
+ struct AlwaysInlinerLegacyPass : public ModulePass {
129
+ bool InsertLifetime;
140
130
141
- public:
142
- AlwaysInlinerLegacyPass () : LegacyInlinerBase(ID, /* InsertLifetime*/ true ) {
143
- initializeAlwaysInlinerLegacyPassPass (*PassRegistry::getPassRegistry ());
144
- }
131
+ AlwaysInlinerLegacyPass ()
132
+ : AlwaysInlinerLegacyPass(/* InsertLifetime*/ true ) {}
145
133
146
134
AlwaysInlinerLegacyPass (bool InsertLifetime)
147
- : LegacyInlinerBase (ID, InsertLifetime) {
135
+ : ModulePass (ID), InsertLifetime( InsertLifetime) {
148
136
initializeAlwaysInlinerLegacyPassPass (*PassRegistry::getPassRegistry ());
149
137
}
150
138
151
139
// / Main run interface method. We override here to avoid calling skipSCC().
152
- bool runOnSCC (CallGraphSCC &SCC) override { return inlineCalls (SCC); }
140
+ bool runOnModule (Module &M) override {
141
+
142
+ auto &PSI = getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI ();
143
+ auto GetAAR = [&](Function &F) -> AAResults & {
144
+ return getAnalysis<AAResultsWrapperPass>(F).getAAResults ();
145
+ };
146
+ auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
147
+ return getAnalysis<AssumptionCacheTracker>().getAssumptionCache (F);
148
+ };
149
+
150
+ return AlwaysInlineImpl (M, InsertLifetime, PSI, GetAssumptionCache, GetAAR,
151
+ /* GetBFI*/ nullptr );
152
+ }
153
153
154
154
static char ID; // Pass identification, replacement for typeid
155
155
156
- InlineCost getInlineCost (CallBase &CB) override ;
157
-
158
- using llvm::Pass::doFinalization;
159
- bool doFinalization (CallGraph &CG) override {
160
- return removeDeadFunctions (CG, /* AlwaysInlineOnly=*/ true );
156
+ void getAnalysisUsage (AnalysisUsage &AU) const override {
157
+ AU.addRequired <AssumptionCacheTracker>();
158
+ AU.addRequired <AAResultsWrapperPass>();
159
+ AU.addRequired <ProfileSummaryInfoWrapperPass>();
161
160
}
162
161
};
163
- }
162
+
163
+ } // namespace
164
164
165
165
char AlwaysInlinerLegacyPass::ID = 0 ;
166
166
INITIALIZE_PASS_BEGIN (AlwaysInlinerLegacyPass, " always-inline" ,
167
167
" Inliner for always_inline functions" , false , false )
168
+ INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
168
169
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
169
- INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
170
170
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
171
- INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
172
171
INITIALIZE_PASS_END(AlwaysInlinerLegacyPass, " always-inline" ,
173
172
" Inliner for always_inline functions" , false , false )
174
173
175
174
Pass *llvm::createAlwaysInlinerLegacyPass(bool InsertLifetime) {
176
175
return new AlwaysInlinerLegacyPass (InsertLifetime);
177
176
}
178
177
179
- // / Get the inline cost for the always-inliner.
180
- // /
181
- // / The always inliner *only* handles functions which are marked with the
182
- // / attribute to force inlining. As such, it is dramatically simpler and avoids
183
- // / using the powerful (but expensive) inline cost analysis. Instead it uses
184
- // / a very simple and boring direct walk of the instructions looking for
185
- // / impossible-to-inline constructs.
186
- // /
187
- // / Note, it would be possible to go to some lengths to cache the information
188
- // / computed here, but as we only expect to do this for relatively few and
189
- // / small functions which have the explicit attribute to force inlining, it is
190
- // / likely not worth it in practice.
191
- InlineCost AlwaysInlinerLegacyPass::getInlineCost (CallBase &CB) {
192
- Function *Callee = CB.getCalledFunction ();
193
-
194
- // Only inline direct calls to functions with always-inline attributes
195
- // that are viable for inlining.
196
- if (!Callee)
197
- return InlineCost::getNever (" indirect call" );
198
-
199
- // When callee coroutine function is inlined into caller coroutine function
200
- // before coro-split pass,
201
- // coro-early pass can not handle this quiet well.
202
- // So we won't inline the coroutine function if it have not been unsplited
203
- if (Callee->isPresplitCoroutine ())
204
- return InlineCost::getNever (" unsplited coroutine call" );
205
-
206
- // FIXME: We shouldn't even get here for declarations.
207
- if (Callee->isDeclaration ())
208
- return InlineCost::getNever (" no definition" );
209
-
210
- if (!CB.hasFnAttr (Attribute::AlwaysInline))
211
- return InlineCost::getNever (" no alwaysinline attribute" );
212
-
213
- if (Callee->hasFnAttribute (Attribute::AlwaysInline) && CB.isNoInline ())
214
- return InlineCost::getNever (" noinline call site attribute" );
215
-
216
- auto IsViable = isInlineViable (*Callee);
217
- if (!IsViable.isSuccess ())
218
- return InlineCost::getNever (IsViable.getFailureReason ());
219
-
220
- return InlineCost::getAlways (" always inliner" );
178
+ PreservedAnalyses AlwaysInlinerPass::run (Module &M,
179
+ ModuleAnalysisManager &MAM) {
180
+ FunctionAnalysisManager &FAM =
181
+ MAM.getResult <FunctionAnalysisManagerModuleProxy>(M).getManager ();
182
+ auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
183
+ return FAM.getResult <AssumptionAnalysis>(F);
184
+ };
185
+ auto GetBFI = [&](Function &F) -> BlockFrequencyInfo & {
186
+ return FAM.getResult <BlockFrequencyAnalysis>(F);
187
+ };
188
+ auto GetAAR = [&](Function &F) -> AAResults & {
189
+ return FAM.getResult <AAManager>(F);
190
+ };
191
+ auto &PSI = MAM.getResult <ProfileSummaryAnalysis>(M);
192
+
193
+ bool Changed = AlwaysInlineImpl (M, InsertLifetime, PSI, GetAssumptionCache,
194
+ GetAAR, GetBFI);
195
+
196
+ return Changed ? PreservedAnalyses::none () : PreservedAnalyses::all ();
221
197
}
0 commit comments