[llvm] [AMDGPU][SplitModule] Handle !callees metadata (PR #108802)
Shilei Tian via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 16 08:50:30 PDT 2024
================
@@ -492,29 +526,60 @@ void SplitGraph::buildGraph(CallGraph &CG) {
continue;
// Look at direct callees and create the necessary edges in the graph.
- bool HasIndirectCall = false;
- Node &N = getNode(Cache, Fn);
+ SetVector<const Function *> DirectCallees;
+ bool CallsExternal = false;
for (auto &CGEntry : *CG[&Fn]) {
auto *CGNode = CGEntry.second;
- auto *Callee = CGNode->getFunction();
- if (!Callee) {
- // TODO: Don't consider inline assembly as indirect calls.
- if (CGNode == CG.getCallsExternalNode())
- HasIndirectCall = true;
- continue;
- }
-
- if (!Callee->isDeclaration())
- createEdge(N, getNode(Cache, *Callee), EdgeKind::DirectCall);
+ if (auto *Callee = CGNode->getFunction()) {
+ if (!Callee->isDeclaration())
+ DirectCallees.insert(Callee);
+ } else if (CGNode == CG.getCallsExternalNode())
+ CallsExternal = true;
}
// Keep track of this function if it contains an indirect call and/or if it
// can be indirectly called.
- if (HasIndirectCall) {
- LLVM_DEBUG(dbgs() << "indirect call found in " << Fn.getName() << "\n");
- FnsWithIndirectCalls.push_back(&Fn);
+ if (CallsExternal) {
+ LLVM_DEBUG(dbgs() << " [!] callgraph is incomplete for " << Fn.getName()
+ << " - analyzing function\n");
+
+ SmallVector<Function *> KnownCallees;
+ bool HasUnknownIndirectCall = false;
+ for (const auto &Inst : instructions(Fn)) {
+ // look at all calls without a direct callee.
+ const auto *CB = dyn_cast<CallBase>(&Inst);
+ if (!CB || CB->getCalledFunction())
+ continue;
+
+ // inline assembly can be ignored, unless InlineAsmIsIndirectCall is
+ // true.
+ if (CB->isInlineAsm()) {
+ if (InlineAsmIsIndirectCall)
+ HasUnknownIndirectCall = true;
+ LLVM_DEBUG(dbgs() << " found inline assembly\n");
+ continue;
+ }
+
+ if (handleCalleesMD(Inst, KnownCallees))
+ continue;
+
+ // Everything else is handled conservatively. If we fall into the
+ // conservative case don't bother analyzing further.
+ HasUnknownIndirectCall = true;
+ break;
+ }
+
+ if (HasUnknownIndirectCall) {
+ LLVM_DEBUG(dbgs() << " indirect call found\n");
+ FnsWithIndirectCalls.push_back(&Fn);
+ } else if (!KnownCallees.empty())
+ DirectCallees.insert(KnownCallees.begin(), KnownCallees.end());
}
+ Node &N = getNode(Cache, Fn);
+ for (const auto *Callee : DirectCallees)
+ createEdge(N, getNode(Cache, *Callee), EdgeKind::DirectCall);
----------------
shiltian wrote:
I have a question (probably has been asked by someone before IIRC). I thought when constructing the call graph, it already takes all potential callees into consideration such that the call edges are already there. It seems like that's not the case.
https://github.com/llvm/llvm-project/pull/108802
More information about the llvm-commits
mailing list