Fix bug where array malloc with unexpected computation of the size argument resulted...
[oota-llvm.git] / lib / Analysis / IPA / CallGraphSCCPass.cpp
index f7c38e2cce28c0422cd2efe8c48ae060533f17b9..a96a5c591f831f9de56ccb8e05b57c5dd0932fbe 100644 (file)
 #include "llvm/PassManagers.h"
 #include "llvm/Function.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/IntrinsicInst.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace llvm;
 
 //===----------------------------------------------------------------------===//
 // CGPassManager
 //
-/// CGPassManager manages FPPassManagers and CalLGraphSCCPasses.
+/// CGPassManager manages FPPassManagers and CallGraphSCCPasses.
 
 namespace {
 
@@ -94,10 +95,10 @@ bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
       RefreshCallGraph(CurSCC, CG, false);
       CallGraphUpToDate = true;
     }
-    
-    StartPassTimer(P);
+
+    Timer *T = StartPassTimer(CGSP);
     Changed = CGSP->runOnSCC(CurSCC);
-    StopPassTimer(P);
+    StopPassTimer(CGSP, T);
     
     // After the CGSCCPass is done, when assertions are enabled, use
     // RefreshCallGraph to verify that the callgraph was correctly updated.
@@ -109,7 +110,6 @@ bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
     return Changed;
   }
   
-  StartPassTimer(P);
   FPPassManager *FPP = dynamic_cast<FPPassManager *>(P);
   assert(FPP && "Invalid CGPassManager member");
   
@@ -117,10 +117,11 @@ bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
   for (unsigned i = 0, e = CurSCC.size(); i != e; ++i) {
     if (Function *F = CurSCC[i]->getFunction()) {
       dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName());
+      Timer *T = StartPassTimer(FPP);
       Changed |= FPP->runOnFunction(*F);
+      StopPassTimer(FPP, T);
     }
   }
-  StopPassTimer(P);
   
   // The function pass(es) modified the IR, they may have clobbered the
   // callgraph.
@@ -160,7 +161,7 @@ void CGPassManager::RefreshCallGraph(std::vector<CallGraphNode*> &CurSCC,
     // CGN with those actually in the function.
     
     // Get the set of call sites currently in the function.
-    for (CallGraphNode::iterator I = CGN->begin(), E = CGN->end(); I != E; ){
+    for (CallGraphNode::iterator I = CGN->begin(), E = CGN->end(); I != E; ) {
       // If this call site is null, then the function pass deleted the call
       // entirely and the WeakVH nulled it out.  
       if (I->first == 0 ||
@@ -176,8 +177,16 @@ void CGPassManager::RefreshCallGraph(std::vector<CallGraphNode*> &CurSCC,
         assert(!CheckingMode &&
                "CallGraphSCCPass did not update the CallGraph correctly!");
         
-        // Just remove the edge from the set of callees.
+        // Just remove the edge from the set of callees, keep track of whether
+        // I points to the last element of the vector.
+        bool WasLast = I + 1 == E;
         CGN->removeCallEdge(I);
+        
+        // If I pointed to the last element of the vector, we have to bail out:
+        // iterator checking rejects comparisons of the resultant pointer with
+        // end.
+        if (WasLast)
+          break;
         E = CGN->end();
         continue;
       }
@@ -192,7 +201,7 @@ void CGPassManager::RefreshCallGraph(std::vector<CallGraphNode*> &CurSCC,
     for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
       for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
         CallSite CS = CallSite::get(I);
-        if (!CS.getInstruction()) continue;
+        if (!CS.getInstruction() || isa<DbgInfoIntrinsic>(I)) continue;
         
         // If this call site already existed in the callgraph, just verify it
         // matches up to expectations and remove it from CallSites.
@@ -227,8 +236,15 @@ void CGPassManager::RefreshCallGraph(std::vector<CallGraphNode*> &CurSCC,
             CalleeNode = CG.getOrInsertFunction(Callee);
           else
             CalleeNode = CG.getCallsExternalNode();
-          
-          ExistingIt->second = CalleeNode;
+
+          // Update the edge target in CGN.
+          for (CallGraphNode::iterator I = CGN->begin(); ; ++I) {
+            assert(I != CGN->end() && "Didn't find call entry");
+            if (I->first == CS.getInstruction()) {
+              I->second = CalleeNode;
+              break;
+            }
+          }
           MadeChange = true;
           continue;
         }
@@ -301,7 +317,20 @@ bool CGPassManager::runOnModule(Module &M) {
          PassNo != e; ++PassNo) {
       Pass *P = getContainedPass(PassNo);
 
-      dumpPassInfo(P, EXECUTION_MSG, ON_CG_MSG, "");
+      // If we're in -debug-pass=Executions mode, construct the SCC node list,
+      // otherwise avoid constructing this string as it is expensive.
+      if (isPassDebuggingExecutionsOrMore()) {
+        std::string Functions;
+#ifndef NDEBUG
+        raw_string_ostream OS(Functions);
+        for (unsigned i = 0, e = CurSCC.size(); i != e; ++i) {
+          if (i) OS << ", ";
+          CurSCC[i]->print(OS);
+        }
+        OS.flush();
+#endif
+        dumpPassInfo(P, EXECUTION_MSG, ON_CG_MSG, Functions);
+      }
       dumpRequiredSet(P);
 
       initializeAnalysisImpl(P);