Skip to content

Commit e787aa2

Browse files
committed
[WPD]: add devirt flag to conditionally enable speculative devirtualization
in the pass when it gets launched by pass manager.
1 parent 0b5d559 commit e787aa2

File tree

3 files changed

+38
-20
lines changed

3 files changed

+38
-20
lines changed

llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,14 @@ struct WholeProgramDevirtPass : public PassInfoMixin<WholeProgramDevirtPass> {
226226
ModuleSummaryIndex *ExportSummary;
227227
const ModuleSummaryIndex *ImportSummary;
228228
bool UseCommandLine = false;
229+
bool DevirtSpeculatively = false;
229230
WholeProgramDevirtPass()
230231
: ExportSummary(nullptr), ImportSummary(nullptr), UseCommandLine(true) {}
231232
WholeProgramDevirtPass(ModuleSummaryIndex *ExportSummary,
232-
const ModuleSummaryIndex *ImportSummary)
233-
: ExportSummary(ExportSummary), ImportSummary(ImportSummary) {
233+
const ModuleSummaryIndex *ImportSummary,
234+
bool DevirtSpeculatively = false)
235+
: ExportSummary(ExportSummary), ImportSummary(ImportSummary),
236+
DevirtSpeculatively(DevirtSpeculatively) {
234237
assert(!(ExportSummary && ImportSummary));
235238
}
236239
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &);

llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

771775
struct DevirtIndex {
@@ -808,11 +812,22 @@ struct DevirtIndex {
808812
PreservedAnalyses 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
}
@@ -1008,7 +1023,8 @@ static Error checkCombinedSummaryForTesting(ModuleSummaryIndex *Summary) {
10081023
return ErrorSuccess();
10091024
}
10101025

1011-
bool DevirtModule::runForTesting(Module &M, ModuleAnalysisManager &MAM) {
1026+
bool DevirtModule::runForTesting(Module &M, ModuleAnalysisManager &MAM,
1027+
bool DevirtSpeculatively) {
10121028
std::unique_ptr<ModuleSummaryIndex> Summary =
10131029
std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);
10141030

@@ -1037,7 +1053,8 @@ bool DevirtModule::runForTesting(Module &M, ModuleAnalysisManager &MAM) {
10371053
ClSummaryAction == PassSummaryAction::Export ? Summary.get()
10381054
: nullptr,
10391055
ClSummaryAction == PassSummaryAction::Import ? Summary.get()
1040-
: nullptr)
1056+
: nullptr,
1057+
DevirtSpeculatively)
10411058
.run();
10421059

10431060
if (!ClWriteSummary.empty()) {
@@ -1101,10 +1118,10 @@ bool DevirtModule::tryFindVirtualCallTargets(
11011118
if (!TM.Bits->GV->isConstant())
11021119
return false;
11031120

1104-
// Without ClDevirtualizeSpeculatively, we cannot perform whole program
1121+
// Without DevirtSpeculatively, we cannot perform whole program
11051122
// devirtualization analysis on a vtable with public LTO visibility.
1106-
if (!ClDevirtualizeSpeculatively && TM.Bits->GV->getVCallVisibility() ==
1107-
GlobalObject::VCallVisibilityPublic)
1123+
if (!DevirtSpeculatively && TM.Bits->GV->getVCallVisibility() ==
1124+
GlobalObject::VCallVisibilityPublic)
11081125
return false;
11091126

11101127
Function *Fn = nullptr;
@@ -1125,7 +1142,7 @@ bool DevirtModule::tryFindVirtualCallTargets(
11251142

11261143
// In most cases empty functions will be overridden by the
11271144
// implementation of the derived class, so we can skip them.
1128-
if (ClDevirtualizeSpeculatively && Fn->getReturnType()->isVoidTy() &&
1145+
if (DevirtSpeculatively && Fn->getReturnType()->isVoidTy() &&
11291146
Fn->getInstructionCount() <= 1)
11301147
continue;
11311148

@@ -1251,8 +1268,7 @@ void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo,
12511268
// add support to compare the virtual function pointer to the
12521269
// devirtualized target. In case of a mismatch, fall back to indirect
12531270
// call.
1254-
if (DevirtCheckMode == WPDCheckMode::Fallback ||
1255-
ClDevirtualizeSpeculatively) {
1271+
if (DevirtCheckMode == WPDCheckMode::Fallback || DevirtSpeculatively) {
12561272
MDNode *Weights = MDBuilder(M.getContext()).createLikelyBranchWeights();
12571273
// Version the indirect call site. If the called value is equal to the
12581274
// given callee, 'NewInst' will be executed, otherwise the original call
@@ -1354,7 +1370,7 @@ bool DevirtModule::trySingleImplDevirt(
13541370
// Out of speculative devirtualization mode, if the only implementation has
13551371
// local linkage, we must promote to external to make it visible to thin LTO
13561372
// objects.
1357-
if (!ClDevirtualizeSpeculatively && TheFn->hasLocalLinkage()) {
1373+
if (!DevirtSpeculatively && TheFn->hasLocalLinkage()) {
13581374
std::string NewName = (TheFn->getName() + ".llvm.merged").str();
13591375

13601376
// Since we are renaming the function, any comdats with the same name must
@@ -2378,7 +2394,7 @@ bool DevirtModule::run() {
23782394
Intrinsic::getDeclarationIfExists(&M, Intrinsic::type_test);
23792395
// If we are in speculative devirtualization mode, we can work on the public
23802396
// type test intrinsics.
2381-
if (!TypeTestFunc && ClDevirtualizeSpeculatively)
2397+
if (!TypeTestFunc && DevirtSpeculatively)
23822398
TypeTestFunc =
23832399
Intrinsic::getDeclarationIfExists(&M, Intrinsic::public_type_test);
23842400
Function *TypeCheckedLoadFunc =
@@ -2507,7 +2523,7 @@ bool DevirtModule::run() {
25072523
trySingleImplDevirt(ExportSummary, TargetsForSlot, S.second, Res);
25082524
// Out of speculative devirtualization mode, Try to apply virtual constant
25092525
// propagation or branch funneling.
2510-
if (!SingleImplDevirt && !ClDevirtualizeSpeculatively) {
2526+
if (!SingleImplDevirt && !DevirtSpeculatively) {
25112527
DidVirtualConstProp |=
25122528
tryVirtualConstProp(TargetsForSlot, S.second, Res, S.first);
25132529

llvm/test/Transforms/WholeProgramDevirt/speculative-devirt-single-impl.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ define i1 @vf(ptr %this) #0 !dbg !7 {
2323
ret i1 true
2424
}
2525

26-
; This should NOT be devirtualized because during non-lto empty functions
27-
; are skipped.
26+
; This should NOT be devirtualized because empty functions are skipped during non-lto.
2827
define void @vf_empty(ptr %this) !dbg !11 {
2928
ret void
3029
}

0 commit comments

Comments
 (0)