Remove the "really gross hacks" that are there to deal with recursive functions.
authorChris Lattner <sabre@nondot.org>
Thu, 8 Apr 2004 06:34:31 +0000 (06:34 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 8 Apr 2004 06:34:31 +0000 (06:34 +0000)
Now we collect all of the call sites we are interested in inlining, then inline
them.  This entirely avoids issues with trying to inline a call site we got by
inlining another call site.  This also eliminates iterator invalidation issues.

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

lib/Transforms/IPO/InlineSimple.cpp
lib/Transforms/IPO/Inliner.cpp
lib/Transforms/IPO/Inliner.h

index 0c950c7ba3f4337062013ac3a4dd44449ad39657..c0d97c5515b00f534ac5cbb20f3c849a2fef664c 100644 (file)
@@ -217,13 +217,7 @@ int SimpleInliner::getInlineCost(CallSite CS) {
   // Don't inline into something too big, which would make it bigger.  Here, we
   // count each basic block as a single unit.
   //
-  // FIXME: THIS IS A TOTAL HACK.  The problem is that we don't keep track of
-  // which call sites are the result of an inlining operation.  Because of this,
-  // if we inline a recursive function into a callee, we will see a new call to
-  // the recursive function.  Every time we inline we get a new callsite for the
-  // function, which only stops when the caller reaches its inlining limit.
-  // Until the real problem is fixed, we apply this gnasty hack.
-  InlineCost += Caller->size();
+  InlineCost += Caller->size()/20;
 
 
   // Look at the size of the callee.  Each basic block counts as 20 units, and
index c0861f1b673c72ecd57611979dc4f64ac4e8074c..325631a79227d5641c816eb578187715c5c22302 100644 (file)
@@ -58,84 +58,67 @@ bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
     if (F == 0 || F->isExternal()) continue;
     DEBUG(std::cerr << "  Inspecting function: " << F->getName() << "\n");
 
+    // Scan through and identify all call sites ahead of time so that we only
+    // inline call sites in the original functions, not call sites that result
+    // in inlining other functions.
+    std::vector<CallSite> CallSites;
     for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
-      for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ) {
-        bool ShouldInc = true;
-        // Found a call or invoke instruction?
-        if (isa<CallInst>(I) || isa<InvokeInst>(I)) {
-          CallSite CS = CallSite::get(I);
-          if (Function *Callee = CS.getCalledFunction())
-            if (!Callee->isExternal() && !IsRecursiveFunction.count(Callee)) {
-              // Determine whether this is a function IN the SCC...
-              bool inSCC = SCCFunctions.count(Callee);
+      for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
+        CallSite CS = CallSite::get(I);
+        if (CS.getInstruction() && CS.getCalledFunction() &&
+            !CS.getCalledFunction()->isExternal())
+          CallSites.push_back(CS);
+      }
 
-              // Keep track of whether this is a directly recursive function.
-              if (Callee == F) IsRecursiveFunction.insert(F);
+    // Now that we have all of the call sites, loop over them and inline them if
+    // it looks profitable to do so.
+    for (unsigned i = 0, e = CallSites.size(); i != e; ++i) {
+      CallSite CS = CallSites[i];
+      Function *Callee = CS.getCalledFunction();
+      // Determine whether this is a function IN the SCC...
+      bool inSCC = SCCFunctions.count(Callee);
+    
+      // If the policy determines that we should inline this function,
+      // try to do so...
+      int InlineCost = inSCC ? getRecursiveInlineCost(CS) : getInlineCost(CS);
+      if (InlineCost >= (int)InlineThreshold) {
+        DEBUG(std::cerr << "    NOT Inlining: cost=" << InlineCost
+              << ", Call: " << *CS.getInstruction());
+      } else {
+        DEBUG(std::cerr << "    Inlining: cost=" << InlineCost
+              << ", Call: " << *CS.getInstruction());
+      
+        Function *Caller = CS.getInstruction()->getParent()->getParent();
 
-              // If the policy determines that we should inline this function,
-              // try to do so...
-              int InlineCost = inSCC ? getRecursiveInlineCost(CS) :
-                                       getInlineCost(CS);
-              if (InlineCost >= (int)InlineThreshold) {
-                DEBUG(std::cerr << "    NOT Inlining: cost=" << InlineCost
-                                << ", Call: " << *CS.getInstruction());
-              } else {
-                DEBUG(std::cerr << "    Inlining: cost=" << InlineCost
-                                << ", Call: " << *CS.getInstruction());
+        // Attempt to inline the function...
+        if (InlineFunction(CS)) {
+          ++NumInlined;
+  
+          if (Callee->hasOneUse())
+            if (ConstantPointerRef *CPR =
+                dyn_cast<ConstantPointerRef>(Callee->use_back()))
+              if (CPR->use_empty())
+                CPR->destroyConstant();
+        
+          // If we inlined the last possible call site to the function,
+          // delete the function body now.
+          if (Callee->use_empty() && Callee != Caller &&
+              (Callee->hasInternalLinkage() || Callee->hasLinkOnceLinkage())) {
+            DEBUG(std::cerr << "    -> Deleting dead function: "
+                  << (void*)Callee << Callee->getName() << "\n");
+            std::set<Function*>::iterator I = SCCFunctions.find(Callee);
+            if (I != SCCFunctions.end())    // Remove function from this SCC.
+              SCCFunctions.erase(I);
 
-                // Save an iterator to the instruction before the call if it
-                // exists, otherwise get an iterator at the end of the
-                // block... because the call will be destroyed.
-                //
-                BasicBlock::iterator SI;
-                if (I != BB->begin()) {
-                  SI = I; --SI;           // Instruction before the call...
-                } else {
-                  SI = BB->end();
-                }
-                
-                if (performInlining(CS, SCCFunctions)) {
-                  // Move to instruction before the call...
-                  I = (SI == BB->end()) ? BB->begin() : SI;
-                  ShouldInc = false; // Don't increment iterator until next time
-                  Changed = true;
-                }
-              }
-            }
+            Callee->getParent()->getFunctionList().erase(Callee);
+            ++NumDeleted;
+          }
+          Changed = true;
         }
-        if (ShouldInc) ++I;
       }
+    }
   }
-  return Changed;
-}
-
-bool Inliner::performInlining(CallSite CS, std::set<Function*> &SCC) {
-  Function *Callee = CS.getCalledFunction();
-  Function *Caller = CS.getInstruction()->getParent()->getParent();
 
-  // Attempt to inline the function...
-  if (!InlineFunction(CS)) return false;
-  ++NumInlined;
-  
-  if (Callee->hasOneUse())
-    if (ConstantPointerRef *CPR =
-        dyn_cast<ConstantPointerRef>(Callee->use_back()))
-      if (CPR->use_empty())
-        CPR->destroyConstant();
-  
-  // If we inlined the last possible call site to the function,
-  // delete the function body now.
-  if (Callee->use_empty() && Callee != Caller &&
-      (Callee->hasInternalLinkage() || Callee->hasLinkOnceLinkage())) {
-    DEBUG(std::cerr << "    -> Deleting dead function: " << (void*)Callee
-                    << Callee->getName() << "\n");
-    std::set<Function*>::iterator I = SCC.find(Callee);
-    if (I != SCC.end())       // Remove function from this SCC...
-      SCC.erase(I);
-
-    Callee->getParent()->getFunctionList().erase(Callee);
-    ++NumDeleted;
-  }
-  return true; 
+  return Changed;
 }
 
index 805876c54d6f7dd45bf640560fa20384c74369f1..b63fe2ac05cebb74b816f404a500f6a6eeff38e9 100644 (file)
@@ -56,12 +56,6 @@ struct Inliner : public CallGraphSCCPass {
 private:
   // InlineThreshold - Cache the value here for easy access.
   unsigned InlineThreshold;
-
-  // IsRecursiveFunction - This contains all functions which are directly
-  // recursive, which we do NOT want to inline into other functions.
-  std::set<Function*> IsRecursiveFunction;
-
-  bool performInlining(CallSite CS, std::set<Function*> &SCC);
 };
 
 } // End llvm namespace