https://github.com/hassnaaHamdi created https://github.com/llvm/llvm-project/pull/141777
None >From 702f64a84914d2fe467a12babd99338f2215d425 Mon Sep 17 00:00:00 2001 From: Hassnaa Hamdi <hassnaa.ha...@arm.com> Date: Wed, 28 May 2025 14:27:34 +0000 Subject: [PATCH] Enable WPD without lto --- clang/lib/CodeGen/CGVTables.cpp | 3 +- clang/lib/Driver/ToolChains/Clang.cpp | 8 +- llvm/lib/Passes/PassBuilderPipelines.cpp | 3 + .../lib/Transforms/IPO/WholeProgramDevirt.cpp | 83 +++++++++++-------- 4 files changed, 61 insertions(+), 36 deletions(-) diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index c7447273a42fa..48036df7b7b6f 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -1359,7 +1359,8 @@ void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD, // Emit type metadata on vtables with LTO or IR instrumentation. // In IR instrumentation, the type metadata is used to find out vtable // definitions (for type profiling) among all global variables. - if (!getCodeGenOpts().LTOUnit && !getCodeGenOpts().hasProfileIRInstr()) + if (!getCodeGenOpts().LTOUnit && !getCodeGenOpts().hasProfileIRInstr() && + !getCodeGenOpts().WholeProgramVTables) return; CharUnits ComponentWidth = GetTargetTypeStoreSize(getVTableComponentType()); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 13842b8cc2870..bdb7fc9b778d6 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7970,8 +7970,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, IsDeviceOffloadAction ? D.getLTOMode() : D.getOffloadLTOMode(); auto OtherIsUsingLTO = OtherLTOMode != LTOK_None; - if ((!IsUsingLTO && !OtherIsUsingLTO) || - (IsPS4 && !UnifiedLTO && (D.getLTOMode() != LTOK_Full))) + if (!IsUsingLTO && !OtherIsUsingLTO && !UnifiedLTO) { + if (Arg *A = Args.getLastArg(options::OPT_O_Group)) + if (!A->getOption().matches(options::OPT_O0)) + CmdArgs.push_back("-fwhole-program-vtables"); + } else if ((!IsUsingLTO && !OtherIsUsingLTO) || + (IsPS4 && !UnifiedLTO && (D.getLTOMode() != LTOK_Full))) D.Diag(diag::err_drv_argument_only_allowed_with) << "-fwhole-program-vtables" << ((IsPS4 && !UnifiedLTO) ? "-flto=full" : "-flto"); diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp index f3654600c5abb..0d021cb7c47c3 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -1295,6 +1295,9 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, MPM.addPass(GlobalOptPass()); MPM.addPass(GlobalDCEPass()); + if (Phase == ThinOrFullLTOPhase::None && Level != OptimizationLevel::O0) + MPM.addPass(WholeProgramDevirtPass(nullptr, nullptr)); + return MPM; } diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp index 3a25255d0a4c8..44c2b58f3b735 100644 --- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -60,7 +60,9 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/BasicAliasAnalysis.h" +#include "llvm/Analysis/ModuleSummaryAnalysis.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" +#include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/Analysis/TypeMetadataUtils.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Bitcode/BitcodeWriter.h" @@ -209,7 +211,8 @@ static cl::opt<WPDCheckMode> DevirtCheckMode( cl::values(clEnumValN(WPDCheckMode::None, "none", "No checking"), clEnumValN(WPDCheckMode::Trap, "trap", "Trap when incorrect"), clEnumValN(WPDCheckMode::Fallback, "fallback", - "Fallback to indirect when incorrect"))); + "Fallback to indirect when incorrect")), + cl::init(WPDCheckMode::Fallback)); namespace { struct PatternList { @@ -804,6 +807,12 @@ PreservedAnalyses WholeProgramDevirtPass::run(Module &M, return PreservedAnalyses::all(); return PreservedAnalyses::none(); } + if (!ExportSummary) { + ProfileSummaryInfo PSI(M); + std::optional<ModuleSummaryIndex> Index; + Index.emplace(buildModuleSummaryIndex(M, nullptr, &PSI)); + ExportSummary = Index.has_value() ? &Index.value() : nullptr; + } if (!DevirtModule(M, AARGetter, OREGetter, LookupDomTree, ExportSummary, ImportSummary) .run()) @@ -814,8 +823,10 @@ PreservedAnalyses WholeProgramDevirtPass::run(Module &M, // Enable whole program visibility if enabled by client (e.g. linker) or // internal option, and not force disabled. bool llvm::hasWholeProgramVisibility(bool WholeProgramVisibilityEnabledInLTO) { - return (WholeProgramVisibilityEnabledInLTO || WholeProgramVisibility) && - !DisableWholeProgramVisibility; + if (WholeProgramVisibilityEnabledInLTO) + return (WholeProgramVisibilityEnabledInLTO || WholeProgramVisibility) && + !DisableWholeProgramVisibility; + return true; } static bool @@ -1099,9 +1110,9 @@ bool DevirtModule::tryFindVirtualCallTargets( // We cannot perform whole program devirtualization analysis on a vtable // with public LTO visibility. - if (TM.Bits->GV->getVCallVisibility() == - GlobalObject::VCallVisibilityPublic) - return false; + // if (TM.Bits->GV->getVCallVisibility() == + // GlobalObject::VCallVisibilityPublic) + // return false; Function *Fn = nullptr; Constant *C = nullptr; @@ -1342,26 +1353,28 @@ bool DevirtModule::trySingleImplDevirt( // If the only implementation has local linkage, we must promote to external // to make it visible to thin LTO objects. We can only get here during the // ThinLTO export phase. - if (TheFn->hasLocalLinkage()) { - std::string NewName = (TheFn->getName() + ".llvm.merged").str(); - - // Since we are renaming the function, any comdats with the same name must - // also be renamed. This is required when targeting COFF, as the comdat name - // must match one of the names of the symbols in the comdat. - if (Comdat *C = TheFn->getComdat()) { - if (C->getName() == TheFn->getName()) { - Comdat *NewC = M.getOrInsertComdat(NewName); - NewC->setSelectionKind(C->getSelectionKind()); - for (GlobalObject &GO : M.global_objects()) - if (GO.getComdat() == C) - GO.setComdat(NewC); - } - } - - TheFn->setLinkage(GlobalValue::ExternalLinkage); - TheFn->setVisibility(GlobalValue::HiddenVisibility); - TheFn->setName(NewName); - } + // if (TheFn->hasLocalLinkage()) { + // std::string NewName = (TheFn->getName() + ".llvm.merged").str(); + + // // Since we are renaming the function, any comdats with the same name + // must + // // also be renamed. This is required when targeting COFF, as the comdat + // name + // // must match one of the names of the symbols in the comdat. + // if (Comdat *C = TheFn->getComdat()) { + // if (C->getName() == TheFn->getName()) { + // Comdat *NewC = M.getOrInsertComdat(NewName); + // NewC->setSelectionKind(C->getSelectionKind()); + // for (GlobalObject &GO : M.global_objects()) + // if (GO.getComdat() == C) + // GO.setComdat(NewC); + // } + // } + + // TheFn->setLinkage(GlobalValue::ExternalLinkage); + // TheFn->setVisibility(GlobalValue::HiddenVisibility); + // TheFn->setName(NewName); + // } if (ValueInfo TheFnVI = ExportSummary->getValueInfo(TheFn->getGUID())) // Any needed promotion of 'TheFn' has already been done during // LTO unit split, so we can ignore return value of AddCalls. @@ -2321,6 +2334,9 @@ bool DevirtModule::run() { Function *TypeTestFunc = Intrinsic::getDeclarationIfExists(&M, Intrinsic::type_test); + if (!TypeTestFunc) + TypeTestFunc = + Intrinsic::getDeclarationIfExists(&M, Intrinsic::public_type_test); Function *TypeCheckedLoadFunc = Intrinsic::getDeclarationIfExists(&M, Intrinsic::type_checked_load); Function *TypeCheckedLoadRelativeFunc = Intrinsic::getDeclarationIfExists( @@ -2443,13 +2459,14 @@ bool DevirtModule::run() { .WPDRes[S.first.ByteOffset]; if (tryFindVirtualCallTargets(TargetsForSlot, TypeMemberInfos, S.first.ByteOffset, ExportSummary)) { - - if (!trySingleImplDevirt(ExportSummary, TargetsForSlot, S.second, Res)) { - DidVirtualConstProp |= - tryVirtualConstProp(TargetsForSlot, S.second, Res, S.first); - - tryICallBranchFunnel(TargetsForSlot, S.second, Res, S.first); - } + trySingleImplDevirt(ExportSummary, TargetsForSlot, S.second, Res); + // Following features are not needed for the case of enabling WPD without + // lto. if (!trySingleImplDevirt(ExportSummary, TargetsForSlot, S.second, + // Res)) { DidVirtualConstProp |= + // tryVirtualConstProp(TargetsForSlot, S.second, Res, S.first); + + // tryICallBranchFunnel(TargetsForSlot, S.second, Res, S.first); + // } // Collect functions devirtualized at least for one call site for stats. if (RemarksEnabled || AreStatisticsEnabled()) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits