Make the call graph more precise despite the hated constantpointerrefs.
authorChris Lattner <sabre@nondot.org>
Fri, 31 Oct 2003 21:05:12 +0000 (21:05 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 31 Oct 2003 21:05:12 +0000 (21:05 +0000)
Do you detect the animosity I feel towards CPRs yet?

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

lib/Analysis/IPA/CallGraph.cpp

index f5be91c8acfbf5c7464b329ce6f4dc96a1763bbf..7c0deddc3a16aba9b80089969daab18e3adfe74d 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Analysis/CallGraph.h"
+#include "llvm/Constants.h"     // Remove when ConstantPointerRefs are gone
 #include "llvm/Module.h"
 #include "llvm/iOther.h"
 #include "llvm/iTerminators.h"
+#include "llvm/Support/CallSite.h"
 #include "Support/STLExtras.h"
 
 static RegisterAnalysis<CallGraph> X("callgraph", "Call Graph Construction");
@@ -184,6 +186,13 @@ CallGraphNode *CallGraph::getNodeFor(Function *F) {
   return CGN = new CallGraphNode(F);
 }
 
+static bool isOnlyADirectCall(Function *F, CallSite CS) {
+  if (!CS.getInstruction()) return false;
+  for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I)
+    if (*I == F) return false;
+  return true;
+}
+
 // addToCallGraph - Add a function to the call graph, and link the node to all
 // of the functions that it calls.
 //
@@ -211,28 +220,39 @@ void CallGraph::addToCallGraph(Function *F) {
 
   // Loop over all of the users of the function... looking for callers...
   //
+  bool isUsedExternally = false;
   for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; ++I) {
-    User *U = *I;
-    if (CallInst *CI = dyn_cast<CallInst>(U))
-      getNodeFor(CI->getParent()->getParent())->addCalledFunction(Node);
-    else if (InvokeInst *II = dyn_cast<InvokeInst>(U))
-      getNodeFor(II->getParent()->getParent())->addCalledFunction(Node);
-    else                         // Can't classify the user!
-      ExternalNode->addCalledFunction(Node);
+    if (Instruction *Inst = dyn_cast<Instruction>(*I)) {
+      if (isOnlyADirectCall(F, CallSite::get(Inst)))
+        getNodeFor(Inst->getParent()->getParent())->addCalledFunction(Node);
+      else
+        isUsedExternally = true;
+    } else if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(*I)) {
+      // THIS IS A DISGUSTING HACK.  Brought to you by the power of
+      // ConstantPointerRefs!
+      for (Value::use_iterator I = CPR->use_begin(), E = CPR->use_end();
+           I != E; ++I)
+        if (Instruction *Inst = dyn_cast<Instruction>(*I)) {
+          if (isOnlyADirectCall(F, CallSite::get(Inst)))
+            getNodeFor(Inst->getParent()->getParent())->addCalledFunction(Node);
+          else
+            isUsedExternally = true;
+        } else {
+          isUsedExternally = true;
+        }
+    } else {                        // Can't classify the user!
+      isUsedExternally = true;
+    }
   }
+  if (isUsedExternally)
+    ExternalNode->addCalledFunction(Node);
 
   // Look for an indirect function call...
   for (Function::iterator BB = F->begin(), BBE = F->end(); BB != BBE; ++BB)
     for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE; ++II){
-      Instruction &I = *II;
-
-      if (CallInst *CI = dyn_cast<CallInst>(&I)) {
-        if (CI->getCalledFunction() == 0)
-          Node->addCalledFunction(ExternalNode);
-      } else if (InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
-        if (II->getCalledFunction() == 0)
-          Node->addCalledFunction(ExternalNode);
-      }
+      CallSite CS = CallSite::get(II);
+      if (CS.getInstruction() && !CS.getCalledFunction())
+        Node->addCalledFunction(ExternalNode);
     }
 }