@@ -81,6 +81,11 @@ static cl::opt<std::string> ModuleSummaryDotFile(
8181 " module-summary-dot-file" , cl::Hidden, cl::value_desc(" filename" ),
8282 cl::desc(" File to emit dot graph of new summary into" ));
8383
84+ static cl::opt<bool > EnableMemProfIndirectCallSupport (
85+ " enable-memprof-indirect-call-support" , cl::init(true ), cl::Hidden,
86+ cl::desc(
87+ " Enable MemProf support for summarizing and cloning indirect calls" ));
88+
8489extern cl::opt<bool > ScalePartialSampleProfileWorkingSetSize;
8590
8691extern cl::opt<unsigned > MaxNumVTableAnnotations;
@@ -404,6 +409,11 @@ static void computeFunctionSummary(
404409 if (HasLocalsInUsedOrAsm && CI && CI->isInlineAsm ())
405410 HasInlineAsmMaybeReferencingInternal = true ;
406411
412+ // Compute this once per indirect call.
413+ uint32_t NumCandidates = 0 ;
414+ uint64_t TotalCount = 0 ;
415+ MutableArrayRef<InstrProfValueData> CandidateProfileData;
416+
407417 auto *CalledValue = CB->getCalledOperand ();
408418 auto *CalledFunction = CB->getCalledFunction ();
409419 if (CalledValue && !CalledFunction) {
@@ -481,9 +491,7 @@ static void computeFunctionSummary(
481491 }
482492 }
483493
484- uint32_t NumCandidates;
485- uint64_t TotalCount;
486- auto CandidateProfileData =
494+ CandidateProfileData =
487495 ICallAnalysis.getPromotionCandidatesForInstruction (&I, TotalCount,
488496 NumCandidates);
489497 for (const auto &Candidate : CandidateProfileData)
@@ -495,16 +503,6 @@ static void computeFunctionSummary(
495503 if (!IsThinLTO)
496504 continue ;
497505
498- // TODO: Skip indirect calls for now. Need to handle these better, likely
499- // by creating multiple Callsites, one per target, then speculatively
500- // devirtualize while applying clone info in the ThinLTO backends. This
501- // will also be important because we will have a different set of clone
502- // versions per target. This handling needs to match that in the ThinLTO
503- // backend so we handle things consistently for matching of callsite
504- // summaries to instructions.
505- if (!CalledFunction)
506- continue ;
507-
508506 // Ensure we keep this analysis in sync with the handling in the ThinLTO
509507 // backend (see MemProfContextDisambiguation::applyImport). Save this call
510508 // so that we can skip it in checking the reverse case later.
@@ -555,13 +553,24 @@ static void computeFunctionSummary(
555553 SmallVector<unsigned > StackIdIndices;
556554 for (auto StackId : InstCallsite)
557555 StackIdIndices.push_back (Index.addOrGetStackIdIndex (StackId));
558- // Use the original CalledValue, in case it was an alias. We want
559- // to record the call edge to the alias in that case. Eventually
560- // an alias summary will be created to associate the alias and
561- // aliasee.
562- auto CalleeValueInfo =
563- Index.getOrInsertValueInfo (cast<GlobalValue>(CalledValue));
564- Callsites.push_back ({CalleeValueInfo, StackIdIndices});
556+ if (CalledFunction) {
557+ // Use the original CalledValue, in case it was an alias. We want
558+ // to record the call edge to the alias in that case. Eventually
559+ // an alias summary will be created to associate the alias and
560+ // aliasee.
561+ auto CalleeValueInfo =
562+ Index.getOrInsertValueInfo (cast<GlobalValue>(CalledValue));
563+ Callsites.push_back ({CalleeValueInfo, StackIdIndices});
564+ } else if (EnableMemProfIndirectCallSupport) {
565+ // For indirect callsites, create multiple Callsites, one per target.
566+ // This enables having a different set of clone versions per target,
567+ // and we will apply the cloning decisions while speculatively
568+ // devirtualizing in the ThinLTO backends.
569+ for (const auto &Candidate : CandidateProfileData) {
570+ auto CalleeValueInfo = Index.getOrInsertValueInfo (Candidate.Value );
571+ Callsites.push_back ({CalleeValueInfo, StackIdIndices});
572+ }
573+ }
565574 }
566575 }
567576 }
@@ -1214,9 +1223,13 @@ bool llvm::mayHaveMemprofSummary(const CallBase *CB) {
12141223 if (CI && CalledFunction->isIntrinsic ())
12151224 return false ;
12161225 } else {
1217- // TODO: For now skip indirect calls. See comments in
1218- // computeFunctionSummary for what is needed to handle this.
1219- return false ;
1226+ // Skip inline assembly calls.
1227+ if (CI && CI->isInlineAsm ())
1228+ return false ;
1229+ // Skip direct calls via Constant.
1230+ if (!CalledValue || isa<Constant>(CalledValue))
1231+ return false ;
1232+ return true ;
12201233 }
12211234 return true ;
12221235}
0 commit comments