#ifndef LLVM_ANALYSIS_INLINECOST_H
#define LLVM_ANALYSIS_INLINECOST_H
-#include "llvm/Function.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/ValueMap.h"
-#include "llvm/Analysis/CodeMetrics.h"
+#include "llvm/Analysis/CallGraphSCCPass.h"
#include <cassert>
#include <climits>
-#include <vector>
namespace llvm {
+class CallSite;
+class DataLayout;
+class Function;
+class TargetTransformInfo;
+
+namespace InlineConstants {
+ // Various magic constants used to adjust heuristics.
+ const int InstrCost = 5;
+ const int IndirectCallThreshold = 100;
+ const int CallPenalty = 25;
+ const int LastCallToStaticBonus = -15000;
+ const int ColdccPenalty = 2000;
+ const int NoreturnPenalty = 10000;
+ /// Do not inline functions which allocate this many bytes on the stack
+ /// when the caller is recursive.
+ const unsigned TotalAllocaSizeRecursiveCaller = 1024;
+}
+
+/// \brief Represents the cost of inlining a function.
+///
+/// This supports special values for functions which should "always" or
+/// "never" be inlined. Otherwise, the cost represents a unitless amount;
+/// smaller values increase the likelihood of the function being inlined.
+///
+/// Objects of this type also provide the adjusted threshold for inlining
+/// based on the information available for a particular callsite. They can be
+/// directly tested to determine if inlining should occur given the cost and
+/// threshold for this cost metric.
+class InlineCost {
+ enum SentinelValues {
+ AlwaysInlineCost = INT_MIN,
+ NeverInlineCost = INT_MAX
+ };
+
+ /// \brief The estimated cost of inlining this callsite.
+ const int Cost;
+
+ /// \brief The adjusted threshold against which this cost was computed.
+ const int Threshold;
- class CallSite;
- class TargetData;
-
- namespace InlineConstants {
- // Various magic constants used to adjust heuristics.
- const int InstrCost = 5;
- const int IndirectCallThreshold = 100;
- const int CallPenalty = 25;
- const int LastCallToStaticBonus = -15000;
- const int ColdccPenalty = 2000;
- const int NoreturnPenalty = 10000;
+ // Trivial constructor, interesting logic in the factory functions below.
+ InlineCost(int Cost, int Threshold) : Cost(Cost), Threshold(Threshold) {}
+
+public:
+ static InlineCost get(int Cost, int Threshold) {
+ assert(Cost > AlwaysInlineCost && "Cost crosses sentinel value");
+ assert(Cost < NeverInlineCost && "Cost crosses sentinel value");
+ return InlineCost(Cost, Threshold);
+ }
+ static InlineCost getAlways() {
+ return InlineCost(AlwaysInlineCost, 0);
+ }
+ static InlineCost getNever() {
+ return InlineCost(NeverInlineCost, 0);
}
- /// \brief Represents the cost of inlining a function.
- ///
- /// This supports special values for functions which should "always" or
- /// "never" be inlined. Otherwise, the cost represents a unitless amount;
- /// smaller values increase the likelihood of the function being inlined.
- ///
- /// Objects of this type also provide the adjusted threshold for inlining
- /// based on the information available for a particular callsite. They can be
- /// directly tested to determine if inlining should occur given the cost and
- /// threshold for this cost metric.
- class InlineCost {
- enum CostKind {
- CK_Variable,
- CK_Always,
- CK_Never
- };
-
- const int Cost : 30; // The inlining cost if neither always nor never.
- const unsigned Kind : 2; // The type of cost, one of CostKind above.
-
- /// \brief The adjusted threshold against which this cost should be tested.
- const int Threshold;
-
- // Trivial constructor, interesting logic in the factory functions below.
- InlineCost(int Cost, CostKind Kind, int Threshold)
- : Cost(Cost), Kind(Kind), Threshold(Threshold) {}
-
- public:
- static InlineCost get(int Cost, int Threshold) {
- InlineCost Result(Cost, CK_Variable, Threshold);
- assert(Result.Cost == Cost && "Cost exceeds InlineCost precision");
- return Result;
- }
- static InlineCost getAlways() {
- return InlineCost(0, CK_Always, 0);
- }
- static InlineCost getNever() {
- return InlineCost(0, CK_Never, 0);
- }
-
- /// \brief Test whether the inline cost is low enough for inlining.
- operator bool() const {
- if (isAlways()) return true;
- if (isNever()) return false;
- return Cost < Threshold;
- }
-
- bool isVariable() const { return Kind == CK_Variable; }
- bool isAlways() const { return Kind == CK_Always; }
- bool isNever() const { return Kind == CK_Never; }
-
- /// getCost() - Return a "variable" inline cost's amount. It is
- /// an error to call this on an "always" or "never" InlineCost.
- int getCost() const {
- assert(Kind == CK_Variable && "Invalid access of InlineCost");
- return Cost;
- }
-
- /// \brief Get the cost delta from the threshold for inlining.
- /// Only valid if the cost is of the variable kind. Returns a negative
- /// value if the cost is too high to inline.
- int getCostDelta() const {
- return Threshold - getCost();
- }
- };
+ /// \brief Test whether the inline cost is low enough for inlining.
+ LLVM_EXPLICIT operator bool() const {
+ return Cost < Threshold;
+ }
+
+ bool isAlways() const { return Cost == AlwaysInlineCost; }
+ bool isNever() const { return Cost == NeverInlineCost; }
+ bool isVariable() const { return !isAlways() && !isNever(); }
- /// InlineCostAnalyzer - Cost analyzer used by inliner.
- class InlineCostAnalyzer {
- // TargetData if available, or null.
- const TargetData *TD;
+ /// \brief Get the inline cost estimate.
+ /// It is an error to call this on an "always" or "never" InlineCost.
+ int getCost() const {
+ assert(isVariable() && "Invalid access of InlineCost");
+ return Cost;
+ }
- public:
- InlineCostAnalyzer(): TD(0) {}
+ /// \brief Get the cost delta from the threshold for inlining.
+ /// Only valid if the cost is of the variable kind. Returns a negative
+ /// value if the cost is too high to inline.
+ int getCostDelta() const { return Threshold - getCost(); }
+};
- void setTargetData(const TargetData *TData) { TD = TData; }
+/// \brief Cost analyzer used by inliner.
+class InlineCostAnalysis : public CallGraphSCCPass {
+ const TargetTransformInfo *TTI;
- /// \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.
- InlineCost getInlineCost(CallSite CS, int Threshold);
+public:
+ static char ID;
- /// resetCachedFunctionInfo - erase any cached cost info for this function.
- void resetCachedCostInfo(Function* Caller) {
- }
+ InlineCostAnalysis();
+ ~InlineCostAnalysis();
- /// growCachedCostInfo - update the cached cost info for Caller after Callee
- /// has been inlined. If Callee is NULL it means a dead call has been
- /// eliminated.
- void growCachedCostInfo(Function* Caller, Function* Callee);
+ // Pass interface implementation.
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+ bool runOnSCC(CallGraphSCC &SCC) override;
- /// clear - empty the cache of inline costs
- void clear();
- };
+ /// \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);
+};
- /// callIsSmall - If a call is likely to lower to a single target instruction,
- /// or is otherwise deemed small return true.
- bool callIsSmall(const Function *Callee);
}
#endif