1515#include " llvm/ADT/SetVector.h"
1616#include " llvm/Analysis/AliasAnalysis.h"
1717#include " llvm/Analysis/AssumptionCache.h"
18+ #include " llvm/Analysis/InlineAdvisor.h"
1819#include " llvm/Analysis/InlineCost.h"
1920#include " llvm/Analysis/OptimizationRemarkEmitter.h"
2021#include " llvm/Analysis/ProfileSummaryInfo.h"
2122#include " llvm/IR/Module.h"
2223#include " llvm/InitializePasses.h"
23- #include " llvm/Transforms/IPO/Inliner.h"
2424#include " llvm/Transforms/Utils/Cloning.h"
2525#include " llvm/Transforms/Utils/ModuleUtils.h"
2626
@@ -37,86 +37,73 @@ bool AlwaysInlineImpl(
3737 function_ref<BlockFrequencyInfo &(Function &)> GetBFI) {
3838 SmallSetVector<CallBase *, 16 > Calls;
3939 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)) {
4643 if (F.isPresplitCoroutine ())
4744 continue ;
4845
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 ;
8648
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 ;
8878 }
8979
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 ;
9686 }
97- }
9887
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+ }
11199 }
112- InlinedFunctions.erase (NonComdatBegin, InlinedFunctions.end ());
113100
114- if (!InlinedFunctions .empty ()) {
101+ if (!InlinedComdatFunctions .empty ()) {
115102 // Now we just have the comdat functions. Filter out the ones whose comdats
116103 // are not actually dead.
117- filterDeadComdatFunctions (InlinedFunctions );
104+ filterDeadComdatFunctions (InlinedComdatFunctions );
118105 // The remaining functions are actually dead.
119- for (Function *F : InlinedFunctions ) {
106+ for (Function *F : InlinedComdatFunctions ) {
120107 M.getFunctionList ().erase (F);
121108 Changed = true ;
122109 }
0 commit comments