@@ -636,9 +636,11 @@ struct DevirtModule {
636636 std::map<CallInst *, unsigned > NumUnsafeUsesForTypeTest;
637637 PatternList FunctionsToSkip;
638638
639+ const bool DevirtSpeculatively;
639640 DevirtModule (Module &M, ModuleAnalysisManager &MAM,
640641 ModuleSummaryIndex *ExportSummary,
641- const ModuleSummaryIndex *ImportSummary)
642+ const ModuleSummaryIndex *ImportSummary,
643+ bool DevirtSpeculatively)
642644 : M(M), MAM(MAM),
643645 FAM (MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager()),
644646 ExportSummary(ExportSummary), ImportSummary(ImportSummary),
@@ -651,7 +653,8 @@ struct DevirtModule {
651653 RemarksEnabled(areRemarksEnabled()),
652654 OREGetter([&](Function &F) -> OptimizationRemarkEmitter & {
653655 return FAM.getResult <OptimizationRemarkEmitterAnalysis>(F);
654- }) {
656+ }),
657+ DevirtSpeculatively (DevirtSpeculatively) {
655658 assert (!(ExportSummary && ImportSummary));
656659 FunctionsToSkip.init (SkipFunctionNames);
657660 }
@@ -765,7 +768,8 @@ struct DevirtModule {
765768
766769 // Lower the module using the action and summary passed as command line
767770 // arguments. For testing purposes only.
768- static bool runForTesting (Module &M, ModuleAnalysisManager &MAM);
771+ static bool runForTesting (Module &M, ModuleAnalysisManager &MAM,
772+ bool DevirtSpeculatively);
769773};
770774
771775struct DevirtIndex {
@@ -808,11 +812,22 @@ struct DevirtIndex {
808812PreservedAnalyses WholeProgramDevirtPass::run (Module &M,
809813 ModuleAnalysisManager &MAM) {
810814 if (UseCommandLine) {
811- if (!DevirtModule::runForTesting (M, MAM))
815+ if (!DevirtModule::runForTesting (M, MAM, ClDevirtualizeSpeculatively ))
812816 return PreservedAnalyses::all ();
813817 return PreservedAnalyses::none ();
814818 }
815- if (!DevirtModule (M, MAM, ExportSummary, ImportSummary).run ())
819+
820+ std::optional<ModuleSummaryIndex> Index;
821+ if (!ExportSummary && !ImportSummary && DevirtSpeculatively) {
822+ // Build the ExportSummary from the module.
823+ assert (!ExportSummary &&
824+ " ExportSummary is expected to be empty in non-LTO mode" );
825+ ProfileSummaryInfo PSI (M);
826+ Index.emplace (buildModuleSummaryIndex (M, nullptr , &PSI));
827+ ExportSummary = Index.has_value () ? &Index.value () : nullptr ;
828+ }
829+ if (!DevirtModule (M, MAM, ExportSummary, ImportSummary, DevirtSpeculatively)
830+ .run ())
816831 return PreservedAnalyses::all ();
817832 return PreservedAnalyses::none ();
818833}
@@ -1010,7 +1025,8 @@ static Error checkCombinedSummaryForTesting(ModuleSummaryIndex *Summary) {
10101025 return ErrorSuccess ();
10111026}
10121027
1013- bool DevirtModule::runForTesting (Module &M, ModuleAnalysisManager &MAM) {
1028+ bool DevirtModule::runForTesting (Module &M, ModuleAnalysisManager &MAM,
1029+ bool DevirtSpeculatively) {
10141030 std::unique_ptr<ModuleSummaryIndex> Summary =
10151031 std::make_unique<ModuleSummaryIndex>(/* HaveGVs=*/ false );
10161032
@@ -1039,7 +1055,8 @@ bool DevirtModule::runForTesting(Module &M, ModuleAnalysisManager &MAM) {
10391055 ClSummaryAction == PassSummaryAction::Export ? Summary.get ()
10401056 : nullptr ,
10411057 ClSummaryAction == PassSummaryAction::Import ? Summary.get ()
1042- : nullptr )
1058+ : nullptr ,
1059+ DevirtSpeculatively)
10431060 .run ();
10441061
10451062 if (!ClWriteSummary.empty ()) {
@@ -1103,10 +1120,10 @@ bool DevirtModule::tryFindVirtualCallTargets(
11031120 if (!TM.Bits ->GV ->isConstant ())
11041121 return false ;
11051122
1106- // Without ClDevirtualizeSpeculatively , we cannot perform whole program
1123+ // Without DevirtSpeculatively , we cannot perform whole program
11071124 // devirtualization analysis on a vtable with public LTO visibility.
1108- if (!ClDevirtualizeSpeculatively && TM.Bits ->GV ->getVCallVisibility () ==
1109- GlobalObject::VCallVisibilityPublic)
1125+ if (!DevirtSpeculatively && TM.Bits ->GV ->getVCallVisibility () ==
1126+ GlobalObject::VCallVisibilityPublic)
11101127 return false ;
11111128
11121129 Function *Fn = nullptr ;
@@ -1127,7 +1144,7 @@ bool DevirtModule::tryFindVirtualCallTargets(
11271144
11281145 // In most cases empty functions will be overridden by the
11291146 // implementation of the derived class, so we can skip them.
1130- if (ClDevirtualizeSpeculatively && Fn->getReturnType ()->isVoidTy () &&
1147+ if (DevirtSpeculatively && Fn->getReturnType ()->isVoidTy () &&
11311148 Fn->getInstructionCount () <= 1 )
11321149 continue ;
11331150
@@ -1250,8 +1267,7 @@ void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo,
12501267 // add support to compare the virtual function pointer to the
12511268 // devirtualized target. In case of a mismatch, fall back to indirect
12521269 // call.
1253- if (DevirtCheckMode == WPDCheckMode::Fallback ||
1254- ClDevirtualizeSpeculatively) {
1270+ if (DevirtCheckMode == WPDCheckMode::Fallback || DevirtSpeculatively) {
12551271 MDNode *Weights = MDBuilder (M.getContext ()).createLikelyBranchWeights ();
12561272 // Version the indirect call site. If the called value is equal to the
12571273 // given callee, 'NewInst' will be executed, otherwise the original call
@@ -2375,7 +2391,7 @@ bool DevirtModule::run() {
23752391 Function *PublicTypeTestFunc = nullptr ;
23762392 // If we are in speculative devirtualization mode, we can work on the public
23772393 // type test intrinsics.
2378- if (ClDevirtualizeSpeculatively )
2394+ if (DevirtSpeculatively )
23792395 PublicTypeTestFunc =
23802396 Intrinsic::getDeclarationIfExists (&M, Intrinsic::public_type_test);
23812397 Function *TypeTestFunc =
@@ -2511,7 +2527,7 @@ bool DevirtModule::run() {
25112527 // Out of speculative devirtualization mode, Try to apply virtual constant
25122528 // propagation or branch funneling.
25132529 // TODO: This should eventually be enabled for non-public type tests.
2514- if (!SingleImplDevirt && !ClDevirtualizeSpeculatively ) {
2530+ if (!SingleImplDevirt && !DevirtSpeculatively ) {
25152531 DidVirtualConstProp |=
25162532 tryVirtualConstProp (TargetsForSlot, S.second , Res, S.first );
25172533
0 commit comments