Inlining and unrolling heuristics should be aware of free truncs.
authorAndrew Trick <atrick@apple.com>
Sat, 1 Oct 2011 01:39:05 +0000 (01:39 +0000)
committerAndrew Trick <atrick@apple.com>
Sat, 1 Oct 2011 01:39:05 +0000 (01:39 +0000)
We want heuristics to be based on accurate data, but more importantly
we don't want llvm to behave randomly. A benign trunc inserted by an
upstream pass should not cause a wild swings in optimization
level. See PR11034. It's a general problem with threshold-based
heuristics, but we can make it less bad.

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

include/llvm/Analysis/CodeMetrics.h
include/llvm/Analysis/InlineCost.h
lib/Analysis/InlineCost.cpp
lib/Transforms/IPO/InlineAlways.cpp
lib/Transforms/IPO/InlineSimple.cpp
lib/Transforms/Scalar/LoopUnrollPass.cpp

index 9433d07a2b56eeb2c9537b4f4ce6d45cf0f116b5..d96dd82b3591400968c25eed93bc5434c266a053 100644 (file)
@@ -18,6 +18,9 @@
 #include "llvm/ADT/DenseMap.h"
 
 namespace llvm {
+
+  class TargetData;
+
   // CodeMetrics - Calculate size and a few similar metrics for a set of
   // basic blocks.
   struct CodeMetrics {
@@ -68,11 +71,11 @@ namespace llvm {
 
     /// analyzeBasicBlock - Add information about the specified basic block
     /// to the current structure.
-    void analyzeBasicBlock(const BasicBlock *BB);
+    void analyzeBasicBlock(const BasicBlock *BB, const TargetData *TD = 0);
 
     /// analyzeFunction - Add information about the specified function
     /// to the current structure.
-    void analyzeFunction(Function *F);
+    void analyzeFunction(Function *F, const TargetData *TD = 0);
 
     /// CountCodeReductionForConstant - Figure out an approximation for how
     /// many instructions will be constant folded if the specified value is
index a0cce515e9e2ba6d42bc1aaefba439ecf6590b86..36a16e68df0769d16c8ed7937f7180bdcd13d0c7 100644 (file)
@@ -29,6 +29,7 @@ namespace llvm {
   class CallSite;
   template<class PtrType, unsigned SmallSize>
   class SmallPtrSet;
+  class TargetData;
 
   namespace InlineConstants {
     // Various magic constants used to adjust heuristics.
@@ -113,7 +114,7 @@ namespace llvm {
 
       /// analyzeFunction - Add information about the specified function
       /// to the current structure.
-      void analyzeFunction(Function *F);
+      void analyzeFunction(Function *F, const TargetData *TD);
 
       /// NeverInline - Returns true if the function should never be
       /// inlined into any caller.
@@ -124,11 +125,17 @@ namespace llvm {
     // the ValueMap will update itself when this happens.
     ValueMap<const Function *, FunctionInfo> CachedFunctionInfo;
 
+    // TargetData if available, or null.
+    const TargetData *TD;
+
     int CountBonusForConstant(Value *V, Constant *C = NULL);
     int ConstantFunctionBonus(CallSite CS, Constant *C);
     int getInlineSize(CallSite CS, Function *Callee);
     int getInlineBonuses(CallSite CS, Function *Callee);
   public:
+    InlineCostAnalyzer(): TD(0) {}
+
+    void setTargetData(const TargetData *TData) { TD = TData; }
 
     /// getInlineCost - The heuristic used to determine if we should inline the
     /// function call or not.
index 7ec7ae525b22ae374f99d03ce9d86b3076144736..e12e322c2a99441b0fe716c5c4f2bf255b85d34a 100644 (file)
@@ -15,6 +15,7 @@
 #include "llvm/Support/CallSite.h"
 #include "llvm/CallingConv.h"
 #include "llvm/IntrinsicInst.h"
+#include "llvm/Target/TargetData.h"
 #include "llvm/ADT/SmallPtrSet.h"
 
 using namespace llvm;
@@ -52,7 +53,8 @@ bool llvm::callIsSmall(const Function *F) {
 
 /// analyzeBasicBlock - Fill in the current structure with information gleaned
 /// from the specified block.
-void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) {
+void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB,
+                                    const TargetData *TD) {
   ++NumBlocks;
   unsigned NumInstsBeforeThisBB = NumInsts;
   for (BasicBlock::const_iterator II = BB->begin(), E = BB->end();
@@ -105,6 +107,11 @@ void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) {
       if (CI->isLosslessCast() || isa<IntToPtrInst>(CI) ||
           isa<PtrToIntInst>(CI))
         continue;
+      // trunc to a native type is free (assuming the target has compare and
+      // shift-right of the same width).
+      if (isa<TruncInst>(CI) && TD &&
+          TD->isLegalInteger(TD->getTypeSizeInBits(CI->getType())))
+        continue;
       // Result of a cmp instruction is often extended (to be used by other
       // cmp instructions, logical or return instructions). These are usually
       // nop on most sane targets.
@@ -217,7 +224,7 @@ unsigned CodeMetrics::CountCodeReductionForAlloca(Value *V) {
 
 /// analyzeFunction - Fill in the current structure with information gleaned
 /// from the specified function.
-void CodeMetrics::analyzeFunction(Function *F) {
+void CodeMetrics::analyzeFunction(Function *F, const TargetData *TD) {
   // If this function contains a call to setjmp or _setjmp, never inline
   // it.  This is a hack because we depend on the user marking their local
   // variables as volatile if they are live across a setjmp call, and they
@@ -227,13 +234,14 @@ void CodeMetrics::analyzeFunction(Function *F) {
 
   // Look at the size of the callee.
   for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
-    analyzeBasicBlock(&*BB);
+    analyzeBasicBlock(&*BB, TD);
 }
 
 /// analyzeFunction - Fill in the current structure with information gleaned
 /// from the specified function.
-void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) {
-  Metrics.analyzeFunction(F);
+void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F,
+                                                       const TargetData *TD) {
+  Metrics.analyzeFunction(F, TD);
 
   // A function with exactly one return has it removed during the inlining
   // process (see InlineFunction), so don't count it.
@@ -275,7 +283,7 @@ int InlineCostAnalyzer::getSpecializationBonus(Function *Callee,
 
   // If we haven't calculated this information yet, do so now.
   if (CalleeFI->Metrics.NumBlocks == 0)
-    CalleeFI->analyzeFunction(Callee);
+    CalleeFI->analyzeFunction(Callee, TD);
 
   unsigned ArgNo = 0;
   unsigned i = 0;
@@ -365,7 +373,7 @@ int InlineCostAnalyzer::getInlineSize(CallSite CS, Function *Callee) {
 
   // If we haven't calculated this information yet, do so now.
   if (CalleeFI->Metrics.NumBlocks == 0)
-    CalleeFI->analyzeFunction(Callee);
+    CalleeFI->analyzeFunction(Callee, TD);
 
   // InlineCost - This value measures how good of an inline candidate this call
   // site is to inline.  A lower inline cost make is more likely for the call to
@@ -418,7 +426,7 @@ int InlineCostAnalyzer::getInlineBonuses(CallSite CS, Function *Callee) {
 
   // If we haven't calculated this information yet, do so now.
   if (CalleeFI->Metrics.NumBlocks == 0)
-    CalleeFI->analyzeFunction(Callee);
+    CalleeFI->analyzeFunction(Callee, TD);
 
   bool isDirectCall = CS.getCalledFunction() == Callee;
   Instruction *TheCall = CS.getInstruction();
@@ -486,7 +494,7 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS,
 
   // If we haven't calculated this information yet, do so now.
   if (CalleeFI->Metrics.NumBlocks == 0)
-    CalleeFI->analyzeFunction(Callee);
+    CalleeFI->analyzeFunction(Callee, TD);
 
   // If we should never inline this, return a huge cost.
   if (CalleeFI->NeverInline())
@@ -505,7 +513,7 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS,
 
     // If we haven't calculated this information yet, do so now.
     if (CallerFI.Metrics.NumBlocks == 0) {
-      CallerFI.analyzeFunction(Caller);
+      CallerFI.analyzeFunction(Caller, TD);
 
       // Recompute the CalleeFI pointer, getting Caller could have invalidated
       // it.
@@ -544,7 +552,7 @@ InlineCost InlineCostAnalyzer::getSpecializationCost(Function *Callee,
 
   // If we haven't calculated this information yet, do so now.
   if (CalleeFI->Metrics.NumBlocks == 0)
-    CalleeFI->analyzeFunction(Callee);
+    CalleeFI->analyzeFunction(Callee, TD);
 
   int Cost = 0;
 
@@ -570,7 +578,7 @@ float InlineCostAnalyzer::getInlineFudgeFactor(CallSite CS) {
 
   // If we haven't calculated this information yet, do so now.
   if (CalleeFI.Metrics.NumBlocks == 0)
-    CalleeFI.analyzeFunction(Callee);
+    CalleeFI.analyzeFunction(Callee, TD);
 
   float Factor = 1.0f;
   // Single BB functions are often written to be inlined.
index 50cccd51a069e4d2966e943667d8dd6ab2f8e6e6..c0426da2c687ef0cde4707bbb4041988a1a8ef13 100644 (file)
@@ -23,6 +23,7 @@
 #include "llvm/Support/CallSite.h"
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Transforms/IPO/InlinerPass.h"
+#include "llvm/Target/TargetData.h"
 #include "llvm/ADT/SmallPtrSet.h"
 
 using namespace llvm;
@@ -74,6 +75,8 @@ Pass *llvm::createAlwaysInlinerPass() { return new AlwaysInliner(); }
 // doInitialization - Initializes the vector of functions that have not
 // been annotated with the "always inline" attribute.
 bool AlwaysInliner::doInitialization(CallGraph &CG) {
+  CA.setTargetData(getAnalysisIfAvailable<TargetData>());
+
   Module &M = CG.getModule();
 
   for (Module::iterator I = M.begin(), E = M.end();
index 1ebe7c97e0b72800ce5b7a334e638ddcf7ef5e58..84dd4fdd988785e8212c4c53d06f6f34d77f843c 100644 (file)
@@ -22,6 +22,7 @@
 #include "llvm/Support/CallSite.h"
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Transforms/IPO/InlinerPass.h"
+#include "llvm/Target/TargetData.h"
 #include "llvm/ADT/SmallPtrSet.h"
 
 using namespace llvm;
@@ -75,6 +76,7 @@ Pass *llvm::createFunctionInliningPass(int Threshold) {
 // doInitialization - Initializes the vector of functions that have been
 // annotated with the noinline attribute.
 bool SimpleInliner::doInitialization(CallGraph &CG) {
+  CA.setTargetData(getAnalysisIfAvailable<TargetData>());
 
   Module &M = CG.getModule();
 
index cca7ba0bd4e47b40f15d000763fce02ba68bcf61..91395b2af6aab0362300838a1b1878fa12398a35 100644 (file)
@@ -22,6 +22,7 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/Utils/UnrollLoop.h"
+#include "llvm/Target/TargetData.h"
 #include <climits>
 
 using namespace llvm;
@@ -107,11 +108,12 @@ Pass *llvm::createLoopUnrollPass(int Threshold, int Count, int AllowPartial) {
 }
 
 /// ApproximateLoopSize - Approximate the size of the loop.
-static unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls) {
+static unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls,
+                                    const TargetData *TD) {
   CodeMetrics Metrics;
   for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
        I != E; ++I)
-    Metrics.analyzeBasicBlock(*I);
+    Metrics.analyzeBasicBlock(*I, TD);
   NumCalls = Metrics.NumInlineCandidates;
 
   unsigned LoopSize = Metrics.NumInsts;
@@ -174,8 +176,9 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) {
 
   // Enforce the threshold.
   if (Threshold != NoThreshold) {
+    const TargetData *TD = getAnalysisIfAvailable<TargetData>();
     unsigned NumInlineCandidates;
-    unsigned LoopSize = ApproximateLoopSize(L, NumInlineCandidates);
+    unsigned LoopSize = ApproximateLoopSize(L, NumInlineCandidates, TD);
     DEBUG(dbgs() << "  Loop Size = " << LoopSize << "\n");
     if (NumInlineCandidates != 0) {
       DEBUG(dbgs() << "  Not unrolling loop with inlinable calls.\n");