1f4a2713aSLionel Sambuc //===- InlineAlways.cpp - Code to inline always_inline functions ----------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file implements a custom inliner that handles only functions that
11f4a2713aSLionel Sambuc // are marked as "always inline".
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc
15f4a2713aSLionel Sambuc #include "llvm/Transforms/IPO.h"
16f4a2713aSLionel Sambuc #include "llvm/ADT/SmallPtrSet.h"
17*0a6a1f1dSLionel Sambuc #include "llvm/Analysis/AliasAnalysis.h"
18*0a6a1f1dSLionel Sambuc #include "llvm/Analysis/AssumptionCache.h"
19f4a2713aSLionel Sambuc #include "llvm/Analysis/CallGraph.h"
20f4a2713aSLionel Sambuc #include "llvm/Analysis/InlineCost.h"
21*0a6a1f1dSLionel Sambuc #include "llvm/IR/CallSite.h"
22f4a2713aSLionel Sambuc #include "llvm/IR/CallingConv.h"
23f4a2713aSLionel Sambuc #include "llvm/IR/DataLayout.h"
24f4a2713aSLionel Sambuc #include "llvm/IR/Instructions.h"
25f4a2713aSLionel Sambuc #include "llvm/IR/IntrinsicInst.h"
26f4a2713aSLionel Sambuc #include "llvm/IR/Module.h"
27f4a2713aSLionel Sambuc #include "llvm/IR/Type.h"
28f4a2713aSLionel Sambuc #include "llvm/Transforms/IPO/InlinerPass.h"
29f4a2713aSLionel Sambuc
30f4a2713aSLionel Sambuc using namespace llvm;
31f4a2713aSLionel Sambuc
32*0a6a1f1dSLionel Sambuc #define DEBUG_TYPE "inline"
33*0a6a1f1dSLionel Sambuc
34f4a2713aSLionel Sambuc namespace {
35f4a2713aSLionel Sambuc
36f4a2713aSLionel Sambuc /// \brief Inliner pass which only handles "always inline" functions.
37f4a2713aSLionel Sambuc class AlwaysInliner : public Inliner {
38f4a2713aSLionel Sambuc InlineCostAnalysis *ICA;
39f4a2713aSLionel Sambuc
40f4a2713aSLionel Sambuc public:
41f4a2713aSLionel Sambuc // Use extremely low threshold.
AlwaysInliner()42*0a6a1f1dSLionel Sambuc AlwaysInliner() : Inliner(ID, -2000000000, /*InsertLifetime*/ true),
43*0a6a1f1dSLionel Sambuc ICA(nullptr) {
44f4a2713aSLionel Sambuc initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry());
45f4a2713aSLionel Sambuc }
46f4a2713aSLionel Sambuc
AlwaysInliner(bool InsertLifetime)47f4a2713aSLionel Sambuc AlwaysInliner(bool InsertLifetime)
48*0a6a1f1dSLionel Sambuc : Inliner(ID, -2000000000, InsertLifetime), ICA(nullptr) {
49f4a2713aSLionel Sambuc initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry());
50f4a2713aSLionel Sambuc }
51f4a2713aSLionel Sambuc
52f4a2713aSLionel Sambuc static char ID; // Pass identification, replacement for typeid
53f4a2713aSLionel Sambuc
54*0a6a1f1dSLionel Sambuc InlineCost getInlineCost(CallSite CS) override;
55f4a2713aSLionel Sambuc
56*0a6a1f1dSLionel Sambuc void getAnalysisUsage(AnalysisUsage &AU) const override;
57*0a6a1f1dSLionel Sambuc bool runOnSCC(CallGraphSCC &SCC) override;
58f4a2713aSLionel Sambuc
59f4a2713aSLionel Sambuc using llvm::Pass::doFinalization;
doFinalization(CallGraph & CG)60*0a6a1f1dSLionel Sambuc bool doFinalization(CallGraph &CG) override {
61f4a2713aSLionel Sambuc return removeDeadFunctions(CG, /*AlwaysInlineOnly=*/ true);
62f4a2713aSLionel Sambuc }
63f4a2713aSLionel Sambuc };
64f4a2713aSLionel Sambuc
65f4a2713aSLionel Sambuc }
66f4a2713aSLionel Sambuc
67f4a2713aSLionel Sambuc char AlwaysInliner::ID = 0;
68f4a2713aSLionel Sambuc INITIALIZE_PASS_BEGIN(AlwaysInliner, "always-inline",
69f4a2713aSLionel Sambuc "Inliner for always_inline functions", false, false)
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)70*0a6a1f1dSLionel Sambuc INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
71*0a6a1f1dSLionel Sambuc INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
72*0a6a1f1dSLionel Sambuc INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
73f4a2713aSLionel Sambuc INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)
74f4a2713aSLionel Sambuc INITIALIZE_PASS_END(AlwaysInliner, "always-inline",
75f4a2713aSLionel Sambuc "Inliner for always_inline functions", false, false)
76f4a2713aSLionel Sambuc
77f4a2713aSLionel Sambuc Pass *llvm::createAlwaysInlinerPass() { return new AlwaysInliner(); }
78f4a2713aSLionel Sambuc
createAlwaysInlinerPass(bool InsertLifetime)79f4a2713aSLionel Sambuc Pass *llvm::createAlwaysInlinerPass(bool InsertLifetime) {
80f4a2713aSLionel Sambuc return new AlwaysInliner(InsertLifetime);
81f4a2713aSLionel Sambuc }
82f4a2713aSLionel Sambuc
83f4a2713aSLionel Sambuc /// \brief Get the inline cost for the always-inliner.
84f4a2713aSLionel Sambuc ///
85f4a2713aSLionel Sambuc /// The always inliner *only* handles functions which are marked with the
86f4a2713aSLionel Sambuc /// attribute to force inlining. As such, it is dramatically simpler and avoids
87f4a2713aSLionel Sambuc /// using the powerful (but expensive) inline cost analysis. Instead it uses
88f4a2713aSLionel Sambuc /// a very simple and boring direct walk of the instructions looking for
89f4a2713aSLionel Sambuc /// impossible-to-inline constructs.
90f4a2713aSLionel Sambuc ///
91f4a2713aSLionel Sambuc /// Note, it would be possible to go to some lengths to cache the information
92f4a2713aSLionel Sambuc /// computed here, but as we only expect to do this for relatively few and
93f4a2713aSLionel Sambuc /// small functions which have the explicit attribute to force inlining, it is
94f4a2713aSLionel Sambuc /// likely not worth it in practice.
getInlineCost(CallSite CS)95f4a2713aSLionel Sambuc InlineCost AlwaysInliner::getInlineCost(CallSite CS) {
96f4a2713aSLionel Sambuc Function *Callee = CS.getCalledFunction();
97f4a2713aSLionel Sambuc
98f4a2713aSLionel Sambuc // Only inline direct calls to functions with always-inline attributes
99f4a2713aSLionel Sambuc // that are viable for inlining. FIXME: We shouldn't even get here for
100f4a2713aSLionel Sambuc // declarations.
101f4a2713aSLionel Sambuc if (Callee && !Callee->isDeclaration() &&
102*0a6a1f1dSLionel Sambuc CS.hasFnAttr(Attribute::AlwaysInline) &&
103f4a2713aSLionel Sambuc ICA->isInlineViable(*Callee))
104f4a2713aSLionel Sambuc return InlineCost::getAlways();
105f4a2713aSLionel Sambuc
106f4a2713aSLionel Sambuc return InlineCost::getNever();
107f4a2713aSLionel Sambuc }
108f4a2713aSLionel Sambuc
runOnSCC(CallGraphSCC & SCC)109f4a2713aSLionel Sambuc bool AlwaysInliner::runOnSCC(CallGraphSCC &SCC) {
110f4a2713aSLionel Sambuc ICA = &getAnalysis<InlineCostAnalysis>();
111f4a2713aSLionel Sambuc return Inliner::runOnSCC(SCC);
112f4a2713aSLionel Sambuc }
113f4a2713aSLionel Sambuc
getAnalysisUsage(AnalysisUsage & AU) const114f4a2713aSLionel Sambuc void AlwaysInliner::getAnalysisUsage(AnalysisUsage &AU) const {
115f4a2713aSLionel Sambuc AU.addRequired<InlineCostAnalysis>();
116f4a2713aSLionel Sambuc Inliner::getAnalysisUsage(AU);
117f4a2713aSLionel Sambuc }
118