@@ -482,6 +482,29 @@ void SplitGraph::Node::visitAllDependencies(
482482 }
483483}
484484
485+ // / Checks if \p I has MD_callees and if it does, parse it and put the function
486+ // / in \p Callees.
487+ // /
488+ // / \returns true if there was metadata and it was parsed correctly. false if
489+ // / there was no MD or if it contained unknown entries and parsing failed.
490+ // / If this returns false, \p Callees will contain incomplete information
491+ // / and must not be used.
492+ static bool handleCalleesMD (const Instruction &I,
493+ SetVector<Function *> &Callees) {
494+ auto *MD = I.getMetadata (LLVMContext::MD_callees);
495+ if (!MD)
496+ return false ;
497+
498+ for (const auto &Op : MD->operands ()) {
499+ Function *Callee = mdconst::extract_or_null<Function>(Op);
500+ if (!Callee)
501+ return false ;
502+ Callees.insert (Callee);
503+ }
504+
505+ return true ;
506+ }
507+
485508void SplitGraph::buildGraph (CallGraph &CG) {
486509 SplitModuleTimer SMT (" buildGraph" , " graph construction" );
487510 LLVM_DEBUG (
@@ -519,28 +542,38 @@ void SplitGraph::buildGraph(CallGraph &CG) {
519542 Fn.printAsOperand (dbgs ());
520543 dbgs () << " - analyzing function\n " );
521544
522- bool HasIndirectCall = false ;
545+ SetVector<Function *> KnownCallees;
546+ bool HasUnknownIndirectCall = false ;
523547 for (const auto &Inst : instructions (Fn)) {
524548 // look at all calls without a direct callee.
525- if (const auto *CB = dyn_cast<CallBase>(&Inst);
526- CB && !CB->getCalledFunction ()) {
527- // inline assembly can be ignored, unless InlineAsmIsIndirectCall is
528- // true.
529- if (CB->isInlineAsm ()) {
530- LLVM_DEBUG (dbgs () << " found inline assembly\n " );
531- continue ;
532- }
533-
534- // everything else is handled conservatively.
535- HasIndirectCall = true ;
536- break ;
549+ const auto *CB = dyn_cast<CallBase>(&Inst);
550+ if (!CB || CB->getCalledFunction ())
551+ continue ;
552+
553+ // inline assembly can be ignored, unless InlineAsmIsIndirectCall is
554+ // true.
555+ if (CB->isInlineAsm ()) {
556+ LLVM_DEBUG (dbgs () << " found inline assembly\n " );
557+ continue ;
537558 }
559+
560+ if (handleCalleesMD (Inst, KnownCallees))
561+ continue ;
562+ // If we failed to parse any !callees MD, or some was missing,
563+ // the entire KnownCallees list is now unreliable.
564+ KnownCallees.clear ();
565+
566+ // Everything else is handled conservatively. If we fall into the
567+ // conservative case don't bother analyzing further.
568+ HasUnknownIndirectCall = true ;
569+ break ;
538570 }
539571
540- if (HasIndirectCall ) {
572+ if (HasUnknownIndirectCall ) {
541573 LLVM_DEBUG (dbgs () << " indirect call found\n " );
542574 FnsWithIndirectCalls.push_back (&Fn);
543- }
575+ } else if (!KnownCallees.empty ())
576+ DirectCallees.insert (KnownCallees.begin (), KnownCallees.end ());
544577 }
545578
546579 Node &N = getNode (Cache, Fn);
0 commit comments