Make the inline cost a proper analysis pass. This remains essentially
authorChandler Carruth <chandlerc@gmail.com>
Mon, 21 Jan 2013 11:39:18 +0000 (11:39 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Mon, 21 Jan 2013 11:39:18 +0000 (11:39 +0000)
a dynamic analysis done on each call to the routine. However, now it can
use the standard pass infrastructure to reference other analyses,
instead of a silly setter method. This will become more interesting as
I teach it about more analysis passes.

This updates the two inliner passes to use the inline cost analysis.
Doing so highlights how utterly redundant these two passes are. Either
we should find a cheaper way to do always inlining, or we should merge
the two and just fiddle with the thresholds to get the desired behavior.
I'm leaning increasingly toward the latter as it would also remove the
Inliner sub-class split.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173030 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/InlineCost.h
include/llvm/InitializePasses.h
lib/Analysis/InlineCost.cpp
lib/Transforms/IPO/InlineAlways.cpp
lib/Transforms/IPO/InlineSimple.cpp

index dfdfe3e4f8e8b9edef698c291376934d9f2e7ae3..3d815291781516e7dbb3acae23c8c7c18e2eb6a3 100644 (file)
@@ -15,6 +15,7 @@
 #define LLVM_ANALYSIS_INLINECOST_H
 
 #include "llvm/Analysis/CodeMetrics.h"
+#include "llvm/Analysis/CallGraphSCCPass.h"
 #include <cassert>
 #include <climits>
 
@@ -97,14 +98,18 @@ public:
 };
 
 /// \brief Cost analyzer used by inliner.
-class InlineCostAnalyzer {
-  // DataLayout if available, or null.
+class InlineCostAnalysis : public CallGraphSCCPass {
   const DataLayout *TD;
 
 public:
-  InlineCostAnalyzer() : TD(0) {}
+  static char ID;
 
-  void setDataLayout(const DataLayout *TData) { TD = TData; }
+  InlineCostAnalysis();
+  ~InlineCostAnalysis();
+
+  // Pass interface implementation.
+  void getAnalysisUsage(AnalysisUsage &AU) const;
+  bool runOnSCC(CallGraphSCC &SCC);
 
   /// \brief Get an InlineCost object representing the cost of inlining this
   /// callsite.
@@ -113,6 +118,9 @@ public:
   /// 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.
index 870c7c04ca0455e2f8863e8b8d70555bf9898c4b..aaffd6c9a7a15f23e16db0e37326514ca5c50ec1 100644 (file)
@@ -132,6 +132,7 @@ void initializeIPSCCPPass(PassRegistry&);
 void initializeIVUsersPass(PassRegistry&);
 void initializeIfConverterPass(PassRegistry&);
 void initializeIndVarSimplifyPass(PassRegistry&);
+void initializeInlineCostAnalysisPass(PassRegistry&);
 void initializeInstCombinerPass(PassRegistry&);
 void initializeInstCountPass(PassRegistry&);
 void initializeInstNamerPass(PassRegistry&);
index 6e5c03582256e8468ca573bde9f763ab62ee3d92..3292ebe3d7f8dbf26fa7e9cfd25d4c148483d45c 100644 (file)
@@ -1132,11 +1132,32 @@ void CallAnalyzer::dump() {
 }
 #endif
 
-InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS, int Threshold) {
+INITIALIZE_PASS_BEGIN(InlineCostAnalysis, "inline-cost", "Inline Cost Analysis",
+                      true, true)
+INITIALIZE_PASS_END(InlineCostAnalysis, "inline-cost", "Inline Cost Analysis",
+                    true, true)
+
+char InlineCostAnalysis::ID = 0;
+
+InlineCostAnalysis::InlineCostAnalysis() : CallGraphSCCPass(ID), TD(0) {}
+
+InlineCostAnalysis::~InlineCostAnalysis() {}
+
+void InlineCostAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.setPreservesAll();
+  CallGraphSCCPass::getAnalysisUsage(AU);
+}
+
+bool InlineCostAnalysis::runOnSCC(CallGraphSCC &SCC) {
+  TD = getAnalysisIfAvailable<DataLayout>();
+  return false;
+}
+
+InlineCost InlineCostAnalysis::getInlineCost(CallSite CS, int Threshold) {
   return getInlineCost(CS, CS.getCalledFunction(), Threshold);
 }
 
-InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS, Function *Callee,
+InlineCost InlineCostAnalysis::getInlineCost(CallSite CS, Function *Callee,
                                              int Threshold) {
   // Cannot inline indirect calls.
   if (!Callee)
@@ -1177,9 +1198,10 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS, Function *Callee,
   return llvm::InlineCost::get(CA.getCost(), CA.getThreshold());
 }
 
-bool InlineCostAnalyzer::isInlineViable(Function &F) {
-  bool ReturnsTwice =F.getAttributes().hasAttribute(AttributeSet::FunctionIndex,
-                                                    Attribute::ReturnsTwice);
+bool InlineCostAnalysis::isInlineViable(Function &F) {
+  bool ReturnsTwice =
+    F.getAttributes().hasAttribute(AttributeSet::FunctionIndex,
+                                   Attribute::ReturnsTwice);
   for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI) {
     // Disallow inlining of functions which contain an indirect branch.
     if (isa<IndirectBrInst>(BI->getTerminator()))
index 5937fab472b2e2868ea2a223c05dbc25add04122..a0095dad1af7a41a77960e6abe06b414ac048745 100644 (file)
@@ -32,16 +32,16 @@ namespace {
 
 /// \brief Inliner pass which only handles "always inline" functions.
 class AlwaysInliner : public Inliner {
-  InlineCostAnalyzer CA;
+  InlineCostAnalysis *ICA;
 
 public:
   // Use extremely low threshold.
-  AlwaysInliner() : Inliner(ID, -2000000000, /*InsertLifetime*/ true) {
+  AlwaysInliner() : Inliner(ID, -2000000000, /*InsertLifetime*/ true), ICA(0) {
     initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry());
   }
 
   AlwaysInliner(bool InsertLifetime)
-      : Inliner(ID, -2000000000, InsertLifetime) {
+      : Inliner(ID, -2000000000, InsertLifetime), ICA(0) {
     initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry());
   }
 
@@ -49,13 +49,13 @@ public:
 
   virtual InlineCost getInlineCost(CallSite CS);
 
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+  virtual bool runOnSCC(CallGraphSCC &SCC);
+
   using llvm::Pass::doFinalization;
   virtual bool doFinalization(CallGraph &CG) {
     return removeDeadFunctions(CG, /*AlwaysInlineOnly=*/ true);
   }
-
-  using llvm::Pass::doInitialization;
-  virtual bool doInitialization(CallGraph &CG);
 };
 
 }
@@ -64,6 +64,7 @@ char AlwaysInliner::ID = 0;
 INITIALIZE_PASS_BEGIN(AlwaysInliner, "always-inline",
                 "Inliner for always_inline functions", false, false)
 INITIALIZE_AG_DEPENDENCY(CallGraph)
+INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)
 INITIALIZE_PASS_END(AlwaysInliner, "always-inline",
                 "Inliner for always_inline functions", false, false)
 
@@ -94,13 +95,18 @@ InlineCost AlwaysInliner::getInlineCost(CallSite CS) {
   if (Callee && !Callee->isDeclaration() &&
       Callee->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
                                            Attribute::AlwaysInline) &&
-      CA.isInlineViable(*Callee))
+      ICA->isInlineViable(*Callee))
     return InlineCost::getAlways();
 
   return InlineCost::getNever();
 }
 
-bool AlwaysInliner::doInitialization(CallGraph &CG) {
-  CA.setDataLayout(getAnalysisIfAvailable<DataLayout>());
-  return false;
+bool AlwaysInliner::runOnSCC(CallGraphSCC &SCC) {
+  ICA = &getAnalysis<InlineCostAnalysis>();
+  return Inliner::runOnSCC(SCC);
+}
+
+void AlwaysInliner::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<InlineCostAnalysis>();
+  Inliner::getAnalysisUsage(AU);
 }
index b6a4e3725f691fc7bf4334984834cd0f8481171f..a4f7026041886ba8f28193578bd8a5b49ab06215 100644 (file)
@@ -34,26 +34,26 @@ namespace {
 /// inliner pass and the always inliner pass. The two passes use different cost
 /// analyses to determine when to inline.
 class SimpleInliner : public Inliner {
-  InlineCostAnalyzer CA;
+  InlineCostAnalysis *ICA;
 
 public:
-  SimpleInliner() : Inliner(ID) {
+  SimpleInliner() : Inliner(ID), ICA(0) {
     initializeSimpleInlinerPass(*PassRegistry::getPassRegistry());
   }
 
   SimpleInliner(int Threshold)
-      : Inliner(ID, Threshold, /*InsertLifetime*/ true) {
+      : Inliner(ID, Threshold, /*InsertLifetime*/ true), ICA(0) {
     initializeSimpleInlinerPass(*PassRegistry::getPassRegistry());
   }
 
   static char ID; // Pass identification, replacement for typeid
 
   InlineCost getInlineCost(CallSite CS) {
-    return CA.getInlineCost(CS, getInlineThreshold(CS));
+    return ICA->getInlineCost(CS, getInlineThreshold(CS));
   }
 
-  using llvm::Pass::doInitialization;
-  virtual bool doInitialization(CallGraph &CG);
+  virtual bool runOnSCC(CallGraphSCC &SCC);
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const;
 };
 
 } // end anonymous namespace
@@ -62,6 +62,7 @@ char SimpleInliner::ID = 0;
 INITIALIZE_PASS_BEGIN(SimpleInliner, "inline",
                 "Function Integration/Inlining", false, false)
 INITIALIZE_AG_DEPENDENCY(CallGraph)
+INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)
 INITIALIZE_PASS_END(SimpleInliner, "inline",
                 "Function Integration/Inlining", false, false)
 
@@ -71,10 +72,12 @@ Pass *llvm::createFunctionInliningPass(int Threshold) {
   return new SimpleInliner(Threshold);
 }
 
-// doInitialization - Initializes the vector of functions that have been
-// annotated with the noinline attribute.
-bool SimpleInliner::doInitialization(CallGraph &CG) {
-  CA.setDataLayout(getAnalysisIfAvailable<DataLayout>());
-  return false;
+bool SimpleInliner::runOnSCC(CallGraphSCC &SCC) {
+  ICA = &getAnalysis<InlineCostAnalysis>();
+  return Inliner::runOnSCC(SCC);
 }
 
+void SimpleInliner::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<InlineCostAnalysis>();
+  Inliner::getAnalysisUsage(AU);
+}