CallTargets: Fix callee sorting, printing, add test.
* Print caller instruction (not just its address)
* sort/unique by pointer value to ensure no duplicates,
then sort alphabetically for reading.
* std::unique does NOT take same comparator as std::sort,
which was a silly mistake. Fixed.
llvm-svn: 238449
diff --git a/poolalloc/lib/DSA/CallTargets.cpp b/poolalloc/lib/DSA/CallTargets.cpp
index 4306d30..372138d 100644
--- a/poolalloc/lib/DSA/CallTargets.cpp
+++ b/poolalloc/lib/DSA/CallTargets.cpp
@@ -150,7 +150,7 @@
O << cs.getInstruction()->getParent()->getParent()->getName().str() << " "
<< cs.getInstruction()->getName().str() << " ";
}
- O << ii->first.getInstruction() << ":";
+ O << *ii->first.getInstruction() << ":";
for (std::vector<const Function*>::const_iterator i = ii->second.begin(),
e = ii->second.end(); i != e; ++i) {
O << " " << (*i)->getName().str();
@@ -164,15 +164,18 @@
findIndTargets(M);
// Sort callees alphabetically, remove duplicates
- for(auto &i: IndMap) {
+ for (auto &i : IndMap) {
auto &callees = i.second;
- auto FuncNameCmp = [](const Function *a, const Function *b) {
- return a->getName() < b->getName();
- };
- std::sort(callees.begin(), callees.end(), FuncNameCmp);
- callees.erase(std::unique(callees.begin(), callees.end(), FuncNameCmp),
- callees.end());
+ // Sort as Function*, remove duplicates
+ std::sort(callees.begin(), callees.end());
+ callees.erase(std::unique(callees.begin(), callees.end()), callees.end());
+
+ // Sort by name for easier reading:
+ std::sort(callees.begin(), callees.end(),
+ [](const Function *a, const Function *b) {
+ return a->getName() < b->getName();
+ });
}
return false;
diff --git a/poolalloc/test/dsa/callgraph/calltarget_basic.ll b/poolalloc/test/dsa/callgraph/calltarget_basic.ll
new file mode 100644
index 0000000..60db1a3
--- /dev/null
+++ b/poolalloc/test/dsa/callgraph/calltarget_basic.ll
@@ -0,0 +1,48 @@
+; Very basic -calltarget-{,eq}td pass testing.
+
+;RUN: dsaopt %s -calltarget-td -analyze | FileCheck %s
+;RUN: dsaopt %s -calltarget-eqtd -analyze | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Notes:
+; * "A" and "B" are in an SCC so callgraph reports both when
+; calling one of them.
+; * Both calls in @B are reported to potentially call A and
+; C due to lack of flow-sensitivity.
+
+define internal void @C() nounwind {
+entry:
+ ret void
+}
+
+define internal void @A() nounwind {
+entry:
+ ; indirect call to B()
+ %Bfp = alloca void ()*
+ store void ()* @B, void ()** %Bfp, align 8
+ %B = load void ()*, void ()** %Bfp, align 8
+
+;CHECK-DAG: call void %B() #0: A B
+ call void %B() nounwind
+ ret void
+}
+
+define internal void @B() nounwind {
+entry:
+ %fp = alloca void ()*
+
+ ; indirect call to A()
+ store void ()* @A, void ()** %fp, align 8
+ %A = load void ()*, void ()** %fp, align 8
+;CHECK-DAG: call void %A() #0: A B C
+ call void %A() nounwind
+
+ ; indirect call to C()
+ store void ()* @C, void ()** %fp, align 8
+ %C = load void ()*, void ()** %fp, align 8
+;CHECK-DAG: call void %C() #0: A B C
+ call void %C() nounwind
+ ret void
+}
+