OSDN Git Service

Start separating out code metrics into code size metrics and code performance metrics...
authorKenneth Uildriks <kennethuil@gmail.com>
Fri, 8 Oct 2010 13:57:31 +0000 (13:57 +0000)
committerKenneth Uildriks <kennethuil@gmail.com>
Fri, 8 Oct 2010 13:57:31 +0000 (13:57 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116057 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/CodeMetrics.h
include/llvm/Analysis/InlineCost.h
lib/Analysis/InlineCost.cpp

index 1a67409..e89ad90 100644 (file)
@@ -77,7 +77,12 @@ namespace llvm {
     /// many instructions will be constant folded if the specified value is
     /// constant.
     unsigned CountCodeReductionForConstant(Value *V);
-    
+   
+    /// CountBonusForConstant - Figure out an approximation for how much
+    /// per-call performance boost we can expect if the specified value is
+    /// constant.
+    unsigned CountBonusForConstant(Value *V);
+
     /// CountCodeReductionForAlloca - Figure out an approximation of how much
     /// smaller the function will be if it is inlined into a context where an
     /// argument becomes an alloca.
index b3b9395..9963ba4 100644 (file)
@@ -96,9 +96,11 @@ namespace llvm {
     public:
       unsigned ConstantWeight;
       unsigned AllocaWeight;
+      unsigned ConstantBonus;
 
-      ArgInfo(unsigned CWeight, unsigned AWeight)
-        : ConstantWeight(CWeight), AllocaWeight(AWeight) {}
+      ArgInfo(unsigned CWeight, unsigned AWeight, unsigned CBonus)
+        : ConstantWeight(CWeight), AllocaWeight(AWeight), ConstantBonus(CBonus)
+          {}
     };
 
     struct FunctionInfo {
index afdf474..a0e2ec7 100644 (file)
@@ -142,6 +142,55 @@ void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) {
   NumBBInsts[BB] = NumInsts - NumInstsBeforeThisBB;
 }
 
+// CountBonusForConstant - Figure out an approximation for how much per-call
+// performance boost we can expect if the specified value is constant.
+unsigned CodeMetrics::CountBonusForConstant(Value *V) {
+  unsigned Bonus = 0;
+  for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){
+    User *U = *UI;
+    if (CallInst *CI = dyn_cast<CallInst>(U)) {
+      // Turning an indirect call into a direct call is a BIG win
+      if (CI->getCalledValue() == V)
+        Bonus += InlineConstants::IndirectCallBonus;
+    }
+    else if (InvokeInst *II = dyn_cast<InvokeInst>(U)) {
+      // Turning an indirect call into a direct call is a BIG win
+      if (II->getCalledValue() == V)
+        Bonus += InlineConstants::IndirectCallBonus;
+    }
+    // FIXME: Eliminating conditional branches and switches should
+    // also yield a per-call performance boost.
+    else {
+      // Figure out the bonuses that wll accrue due to simple constant
+      // propagation.
+      Instruction &Inst = cast<Instruction>(*U);
+
+      // We can't constant propagate instructions which have effects or
+      // read memory.
+      //
+      // FIXME: It would be nice to capture the fact that a load from a
+      // pointer-to-constant-global is actually a *really* good thing to zap.
+      // Unfortunately, we don't know the pointer that may get propagated here,
+      // so we can't make this decision.
+      if (Inst.mayReadFromMemory() || Inst.mayHaveSideEffects() ||
+          isa<AllocaInst>(Inst))
+        continue;
+
+      bool AllOperandsConstant = true;
+      for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i)
+        if (!isa<Constant>(Inst.getOperand(i)) && Inst.getOperand(i) != V) {
+          AllOperandsConstant = false;
+          break;
+        }
+
+      if (AllOperandsConstant)
+        Bonus += CountBonusForConstant(&Inst);
+    }
+  }
+  return Bonus;
+}
+
+
 // CountCodeReductionForConstant - Figure out an approximation for how many
 // instructions will be constant folded if the specified value is constant.
 //
@@ -158,14 +207,6 @@ unsigned CodeMetrics::CountCodeReductionForConstant(Value *V) {
         Instrs += NumBBInsts[TI.getSuccessor(I)];
       // We don't know which blocks will be eliminated, so use the average size.
       Reduction += InlineConstants::InstrCost*Instrs*(NumSucc-1)/NumSucc;
-    } else if (CallInst *CI = dyn_cast<CallInst>(U)) {
-      // Turning an indirect call into a direct call is a BIG win
-      if (CI->getCalledValue() == V)
-        Reduction += InlineConstants::IndirectCallBonus;
-    } else if (InvokeInst *II = dyn_cast<InvokeInst>(U)) {
-      // Turning an indirect call into a direct call is a BIG win
-      if (II->getCalledValue() == V)
-        Reduction += InlineConstants::IndirectCallBonus;
     } else {
       // Figure out if this instruction will be removed due to simple constant
       // propagation.
@@ -259,7 +300,8 @@ void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) {
   ArgumentWeights.reserve(F->arg_size());
   for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
     ArgumentWeights.push_back(ArgInfo(Metrics.CountCodeReductionForConstant(I),
-                                      Metrics.CountCodeReductionForAlloca(I)));
+                                      Metrics.CountCodeReductionForAlloca(I),
+                                      Metrics.CountBonusForConstant(I)));
 }
 
 /// NeverInline - returns true if the function should never be inlined into
@@ -383,7 +425,8 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS,
       // away with this information.
     } else if (isa<Constant>(I)) {
       if (ArgNo < CalleeFI->ArgumentWeights.size())
-        InlineCost -= CalleeFI->ArgumentWeights[ArgNo].ConstantWeight;
+        InlineCost -= (CalleeFI->ArgumentWeights[ArgNo].ConstantWeight +
+                       CalleeFI->ArgumentWeights[ArgNo].ConstantBonus);
     }
   }