class CallSite;
class DataLayout;
class Function;
-class TargetTransformInfoWrapperPass;
+class TargetTransformInfo;
namespace InlineConstants {
// Various magic constants used to adjust heuristics.
int getCostDelta() const { return Threshold - getCost(); }
};
-/// \brief Cost analyzer used by inliner.
-class InlineCostAnalysis : public CallGraphSCCPass {
- TargetTransformInfoWrapperPass *TTIWP;
- AssumptionCacheTracker *ACT;
-
-public:
- static char ID;
-
- InlineCostAnalysis();
- ~InlineCostAnalysis() override;
-
- // Pass interface implementation.
- void getAnalysisUsage(AnalysisUsage &AU) const override;
- bool runOnSCC(CallGraphSCC &SCC) override;
-
- /// \brief Get an InlineCost object representing the cost of inlining this
- /// callsite.
- ///
- /// Note that threshold is passed into this function. Only costs below the
- /// threshold are computed with any accuracy. The threshold can be used to
- /// bound the computation necessary to determine whether the cost is
- /// sufficiently low to warrant inlining.
- ///
- /// Also note that calling this function *dynamically* computes the cost of
- /// inlining the callsite. It is an expensive, heavyweight call.
- InlineCost getInlineCost(CallSite CS, int Threshold);
-
- /// \brief Get an InlineCost with the callee explicitly specified.
- /// This allows you to calculate the cost of inlining a function via a
- /// pointer. This behaves exactly as the version with no explicit callee
- /// parameter in all other respects.
- //
- // Note: This is used by out-of-tree passes, please do not remove without
- // adding a replacement API.
- InlineCost getInlineCost(CallSite CS, Function *Callee, int Threshold);
-
- /// \brief Minimal filter to detect invalid constructs for inlining.
- bool isInlineViable(Function &Callee);
-};
+/// \brief Get an InlineCost object representing the cost of inlining this
+/// callsite.
+///
+/// Note that threshold is passed into this function. Only costs below the
+/// threshold are computed with any accuracy. The threshold can be used to
+/// bound the computation necessary to determine whether the cost is
+/// sufficiently low to warrant inlining.
+///
+/// Also note that calling this function *dynamically* computes the cost of
+/// inlining the callsite. It is an expensive, heavyweight call.
+InlineCost getInlineCost(CallSite CS, int Threshold,
+ TargetTransformInfo &CalleeTTI,
+ AssumptionCacheTracker *ACT);
+
+/// \brief Get an InlineCost with the callee explicitly specified.
+/// This allows you to calculate the cost of inlining a function via a
+/// pointer. This behaves exactly as the version with no explicit callee
+/// parameter in all other respects.
+//
+InlineCost getInlineCost(CallSite CS, Function *Callee, int Threshold,
+ TargetTransformInfo &CalleeTTI,
+ AssumptionCacheTracker *ACT);
+/// \brief Minimal filter to detect invalid constructs for inlining.
+bool isInlineViable(Function &Callee);
}
#endif
#include "llvm/Analysis/CallGraphSCCPass.h"
namespace llvm {
- class CallSite;
- class DataLayout;
- class InlineCost;
- template<class PtrType, unsigned SmallSize>
- class SmallPtrSet;
+class AssumptionCacheTracker;
+class CallSite;
+class DataLayout;
+class InlineCost;
+template <class PtrType, unsigned SmallSize> class SmallPtrSet;
/// Inliner - This class contains all of the helper code which is used to
/// perform the inlining operations that do not depend on the policy.
/// shouldInline - Return true if the inliner should attempt to
/// inline at the given CallSite.
bool shouldInline(CallSite CS);
+
+protected:
+ AssumptionCacheTracker *ACT;
};
} // End llvm namespace
}
#endif
-INITIALIZE_PASS_BEGIN(InlineCostAnalysis, "inline-cost", "Inline Cost Analysis",
- true, true)
-INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
-INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
-INITIALIZE_PASS_END(InlineCostAnalysis, "inline-cost", "Inline Cost Analysis",
- true, true)
-
-char InlineCostAnalysis::ID = 0;
-
-InlineCostAnalysis::InlineCostAnalysis() : CallGraphSCCPass(ID) {}
-
-InlineCostAnalysis::~InlineCostAnalysis() {}
-
-void InlineCostAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- AU.addRequired<AssumptionCacheTracker>();
- AU.addRequired<TargetTransformInfoWrapperPass>();
- CallGraphSCCPass::getAnalysisUsage(AU);
-}
-
-bool InlineCostAnalysis::runOnSCC(CallGraphSCC &SCC) {
- TTIWP = &getAnalysis<TargetTransformInfoWrapperPass>();
- ACT = &getAnalysis<AssumptionCacheTracker>();
- return false;
-}
-
-InlineCost InlineCostAnalysis::getInlineCost(CallSite CS, int Threshold) {
- return getInlineCost(CS, CS.getCalledFunction(), Threshold);
-}
-
/// \brief Test that two functions either have or have not the given attribute
/// at the same time.
template<typename AttrKind>
AttributeFuncs::areInlineCompatible(*Caller, *Callee);
}
-InlineCost InlineCostAnalysis::getInlineCost(CallSite CS, Function *Callee,
- int Threshold) {
+InlineCost llvm::getInlineCost(CallSite CS, int Threshold,
+ TargetTransformInfo &CalleeTTI,
+ AssumptionCacheTracker *ACT) {
+ return getInlineCost(CS, CS.getCalledFunction(), Threshold, CalleeTTI, ACT);
+}
+
+InlineCost llvm::getInlineCost(CallSite CS, Function *Callee, int Threshold,
+ TargetTransformInfo &CalleeTTI,
+ AssumptionCacheTracker *ACT) {
// Cannot inline indirect calls.
if (!Callee)
return llvm::InlineCost::getNever();
// Never inline functions with conflicting attributes (unless callee has
// always-inline attribute).
- if (!functionsHaveCompatibleAttributes(CS.getCaller(), Callee,
- TTIWP->getTTI(*Callee)))
+ if (!functionsHaveCompatibleAttributes(CS.getCaller(), Callee, CalleeTTI))
return llvm::InlineCost::getNever();
// Don't inline this call if the caller has the optnone attribute.
DEBUG(llvm::dbgs() << " Analyzing call of " << Callee->getName()
<< "...\n");
- CallAnalyzer CA(TTIWP->getTTI(*Callee), ACT, *Callee, Threshold, CS);
+ CallAnalyzer CA(CalleeTTI, ACT, *Callee, Threshold, CS);
bool ShouldInline = CA.analyzeCall(CS);
DEBUG(CA.dump());
return llvm::InlineCost::get(CA.getCost(), CA.getThreshold());
}
-bool InlineCostAnalysis::isInlineViable(Function &F) {
+bool llvm::isInlineViable(Function &F) {
bool ReturnsTwice = F.hasFnAttribute(Attribute::ReturnsTwice);
for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI) {
// Disallow inlining of functions which contain indirect branches or
/// \brief Inliner pass which only handles "always inline" functions.
class AlwaysInliner : public Inliner {
- InlineCostAnalysis *ICA;
public:
// Use extremely low threshold.
- AlwaysInliner() : Inliner(ID, -2000000000, /*InsertLifetime*/ true),
- ICA(nullptr) {
+ AlwaysInliner() : Inliner(ID, -2000000000, /*InsertLifetime*/ true) {
initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry());
}
AlwaysInliner(bool InsertLifetime)
- : Inliner(ID, -2000000000, InsertLifetime), ICA(nullptr) {
+ : Inliner(ID, -2000000000, InsertLifetime) {
initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry());
}
InlineCost getInlineCost(CallSite CS) override;
- void getAnalysisUsage(AnalysisUsage &AU) const override;
- bool runOnSCC(CallGraphSCC &SCC) override;
-
using llvm::Pass::doFinalization;
bool doFinalization(CallGraph &CG) override {
return removeDeadFunctions(CG, /*AlwaysInlineOnly=*/ true);
"Inliner for always_inline functions", false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
-INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_END(AlwaysInliner, "always-inline",
"Inliner for always_inline functions", false, false)
// that are viable for inlining. FIXME: We shouldn't even get here for
// declarations.
if (Callee && !Callee->isDeclaration() &&
- CS.hasFnAttr(Attribute::AlwaysInline) &&
- ICA->isInlineViable(*Callee))
+ CS.hasFnAttr(Attribute::AlwaysInline) && isInlineViable(*Callee))
return InlineCost::getAlways();
return InlineCost::getNever();
}
-
-bool AlwaysInliner::runOnSCC(CallGraphSCC &SCC) {
- ICA = &getAnalysis<InlineCostAnalysis>();
- return Inliner::runOnSCC(SCC);
-}
-
-void AlwaysInliner::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<InlineCostAnalysis>();
- Inliner::getAnalysisUsage(AU);
-}
//
//===----------------------------------------------------------------------===//
-#include "llvm/Transforms/IPO.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/InlineCost.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
+#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/InlinerPass.h"
using namespace llvm;
/// inliner pass and the always inliner pass. The two passes use different cost
/// analyses to determine when to inline.
class SimpleInliner : public Inliner {
- InlineCostAnalysis *ICA;
public:
- SimpleInliner() : Inliner(ID), ICA(nullptr) {
+ SimpleInliner() : Inliner(ID) {
initializeSimpleInlinerPass(*PassRegistry::getPassRegistry());
}
SimpleInliner(int Threshold)
- : Inliner(ID, Threshold, /*InsertLifetime*/ true), ICA(nullptr) {
+ : Inliner(ID, Threshold, /*InsertLifetime*/ true) {
initializeSimpleInlinerPass(*PassRegistry::getPassRegistry());
}
static char ID; // Pass identification, replacement for typeid
InlineCost getInlineCost(CallSite CS) override {
- return ICA->getInlineCost(CS, getInlineThreshold(CS));
+ Function *Callee = CS.getCalledFunction();
+ TargetTransformInfo &TTI = TTIWP->getTTI(*Callee);
+ return llvm::getInlineCost(CS, getInlineThreshold(CS), TTI, ACT);
}
bool runOnSCC(CallGraphSCC &SCC) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+private:
+ TargetTransformInfoWrapperPass *TTIWP;
};
static int computeThresholdFromOptLevels(unsigned OptLevel,
"Function Integration/Inlining", false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
-INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)
+INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_END(SimpleInliner, "inline",
"Function Integration/Inlining", false, false)
}
bool SimpleInliner::runOnSCC(CallGraphSCC &SCC) {
- ICA = &getAnalysis<InlineCostAnalysis>();
+ TTIWP = &getAnalysis<TargetTransformInfoWrapperPass>();
return Inliner::runOnSCC(SCC);
}
void SimpleInliner::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<InlineCostAnalysis>();
+ AU.addRequired<TargetTransformInfoWrapperPass>();
Inliner::getAnalysisUsage(AU);
}
// Threshold to use when optsize is specified (and there is no -inline-limit).
const int OptSizeThreshold = 75;
-Inliner::Inliner(char &ID)
- : CallGraphSCCPass(ID), InlineThreshold(InlineLimit), InsertLifetime(true) {}
+Inliner::Inliner(char &ID)
+ : CallGraphSCCPass(ID), InlineThreshold(InlineLimit), InsertLifetime(true) {
+}
Inliner::Inliner(char &ID, int Threshold, bool InsertLifetime)
- : CallGraphSCCPass(ID), InlineThreshold(InlineLimit.getNumOccurrences() > 0 ?
- InlineLimit : Threshold),
- InsertLifetime(InsertLifetime) {}
+ : CallGraphSCCPass(ID),
+ InlineThreshold(InlineLimit.getNumOccurrences() > 0 ? InlineLimit
+ : Threshold),
+ InsertLifetime(InsertLifetime) {}
/// For this class, we declare that we require and preserve the call graph.
/// If the derived class implements this method, it should
bool Inliner::runOnSCC(CallGraphSCC &SCC) {
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
- AssumptionCacheTracker *ACT = &getAnalysis<AssumptionCacheTracker>();
+ ACT = &getAnalysis<AssumptionCacheTracker>();
auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
SmallPtrSet<Function*, 8> SCCFunctions;