LLVM  16.0.0git
AlwaysInliner.cpp
Go to the documentation of this file.
1 //===- AlwaysInliner.cpp - Code to inline always_inline functions ----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements a custom inliner that handles only functions that
10 // are marked as "always inline".
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm/ADT/SetVector.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/InitializePasses.h"
26 
27 using namespace llvm;
28 
29 #define DEBUG_TYPE "inline"
30 
33  // Add inline assumptions during code generation.
36  auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
38  };
39  auto &PSI = MAM.getResult<ProfileSummaryAnalysis>(M);
40 
42  bool Changed = false;
43  SmallVector<Function *, 16> InlinedFunctions;
44  for (Function &F : M) {
45  // When callee coroutine function is inlined into caller coroutine function
46  // before coro-split pass,
47  // coro-early pass can not handle this quiet well.
48  // So we won't inline the coroutine function if it have not been unsplited
49  if (F.isPresplitCoroutine())
50  continue;
51 
52  if (!F.isDeclaration() && isInlineViable(F).isSuccess()) {
53  Calls.clear();
54 
55  for (User *U : F.users())
56  if (auto *CB = dyn_cast<CallBase>(U))
57  if (CB->getCalledFunction() == &F &&
58  CB->hasFnAttr(Attribute::AlwaysInline) &&
59  !CB->getAttributes().hasFnAttr(Attribute::NoInline))
60  Calls.insert(CB);
61 
62  for (CallBase *CB : Calls) {
63  Function *Caller = CB->getCaller();
64  OptimizationRemarkEmitter ORE(Caller);
65  DebugLoc DLoc = CB->getDebugLoc();
66  BasicBlock *Block = CB->getParent();
67 
69  /*cg=*/nullptr, GetAssumptionCache, &PSI,
72 
73  InlineResult Res =
74  InlineFunction(*CB, IFI, /*MergeAttributes=*/true,
75  &FAM.getResult<AAManager>(F), InsertLifetime);
76  if (!Res.isSuccess()) {
77  ORE.emit([&]() {
78  return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc,
79  Block)
80  << "'" << ore::NV("Callee", &F) << "' is not inlined into '"
81  << ore::NV("Caller", Caller)
82  << "': " << ore::NV("Reason", Res.getFailureReason());
83  });
84  continue;
85  }
86 
88  ORE, DLoc, Block, F, *Caller,
89  InlineCost::getAlways("always inline attribute"),
90  /*ForProfileContext=*/false, DEBUG_TYPE);
91 
92  Changed = true;
93  }
94 
95  if (F.hasFnAttribute(Attribute::AlwaysInline)) {
96  // Remember to try and delete this function afterward. This both avoids
97  // re-walking the rest of the module and avoids dealing with any
98  // iterator invalidation issues while deleting functions.
99  InlinedFunctions.push_back(&F);
100  }
101  }
102  }
103 
104  // Remove any live functions.
105  erase_if(InlinedFunctions, [&](Function *F) {
106  F->removeDeadConstantUsers();
107  return !F->isDefTriviallyDead();
108  });
109 
110  // Delete the non-comdat ones from the module and also from our vector.
111  auto NonComdatBegin = partition(
112  InlinedFunctions, [&](Function *F) { return F->hasComdat(); });
113  for (Function *F : make_range(NonComdatBegin, InlinedFunctions.end())) {
114  M.getFunctionList().erase(F);
115  Changed = true;
116  }
117  InlinedFunctions.erase(NonComdatBegin, InlinedFunctions.end());
118 
119  if (!InlinedFunctions.empty()) {
120  // Now we just have the comdat functions. Filter out the ones whose comdats
121  // are not actually dead.
122  filterDeadComdatFunctions(InlinedFunctions);
123  // The remaining functions are actually dead.
124  for (Function *F : InlinedFunctions) {
125  M.getFunctionList().erase(F);
126  Changed = true;
127  }
128  }
129 
130  return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
131 }
132 
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 {
140 
141 public:
142  AlwaysInlinerLegacyPass() : LegacyInlinerBase(ID, /*InsertLifetime*/ true) {
144  }
145 
146  AlwaysInlinerLegacyPass(bool InsertLifetime)
147  : LegacyInlinerBase(ID, InsertLifetime) {
149  }
150 
151  /// Main run interface method. We override here to avoid calling skipSCC().
152  bool runOnSCC(CallGraphSCC &SCC) override { return inlineCalls(SCC); }
153 
154  static char ID; // Pass identification, replacement for typeid
155 
156  InlineCost getInlineCost(CallBase &CB) override;
157 
159  bool doFinalization(CallGraph &CG) override {
160  return removeDeadFunctions(CG, /*AlwaysInlineOnly=*/true);
161  }
162 };
163 }
164 
166 INITIALIZE_PASS_BEGIN(AlwaysInlinerLegacyPass, "always-inline",
167  "Inliner for always_inline functions", false, false)
172 INITIALIZE_PASS_END(AlwaysInlinerLegacyPass, "always-inline",
173  "Inliner for always_inline functions", false, false)
174 
175 Pass *llvm::createAlwaysInlinerLegacyPass(bool InsertLifetime) {
176  return new AlwaysInlinerLegacyPass(InsertLifetime);
177 }
178 
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.
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");
221 }
llvm::initializeAlwaysInlinerLegacyPassPass
void initializeAlwaysInlinerLegacyPassPass(PassRegistry &)
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:152
AssumptionCache.h
llvm::AAManager
A manager for alias analyses.
Definition: AliasAnalysis.h:876
llvm::OptimizationRemarkMissed
Diagnostic information for missed-optimization remarks.
Definition: DiagnosticInfo.h:734
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::SmallVectorImpl::erase
iterator erase(const_iterator CI)
Definition: SmallVector.h:741
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::make_range
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Definition: iterator_range.h:53
llvm::AlwaysInlinerPass::run
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
Definition: AlwaysInliner.cpp:31
llvm::AArch64PACKey::ID
ID
Definition: AArch64BaseInfo.h:818
llvm::AnalysisManager::getResult
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:774
Inliner.h
llvm::Function
Definition: Function.h:60
llvm::createAlwaysInlinerLegacyPass
Pass * createAlwaysInlinerLegacyPass(bool InsertLifetime=true)
Create a legacy pass manager instance of a pass to inline and remove functions marked as "always_inli...
Definition: AlwaysInliner.cpp:175
llvm::InlineFunction
InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, bool MergeAttributes=false, AAResults *CalleeAAR=nullptr, bool InsertLifetime=true, Function *ForwardVarArgsTo=nullptr)
This function inlines the called function into the basic block of the caller.
Definition: InlineFunction.cpp:2046
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
llvm::erase_if
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition: STLExtras.h:1972
OptimizationRemarkEmitter.h
llvm::CallGraph
The basic data container for the call graph of a Module of IR.
Definition: CallGraph.h:72
FAM
FunctionAnalysisManager FAM
Definition: PassBuilderBindings.cpp:59
llvm::CallBase::hasFnAttr
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
Definition: InstrTypes.h:1483
llvm::emitInlinedIntoBasedOnCost
void emitInlinedIntoBasedOnCost(OptimizationRemarkEmitter &ORE, DebugLoc DLoc, const BasicBlock *Block, const Function &Callee, const Function &Caller, const InlineCost &IC, bool ForProfileContext=false, const char *PassName=nullptr)
Emit ORE message based in cost (default heuristic).
Definition: InlineAdvisor.cpp:502
llvm::PreservedAnalyses::none
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:155
true
basic Basic Alias true
Definition: BasicAliasAnalysis.cpp:1792
Module.h
llvm::InlineCost::getAlways
static InlineCost getAlways(const char *Reason, Optional< CostBenefitPair > CostBenefit=None)
Definition: InlineCost.h:124
llvm::isInlineViable
InlineResult isInlineViable(Function &Callee)
Minimal filter to detect invalid constructs for inlining.
Definition: InlineCost.cpp:2988
llvm::ore::NV
DiagnosticInfoOptimizationBase::Argument NV
Definition: OptimizationRemarkEmitter.h:136
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:55
always
bar al al movzbl eax ret Missed when stored in a memory are stored as single byte objects the value of which is always(false) or 1(true). We are not using this fact
Definition: README.txt:1412
AliasAnalysis.h
llvm::CallGraphSCC
CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
Definition: CallGraphSCCPass.h:87
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:24
AlwaysInliner.h
llvm::getInlineCost
InlineCost getInlineCost(CallBase &Call, const InlineParams &Params, TargetTransformInfo &CalleeTTI, function_ref< AssumptionCache &(Function &)> GetAssumptionCache, function_ref< const TargetLibraryInfo &(Function &)> GetTLI, function_ref< BlockFrequencyInfo &(Function &)> GetBFI=nullptr, ProfileSummaryInfo *PSI=nullptr, OptimizationRemarkEmitter *ORE=nullptr)
Get an InlineCost object representing the cost of inlining this callsite.
Definition: InlineCost.cpp:2821
llvm::User
Definition: User.h:44
llvm::CallBase::getCalledFunction
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Definition: InstrTypes.h:1396
MAM
ModuleAnalysisManager MAM
Definition: PassBuilderBindings.cpp:61
llvm::InlineCost
Represents the cost of inlining a function.
Definition: InlineCost.h:89
false
Definition: StackSlotColoring.cpp:141
llvm::InlineResult::isSuccess
bool isSuccess() const
Definition: InlineCost.h:186
llvm::BlockFrequencyAnalysis
Analysis pass which computes BlockFrequencyInfo.
Definition: BlockFrequencyInfo.h:112
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
INITIALIZE_PASS_END
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:58
llvm::TargetLibraryInfoWrapperPass
Definition: TargetLibraryInfo.h:474
ProfileSummaryInfo.h
llvm::LegacyInlinerBase
This class contains all of the helper code which is used to perform the inlining operations that do n...
Definition: Inliner.h:29
llvm::AssumptionAnalysis
A function analysis which provides an AssumptionCache.
Definition: AssumptionCache.h:173
llvm::filterDeadComdatFunctions
void filterDeadComdatFunctions(SmallVectorImpl< Function * > &DeadComdatFunctions)
Filter out potentially dead comdat functions where other entries keep the entire comdat group alive.
Definition: ModuleUtils.cpp:179
INITIALIZE_PASS_DEPENDENCY
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
llvm::CallGraphWrapperPass
The ModulePass which wraps up a CallGraph and the logic to build it.
Definition: CallGraph.h:347
Cloning.h
llvm::ProfileSummaryInfoWrapperPass
An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
Definition: ProfileSummaryInfo.h:193
llvm::OptimizationRemarkEmitter::emit
void emit(DiagnosticInfoOptimizationBase &OptDiag)
Output the remark via the diagnostic handler and to the optimization record file.
Definition: OptimizationRemarkEmitter.cpp:77
InlineCost.h
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
llvm::InlineCost::getNever
static InlineCost getNever(const char *Reason, Optional< CostBenefitPair > CostBenefit=None)
Definition: InlineCost.h:128
llvm::AMDGPU::CPol::SCC
@ SCC
Definition: SIDefines.h:307
llvm::ProfileSummaryAnalysis
An analysis pass based on the new PM to deliver ProfileSummaryInfo.
Definition: ProfileSummaryInfo.h:211
llvm::Pass::doFinalization
virtual bool doFinalization(Module &)
doFinalization - Virtual method overriden by subclasses to do any necessary clean up after all passes...
Definition: Pass.h:120
llvm::AssumptionCacheTracker
An immutable pass that tracks lazily created AssumptionCache objects.
Definition: AssumptionCache.h:202
llvm::OptimizationRemarkEmitter
The optimization diagnostic interface.
Definition: OptimizationRemarkEmitter.h:33
llvm::AssumptionCache
A cache of @llvm.assume calls within a function.
Definition: AssumptionCache.h:42
llvm::InlineResult::getFailureReason
const char * getFailureReason() const
Definition: InlineCost.h:187
llvm::partition
auto partition(R &&Range, UnaryPredicate P)
Provide wrappers to std::partition which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1891
for
this could be done in SelectionDAGISel along with other special for
Definition: README.txt:104
functions
always Inliner for always_inline functions
Definition: AlwaysInliner.cpp:173
Callee
amdgpu Simplify well known AMD library false FunctionCallee Callee
Definition: AMDGPULibCalls.cpp:187
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:158
llvm::CallBase::isNoInline
bool isNoInline() const
Return true if the call should not be inlined.
Definition: InstrTypes.h:1848
INITIALIZE_PASS_BEGIN
INITIALIZE_PASS_BEGIN(AlwaysInlinerLegacyPass, "always-inline", "Inliner for always_inline functions", false, false) INITIALIZE_PASS_END(AlwaysInlinerLegacyPass
llvm::InlineFunctionInfo
This class captures the data input to the InlineFunction call, and records the auxiliary results prod...
Definition: Cloning.h:203
Inliner
partial Partial Inliner
Definition: PartialInlining.cpp:1521
llvm::SmallVectorImpl::clear
void clear()
Definition: SmallVector.h:614
llvm::Pass
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:91
ModuleUtils.h
inline
always inline
Definition: AlwaysInliner.cpp:172
llvm::CallBase
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1174
llvm::SmallSetVector
A SetVector that performs no allocations if smaller than a certain size.
Definition: SetVector.h:307
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:42
llvm::InnerAnalysisManagerProxy
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
Definition: PassManager.h:931
llvm::DebugLoc
A debug info location.
Definition: DebugLoc.h:33
InitializePasses.h
llvm::InlineResult
InlineResult is basically true or false.
Definition: InlineCost.h:177
SetVector.h
DEBUG_TYPE
#define DEBUG_TYPE
Definition: AlwaysInliner.cpp:29