LLVM 22.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"
22#include "llvm/IR/Module.h"
26
27using namespace llvm;
28
29#define DEBUG_TYPE "inline"
30
31namespace {
32
33bool AlwaysInlineImpl(
34 Module &M, bool InsertLifetime, ProfileSummaryInfo &PSI,
36 function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
37 function_ref<AAResults &(Function &)> GetAAR) {
39 bool Changed = false;
40 SmallVector<Function *, 16> InlinedComdatFunctions;
41
42 for (Function &F : make_early_inc_range(M)) {
43 if (F.isPresplitCoroutine())
44 continue;
45
46 if (F.isDeclaration() || !isInlineViable(F).isSuccess())
47 continue;
48
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, nullptr, nullptr);
65 InlineResult Res = InlineFunction(*CB, IFI, /*MergeAttributes=*/true,
66 &GetAAR(F), InsertLifetime);
67 if (!Res.isSuccess()) {
68 ORE.emit([&]() {
69 return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block)
70 << "'" << ore::NV("Callee", &F) << "' is not inlined into '"
71 << ore::NV("Caller", Caller)
72 << "': " << ore::NV("Reason", Res.getFailureReason());
73 });
74 continue;
75 }
76
78 ORE, DLoc, Block, F, *Caller,
79 InlineCost::getAlways("always inline attribute"),
80 /*ForProfileContext=*/false, DEBUG_TYPE);
81
82 Changed = true;
83 if (FAM)
84 FAM->invalidate(*Caller, PreservedAnalyses::none());
85 }
86
87 F.removeDeadConstantUsers();
88 if (F.hasFnAttribute(Attribute::AlwaysInline) && F.isDefTriviallyDead()) {
89 // Remember to try and delete this function afterward. This allows to call
90 // filterDeadComdatFunctions() only once.
91 if (F.hasComdat()) {
92 InlinedComdatFunctions.push_back(&F);
93 } else {
94 if (FAM)
95 FAM->clear(F, F.getName());
96 M.getFunctionList().erase(F);
97 Changed = true;
98 }
99 }
100 }
101
102 if (!InlinedComdatFunctions.empty()) {
103 // Now we just have the comdat functions. Filter out the ones whose comdats
104 // are not actually dead.
105 filterDeadComdatFunctions(InlinedComdatFunctions);
106 // The remaining functions are actually dead.
107 for (Function *F : InlinedComdatFunctions) {
108 if (FAM)
109 FAM->clear(*F, F->getName());
110 M.getFunctionList().erase(F);
111 Changed = true;
112 }
113 }
114
115 return Changed;
116}
117
118struct AlwaysInlinerLegacyPass : public ModulePass {
119 bool InsertLifetime;
120
121 AlwaysInlinerLegacyPass()
122 : AlwaysInlinerLegacyPass(/*InsertLifetime*/ true) {}
123
124 AlwaysInlinerLegacyPass(bool InsertLifetime)
125 : ModulePass(ID), InsertLifetime(InsertLifetime) {
127 }
128
129 /// Main run interface method.
130 bool runOnModule(Module &M) override {
131
132 auto &PSI = getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
133 auto GetAAR = [&](Function &F) -> AAResults & {
134 return getAnalysis<AAResultsWrapperPass>(F).getAAResults();
135 };
136 auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
137 return getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
138 };
139
140 return AlwaysInlineImpl(M, InsertLifetime, PSI, /*FAM=*/nullptr,
141 GetAssumptionCache, GetAAR);
142 }
143
144 static char ID; // Pass identification, replacement for typeid
145
146 void getAnalysisUsage(AnalysisUsage &AU) const override {
150 }
151};
152
153} // namespace
154
155char AlwaysInlinerLegacyPass::ID = 0;
156INITIALIZE_PASS_BEGIN(AlwaysInlinerLegacyPass, "always-inline",
157 "Inliner for always_inline functions", false, false)
161INITIALIZE_PASS_END(AlwaysInlinerLegacyPass, "always-inline",
162 "Inliner for always_inline functions", false, false)
163
165 return new AlwaysInlinerLegacyPass(InsertLifetime);
166}
167
171 MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
172 auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
173 return FAM.getResult<AssumptionAnalysis>(F);
174 };
175 auto GetAAR = [&](Function &F) -> AAResults & {
176 return FAM.getResult<AAManager>(F);
177 };
178 auto &PSI = MAM.getResult<ProfileSummaryAnalysis>(M);
179
180 bool Changed = AlwaysInlineImpl(M, InsertLifetime, PSI, &FAM,
181 GetAssumptionCache, GetAAR);
182 if (!Changed)
183 return PreservedAnalyses::all();
184
186 // We have already invalidated all analyses on modified functions.
188 return PA;
189}
Provides passes to inlining "always_inline" functions.
#define DEBUG_TYPE
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:55
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This file implements a set that has insertion order iteration characteristics.
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
Definition Analysis.h:50
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
A debug info location.
Definition DebugLoc.h:124
static InlineCost getAlways(const char *Reason, std::optional< CostBenefitPair > CostBenefit=std::nullopt)
Definition InlineCost.h:127
This class captures the data input to the InlineFunction call, and records the auxiliary results prod...
Definition Cloning.h:251
InlineResult is basically true or false.
Definition InlineCost.h:181
bool isSuccess() const
Definition InlineCost.h:190
const char * getFailureReason() const
Definition InlineCost.h:191
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
The optimization diagnostic interface.
LLVM_ABI void emit(DiagnosticInfoOptimizationBase &OptDiag)
Output the remark via the diagnostic handler and to the optimization record file.
Diagnostic information for missed-optimization remarks.
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Pass interface - Implemented by all 'passes'.
Definition Pass.h:99
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
An analysis pass based on the new PM to deliver ProfileSummaryInfo.
An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
Analysis providing profile information.
void clear()
Completely clear the SetVector.
Definition SetVector.h:284
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:168
A SetVector that performs no allocations if smaller than a certain size.
Definition SetVector.h:356
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An efficient, type-erasing, non-owning reference to a callable.
Changed
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, bool MergeAttributes=false, AAResults *CalleeAAR=nullptr, bool InsertLifetime=true, Function *ForwardVarArgsTo=nullptr, OptimizationRemarkEmitter *ORE=nullptr)
This function inlines the called function into the basic block of the caller.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:626
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI InlineResult isInlineViable(Function &Callee)
Check if it is mechanically possible to inline the function Callee, based on the contents of the func...
LLVM_ABI 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).
LLVM_ABI Pass * createAlwaysInlinerLegacyPass(bool InsertLifetime=true)
Create a legacy pass manager instance of a pass to inline and remove functions marked as "always_inli...
LLVM_ABI void filterDeadComdatFunctions(SmallVectorImpl< Function * > &DeadComdatFunctions)
Filter out potentially dead comdat functions where other entries keep the entire comdat group alive.
LLVM_ABI void initializeAlwaysInlinerLegacyPassPass(PassRegistry &)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39