15
15
#include " llvm/ADT/SetVector.h"
16
16
#include " llvm/Analysis/AliasAnalysis.h"
17
17
#include " llvm/Analysis/AssumptionCache.h"
18
+ #include " llvm/Analysis/InlineAdvisor.h"
18
19
#include " llvm/Analysis/InlineCost.h"
19
20
#include " llvm/Analysis/OptimizationRemarkEmitter.h"
20
21
#include " llvm/Analysis/ProfileSummaryInfo.h"
21
22
#include " llvm/IR/Module.h"
22
23
#include " llvm/InitializePasses.h"
23
- #include " llvm/Transforms/IPO/Inliner.h"
24
24
#include " llvm/Transforms/Utils/Cloning.h"
25
25
#include " llvm/Transforms/Utils/ModuleUtils.h"
26
26
@@ -37,86 +37,73 @@ bool AlwaysInlineImpl(
37
37
function_ref<BlockFrequencyInfo &(Function &)> GetBFI) {
38
38
SmallSetVector<CallBase *, 16 > Calls;
39
39
bool Changed = false ;
40
- SmallVector<Function *, 16 > InlinedFunctions;
41
- for (Function &F : M) {
42
- // When callee coroutine function is inlined into caller coroutine function
43
- // before coro-split pass,
44
- // coro-early pass can not handle this quiet well.
45
- // So we won't inline the coroutine function if it have not been unsplited
40
+ SmallVector<Function *, 16 > InlinedComdatFunctions;
41
+
42
+ for (Function &F : make_early_inc_range (M)) {
46
43
if (F.isPresplitCoroutine ())
47
44
continue ;
48
45
49
- if (!F.isDeclaration () && isInlineViable (F).isSuccess ()) {
50
- Calls.clear ();
51
-
52
- for (User *U : F.users ())
53
- if (auto *CB = dyn_cast<CallBase>(U))
54
- if (CB->getCalledFunction () == &F &&
55
- CB->hasFnAttr (Attribute::AlwaysInline) &&
56
- !CB->getAttributes ().hasFnAttr (Attribute::NoInline))
57
- Calls.insert (CB);
58
-
59
- for (CallBase *CB : Calls) {
60
- Function *Caller = CB->getCaller ();
61
- OptimizationRemarkEmitter ORE (Caller);
62
- DebugLoc DLoc = CB->getDebugLoc ();
63
- BasicBlock *Block = CB->getParent ();
64
-
65
- InlineFunctionInfo IFI (GetAssumptionCache, &PSI,
66
- GetBFI ? &GetBFI (*Caller) : nullptr ,
67
- GetBFI ? &GetBFI (F) : nullptr );
68
-
69
- InlineResult Res = InlineFunction (*CB, IFI, /* MergeAttributes=*/ true ,
70
- &GetAAR (F), InsertLifetime);
71
- if (!Res.isSuccess ()) {
72
- ORE.emit ([&]() {
73
- return OptimizationRemarkMissed (DEBUG_TYPE, " NotInlined" , DLoc,
74
- Block)
75
- << " '" << ore::NV (" Callee" , &F) << " ' is not inlined into '"
76
- << ore::NV (" Caller" , Caller)
77
- << " ': " << ore::NV (" Reason" , Res.getFailureReason ());
78
- });
79
- continue ;
80
- }
81
-
82
- emitInlinedIntoBasedOnCost (
83
- ORE, DLoc, Block, F, *Caller,
84
- InlineCost::getAlways (" always inline attribute" ),
85
- /* ForProfileContext=*/ false , DEBUG_TYPE);
46
+ if (F.isDeclaration () || !isInlineViable (F).isSuccess ())
47
+ continue ;
86
48
87
- Changed = true ;
49
+ Calls.clear ();
50
+
51
+ for (User *U : F.users ())
52
+ if (auto *CB = dyn_cast<CallBase>(U))
53
+ if (CB->getCalledFunction () == &F &&
54
+ CB->hasFnAttr (Attribute::AlwaysInline) &&
55
+ !CB->getAttributes ().hasFnAttr (Attribute::NoInline))
56
+ Calls.insert (CB);
57
+
58
+ for (CallBase *CB : Calls) {
59
+ Function *Caller = CB->getCaller ();
60
+ OptimizationRemarkEmitter ORE (Caller);
61
+ DebugLoc DLoc = CB->getDebugLoc ();
62
+ BasicBlock *Block = CB->getParent ();
63
+
64
+ InlineFunctionInfo IFI (GetAssumptionCache, &PSI,
65
+ GetBFI ? &GetBFI (*Caller) : nullptr ,
66
+ GetBFI ? &GetBFI (F) : nullptr );
67
+
68
+ InlineResult Res = InlineFunction (*CB, IFI, /* MergeAttributes=*/ true ,
69
+ &GetAAR (F), InsertLifetime);
70
+ if (!Res.isSuccess ()) {
71
+ ORE.emit ([&]() {
72
+ return OptimizationRemarkMissed (DEBUG_TYPE, " NotInlined" , DLoc, Block)
73
+ << " '" << ore::NV (" Callee" , &F) << " ' is not inlined into '"
74
+ << ore::NV (" Caller" , Caller)
75
+ << " ': " << ore::NV (" Reason" , Res.getFailureReason ());
76
+ });
77
+ continue ;
88
78
}
89
79
90
- if (F. hasFnAttribute (Attribute::AlwaysInline)) {
91
- // Remember to try and delete this function afterward. This both avoids
92
- // re-walking the rest of the module and avoids dealing with any
93
- // iterator invalidation issues while deleting functions.
94
- InlinedFunctions. push_back (&F);
95
- }
80
+ emitInlinedIntoBasedOnCost (
81
+ ORE, DLoc, Block, F, *Caller,
82
+ InlineCost::getAlways ( " always inline attribute " ),
83
+ /* ForProfileContext= */ false , DEBUG_TYPE);
84
+
85
+ Changed = true ;
96
86
}
97
- }
98
87
99
- // Remove any live functions.
100
- erase_if (InlinedFunctions, [&](Function *F) {
101
- F->removeDeadConstantUsers ();
102
- return !F->isDefTriviallyDead ();
103
- });
104
-
105
- // Delete the non-comdat ones from the module and also from our vector.
106
- auto NonComdatBegin = partition (
107
- InlinedFunctions, [&](Function *F) { return F->hasComdat (); });
108
- for (Function *F : make_range (NonComdatBegin, InlinedFunctions.end ())) {
109
- M.getFunctionList ().erase (F);
110
- Changed = true ;
88
+ F.removeDeadConstantUsers ();
89
+ if (F.hasFnAttribute (Attribute::AlwaysInline) && F.isDefTriviallyDead ()) {
90
+ // Remember to try and delete this function afterward. This allows to call
91
+ // filterDeadComdatFunctions() only once.
92
+ if (F.hasComdat ()) {
93
+ InlinedComdatFunctions.push_back (&F);
94
+ } else {
95
+ M.getFunctionList ().erase (F);
96
+ Changed = true ;
97
+ }
98
+ }
111
99
}
112
- InlinedFunctions.erase (NonComdatBegin, InlinedFunctions.end ());
113
100
114
- if (!InlinedFunctions .empty ()) {
101
+ if (!InlinedComdatFunctions .empty ()) {
115
102
// Now we just have the comdat functions. Filter out the ones whose comdats
116
103
// are not actually dead.
117
- filterDeadComdatFunctions (InlinedFunctions );
104
+ filterDeadComdatFunctions (InlinedComdatFunctions );
118
105
// The remaining functions are actually dead.
119
- for (Function *F : InlinedFunctions ) {
106
+ for (Function *F : InlinedComdatFunctions ) {
120
107
M.getFunctionList ().erase (F);
121
108
Changed = true ;
122
109
}
0 commit comments