add an assertion to make it clear that PHI nodes are not allowed.
[oota-llvm.git] / lib / Transforms / IPO / Inliner.cpp
index 5718835995616e65ef72d47f64e3d537a62ca44f..ed177478e167448161904cc5b798ceb2905a3067 100644 (file)
@@ -54,11 +54,21 @@ static bool InlineCallIfPossible(CallSite CS, CallGraph &CG,
                                  const std::set<Function*> &SCCFunctions,
                                  const TargetData &TD) {
   Function *Callee = CS.getCalledFunction();
+  Function *Caller = CS.getCaller();
+
   if (!InlineFunction(CS, &CG, &TD)) return false;
 
+  // If the inlined function had a higher stack protection level than the
+  // calling function, then bump up the caller's stack protection level.
+  if (Callee->hasFnAttr(Attribute::StackProtectReq))
+    Caller->addFnAttr(Attribute::StackProtectReq);
+  else if (Callee->hasFnAttr(Attribute::StackProtect) &&
+           !Caller->hasFnAttr(Attribute::StackProtectReq))
+    Caller->addFnAttr(Attribute::StackProtect);
+
   // If we inlined the last possible call site to the function, delete the
   // function body now.
-  if (Callee->use_empty() && Callee->hasInternalLinkage() &&
+  if (Callee->use_empty() && Callee->hasLocalLinkage() &&
       !SCCFunctions.count(Callee)) {
     DOUT << "    -> Deleting dead function: " << Callee->getName() << "\n";
     CallGraphNode *CalleeNode = CG[Callee];
@@ -72,6 +82,44 @@ static bool InlineCallIfPossible(CallSite CS, CallGraph &CG,
   }
   return true;
 }
+        
+/// shouldInline - Return true if the inliner should attempt to inline
+/// at the given CallSite.
+bool Inliner::shouldInline(CallSite CS) {
+  InlineCost IC = getInlineCost(CS);
+  float FudgeFactor = getInlineFudgeFactor(CS);
+  
+  if (IC.isAlways()) {
+    DOUT << "    Inlining: cost=always"
+         << ", Call: " << *CS.getInstruction();
+    return true;
+  }
+  
+  if (IC.isNever()) {
+    DOUT << "    NOT Inlining: cost=never"
+         << ", Call: " << *CS.getInstruction();
+    return false;
+  }
+  
+  int Cost = IC.getValue();
+  int CurrentThreshold = InlineThreshold;
+  Function *Fn = CS.getCaller();
+  if (Fn && !Fn->isDeclaration() 
+      && Fn->hasFnAttr(Attribute::OptimizeForSize)
+      && InlineThreshold != 50) {
+    CurrentThreshold = 50;
+  }
+  
+  if (Cost >= (int)(CurrentThreshold * FudgeFactor)) {
+    DOUT << "    NOT Inlining: cost=" << Cost
+         << ", Call: " << *CS.getInstruction();
+    return false;
+  } else {
+    DOUT << "    Inlining: cost=" << Cost
+         << ", Call: " << *CS.getInstruction();
+    return true;
+  }
+}
 
 bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
   CallGraph &CG = getAnalysis<CallGraph>();
@@ -120,8 +168,7 @@ bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
     for (unsigned CSi = 0; CSi != CallSites.size(); ++CSi)
       if (Function *Callee = CallSites[CSi].getCalledFunction()) {
         // Calls to external functions are never inlinable.
-        if (Callee->isDeclaration() ||
-            CallSites[CSi].getInstruction()->getParent()->getParent() ==Callee){
+        if (Callee->isDeclaration()) {
           if (SCC.size() == 1) {
             std::swap(CallSites[CSi], CallSites.back());
             CallSites.pop_back();
@@ -136,26 +183,16 @@ bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
         // If the policy determines that we should inline this function,
         // try to do so.
         CallSite CS = CallSites[CSi];
-        int InlineCost = getInlineCost(CS);
-        float FudgeFactor = getInlineFudgeFactor(CS);
-        
-        int CurrentThreshold = InlineThreshold;
-        Function *Fn = CS.getCaller();
-        if (Fn && !Fn->isDeclaration() && Fn->hasNote(FnAttr::OptimizeForSize)
-            && InlineThreshold != 50) {
-          CurrentThreshold = 50;
-        }
-        
-        if (InlineCost >= (int)(CurrentThreshold * FudgeFactor)) {
-          DOUT << "    NOT Inlining: cost=" << InlineCost
-               << ", Call: " << *CS.getInstruction();
-        } else {
-          DOUT << "    Inlining: cost=" << InlineCost
-               << ", Call: " << *CS.getInstruction();
-
+        if (shouldInline(CS)) {
+          Function *Caller = CS.getCaller();
           // Attempt to inline the function...
           if (InlineCallIfPossible(CS, CG, SCCFunctions, 
                                    getAnalysis<TargetData>())) {
+            // Remove any cached cost info for this caller, as inlining the callee
+            // has increased the size of the caller (which may be the same as the
+            // callee).
+            resetCachedCostInfo(Caller);
+
             // Remove this call site from the list.  If possible, use 
             // swap/pop_back for efficiency, but do not use it if doing so would
             // move a call site to a function in this SCC before the
@@ -182,6 +219,13 @@ bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
 // doFinalization - Remove now-dead linkonce functions at the end of
 // processing to avoid breaking the SCC traversal.
 bool Inliner::doFinalization(CallGraph &CG) {
+  return removeDeadFunctions(CG);
+}
+
+  /// removeDeadFunctions - Remove dead functions that are not included in
+  /// DNR (Do Not Remove) list.
+bool Inliner::removeDeadFunctions(CallGraph &CG, 
+                                 SmallPtrSet<const Function *, 16> *DNR) {
   std::set<CallGraphNode*> FunctionsToRemove;
 
   // Scan for all of the functions, looking for ones that should now be removed
@@ -193,7 +237,10 @@ bool Inliner::doFinalization(CallGraph &CG) {
       // them.
       F->removeDeadConstantUsers();
 
-      if ((F->hasLinkOnceLinkage() || F->hasInternalLinkage()) &&
+      if (DNR && DNR->count(F))
+        continue;
+
+      if ((F->hasLinkOnceLinkage() || F->hasLocalLinkage()) &&
           F->use_empty()) {
 
         // Remove any call graph edges from the function to its callees.