@@ -482,6 +482,29 @@ void SplitGraph::Node::visitAllDependencies(
482
482
}
483
483
}
484
484
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
+
485
508
void SplitGraph::buildGraph (CallGraph &CG) {
486
509
SplitModuleTimer SMT (" buildGraph" , " graph construction" );
487
510
LLVM_DEBUG (
@@ -519,28 +542,38 @@ void SplitGraph::buildGraph(CallGraph &CG) {
519
542
Fn.printAsOperand (dbgs ());
520
543
dbgs () << " - analyzing function\n " );
521
544
522
- bool HasIndirectCall = false ;
545
+ SetVector<Function *> KnownCallees;
546
+ bool HasUnknownIndirectCall = false ;
523
547
for (const auto &Inst : instructions (Fn)) {
524
548
// 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 ;
537
558
}
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 ;
538
570
}
539
571
540
- if (HasIndirectCall ) {
572
+ if (HasUnknownIndirectCall ) {
541
573
LLVM_DEBUG (dbgs () << " indirect call found\n " );
542
574
FnsWithIndirectCalls.push_back (&Fn);
543
- }
575
+ } else if (!KnownCallees.empty ())
576
+ DirectCallees.insert (KnownCallees.begin (), KnownCallees.end ());
544
577
}
545
578
546
579
Node &N = getNode (Cache, Fn);
0 commit comments