BasicCallGraph patch

The current BasicCallGraph will miss call sites like this:
%tmp86 = call i8* (…)* bitcast (i8* ()* @find_ispell to i8* (…))( ) ; <i8> [#uses=1]

Here the direct user of @find_ispell is a ConstantExpr.
I added several lines of code to address this case.
Below is the output of command: svn diff lib/Analysis/IPA/CallGraph.cpp
Attached is LLVM asm files with such function calls.

Index: lib/Analysis/IPA/CallGraph.cpp

spell-1.0.bc (28 KB)

time-1.7.bc (21.2 KB)

The current BasicCallGraph will miss call sites like this:
%tmp86 = call i8* (...)* bitcast (i8* ()* @find_ispell to i8* (...)*)( )
    ; <i8*> [#uses=1]

Here the direct user of @find_ispell is a ConstantExpr.
I added several lines of code to address this case.
Below is the output of command: svn diff lib/Analysis/IPA/CallGraph.cpp
Attached is LLVM asm files with such function calls.

This is problematic, because it's not checking for the type of constant expr (i.e. is it a bitcast, etc). That can easily be fixed, but here's a basic question: when is this important? The instcombine pass should fix up these bitcasts, so they shouldn't occur frequently in practice. When have you found this to be important?

Thanks,

-Chris

Index: lib/Analysis/IPA/CallGraph.cpp

--- lib/Analysis/IPA/CallGraph.cpp (revision 39771)
+++ lib/Analysis/IPA/CallGraph.cpp (working copy)
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/CallGraph.h"
+#include "llvm/Constants.h"
# include "llvm/Module.h"
# include "llvm/Instructions.h"
# include "llvm/Support/CallSite.h"
@@ -150,6 +151,19 @@
              -> addCalledFunction(CS, Node);
         else
         isUsedExternally = true;
+ } else if (ConstantExpr* CE = dyn_cast<ConstantExpr>(*I)) {
+ for (Value::use_iterator I = CE->use_begin(), E = CE->use_end();
+ I != E; ++I)
+ if (Instruction* Inst = dyn_cast<Instruction>(*I)) {
+ CallSite CS = CallSite::get(Inst);
+ if (isOnlyADirectCall(F, CS))
+ getOrInsertFunction(Inst->getParent()->getParent())
+ ->addCalledFunction(CS, Node);
+ else
+ isUsedExternally = true;
+ } else {
+ isUsedExternally = true;
+ }
       } else if (GlobalValue *GV = dyn_cast<GlobalValue>(*I)) {
         for (Value::use_iterator I = GV->use_begin(), E = GV->use_end();
              I != E; ++I)

-Chris

I am doing inter-procedural static analysis, so I need to do DFS of call graph. llvm-gcc sometimes generates this kind of call instruction, which cause the call graph to be incomplete.

But thanks for your information, instcombine really solves the problem.

I am doing inter-procedural static analysis, so I need to do DFS of call
graph. llvm-gcc sometimes generates this kind of call instruction, which
cause the call graph to be incomplete.

But thanks for your information, instcombine really solves the problem.

Happy to help. You'll probably find that other optimizations help as well, such as simplifycfg (which deletes dead blocks). Depending on what you are doing, using the LLVM IR can be tricky for this sort of stuff because it can get too far from the source level.

-Chris

Happy to help. You’ll probably find that other optimizations help as
well, such as simplifycfg (which deletes dead blocks).

Thank you. I am using it.

Depending on what
you are doing, using the LLVM IR can be tricky for this sort of stuff
because it can get too far from the source level.

Yes, it is really a problem. Now I am using my eyes to map the LLVM IR back to the source code. But it’s tedious and error prone. Is there any better way to do this? I guess carrying debug information in LLVM IR might help. But I don’t know how to use the debug information.

Is there any better way to do this? I guess carrying
debug information in LLVM IR might help. But I don't know how
to use the debug information.

Please keep in mind that I'm not really clueful in this area, but
maybe you need to investigate the debug information to get a
relationship between line numbers and basic blocks.

Debug information is one way to do it. Another way to do it is to use source-level analysis techniquese. When the new C front-end is farther along, it is our goal to support this. Unfortunately, it is still too early.

-Chris