llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-driver

Author: KRM7

<details>
<summary>Changes</summary>

Enable speculative single-target devirtualization with LTO (disabled by 
default, can be enabled using -fdevirtualize-speculatively).

The DevirtSpeculatively member variable is also removed from WPD, so that the 
optimization is controlled entirely by the -devirtualize-speculatively flag. 
The -enable-devirtualize-speculatively flag is now only used to add the WPD 
pass to the non-LTO pipeline.

---

Patch is 47.34 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/233380.diff


20 Files Affected:

- (modified) clang/docs/UsersManual.md (-2) 
- (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+8) 
- (modified) clang/test/Driver/lto.c (+8) 
- (modified) llvm/include/llvm/AsmParser/LLToken.h (+1) 
- (modified) llvm/include/llvm/IR/ModuleSummaryIndex.h (+1) 
- (modified) llvm/include/llvm/IR/ModuleSummaryIndexYAML.h (+2) 
- (modified) llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h (+2-5) 
- (modified) llvm/lib/AsmParser/LLLexer.cpp (+1) 
- (modified) llvm/lib/AsmParser/LLParser.cpp (+3) 
- (modified) llvm/lib/IR/AsmWriter.cpp (+4-1) 
- (modified) llvm/lib/Passes/PassBuilderPipelines.cpp (+1-2) 
- (modified) llvm/lib/Passes/PassesOptions.td (+1-1) 
- (modified) llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp (+74-69) 
- (modified) llvm/test/Assembler/thinlto-summary.ll (+2-2) 
- (added) llvm/test/ThinLTO/X86/devirt_speculative.ll (+71) 
- (added) llvm/test/ThinLTO/X86/devirt_speculative_mixed_vis.ll (+105) 
- (added) 
llvm/test/Transforms/WholeProgramDevirt/devirt-single-impl-check-cfi.ll (+68) 
- (added) llvm/test/Transforms/WholeProgramDevirt/speculative-devirt-cfi.ll 
(+68) 
- (added) 
llvm/test/Transforms/WholeProgramDevirt/speculative-devirt-mixed-vis.ll (+77) 
- (modified) 
llvm/test/Transforms/WholeProgramDevirt/speculative-devirt-single-impl.ll 
(+8-6) 


``````````diff
diff --git a/clang/docs/UsersManual.md b/clang/docs/UsersManual.md
index 96d1c4e009c71a..2c2c131b656e03 100644
--- a/clang/docs/UsersManual.md
+++ b/clang/docs/UsersManual.md
@@ -2589,8 +2589,6 @@ if.end.icp:                                       ; preds 
= %if.false.orig_indir
   ret void
 ```
 
-This feature is temporarily ignored at the LLVM side when LTO is enabled.
-TODO: Update the comment when the LLVM side supports this feature for LTO.
 This feature is turned off by default.
 :::
 
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 7c832ef405fa51..329f5317ea47a9 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1222,6 +1222,14 @@ void tools::addLTOOptions(const ToolChain &ToolChain, 
const ArgList &Args,
         (A->getOption().matches(options::OPT_fglobal_isel) ? "1" : "0")));
   }
 
+  if (Arg *A = Args.getLastArg(options::OPT_fdevirtualize_speculatively,
+                               options::OPT_fno_devirtualize_speculatively))
+    CmdArgs.push_back(Args.MakeArgString(
+        Twine(PluginOptPrefix) + "-devirtualize-speculatively=" +
+        (A->getOption().matches(options::OPT_fdevirtualize_speculatively)
+             ? "1"
+             : "0")));
+
   // If an explicit debugger tuning argument appeared, pass it along.
   if (Arg *A =
           Args.getLastArg(options::OPT_gTune_Group, options::OPT_ggdbN_Group)) 
{
diff --git a/clang/test/Driver/lto.c b/clang/test/Driver/lto.c
index 838eb740863752..be18231f5d335c 100644
--- a/clang/test/Driver/lto.c
+++ b/clang/test/Driver/lto.c
@@ -127,6 +127,14 @@
 // CHECK-NO-SLP: "-plugin-opt=-vectorize-slp=0"
 // CHECK-SLP:    "-plugin-opt=-vectorize-slp=1"
 
+// RUN: %clang --target=x86_64-unknown-linux -### %s -flto 
-fno-devirtualize-speculatively 2> %t
+// RUN: FileCheck --check-prefix=CHECK-NO-DEVIRTUALIZE-SPECULATIVELY < %t %s
+// RUN: %clang --target=x86_64-unknown-linux -### %s -flto 
-fdevirtualize-speculatively 2> %t
+// RUN: FileCheck --check-prefix=CHECK-DEVIRTUALIZE-SPECULATIVELY < %t %s
+//
+// CHECK-NO-DEVIRTUALIZE-SPECULATIVELY: 
"-plugin-opt=-devirtualize-speculatively=0"
+// CHECK-DEVIRTUALIZE-SPECULATIVELY:    
"-plugin-opt=-devirtualize-speculatively=1"
+
 // -flto passes -time-passes when -ftime-report is passed
 // RUN: %clang --target=x86_64-unknown-linux-gnu -### %s -flto -ftime-report 
2> %t
 // RUN: FileCheck --check-prefix=CHECK-TIME-REPORT < %t %s
diff --git a/llvm/include/llvm/AsmParser/LLToken.h 
b/llvm/include/llvm/AsmParser/LLToken.h
index 2679a630c2dd95..e5816ca301527e 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -467,6 +467,7 @@ enum Kind {
   kw_indir,
   kw_singleImpl,
   kw_branchFunnel,
+  kw_speculative,
   kw_singleImplName,
   kw_resByArg,
   kw_byArg,
diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h 
b/llvm/include/llvm/IR/ModuleSummaryIndex.h
index 4f68582b65c4eb..f9d6640f50852a 100644
--- a/llvm/include/llvm/IR/ModuleSummaryIndex.h
+++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h
@@ -1349,6 +1349,7 @@ struct WholeProgramDevirtResolution {
     BranchFunnel, ///< When retpoline mitigation is enabled, use a branch 
funnel
                   ///< that is defined in the merged module. Otherwise same as
                   ///< Indir.
+    Speculative,  ///< Speculative devirtualization
   } TheKind = Indir;
 
   std::string SingleImplName;
diff --git a/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h 
b/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h
index 158c03e77306c9..441433eb381adc 100644
--- a/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h
+++ b/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h
@@ -102,6 +102,8 @@ template <> struct 
ScalarEnumerationTraits<WholeProgramDevirtResolution::Kind> {
     io.enumCase(value, "SingleImpl", WholeProgramDevirtResolution::SingleImpl);
     io.enumCase(value, "BranchFunnel",
                 WholeProgramDevirtResolution::BranchFunnel);
+    io.enumCase(value, "Speculative",
+                WholeProgramDevirtResolution::Speculative);
   }
 };
 
diff --git a/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h 
b/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h
index c3a394ab4fb720..0dd61bbd41a4ab 100644
--- a/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h
+++ b/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h
@@ -227,14 +227,11 @@ struct WholeProgramDevirtPass
   ModuleSummaryIndex *ExportSummary;
   const ModuleSummaryIndex *ImportSummary;
   bool UseCommandLine = false;
-  bool DevirtSpeculatively = false;
   WholeProgramDevirtPass()
       : ExportSummary(nullptr), ImportSummary(nullptr), UseCommandLine(true) {}
   WholeProgramDevirtPass(ModuleSummaryIndex *ExportSummary,
-                         const ModuleSummaryIndex *ImportSummary,
-                         bool DevirtSpeculatively = false)
-      : ExportSummary(ExportSummary), ImportSummary(ImportSummary),
-        DevirtSpeculatively(DevirtSpeculatively) {
+                         const ModuleSummaryIndex *ImportSummary)
+      : ExportSummary(ExportSummary), ImportSummary(ImportSummary) {
     assert(!(ExportSummary && ImportSummary));
   }
   LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 5e52dc8dcb2478..20212fc26451aa 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -884,6 +884,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(indir);
   KEYWORD(singleImpl);
   KEYWORD(branchFunnel);
+  KEYWORD(speculative);
   KEYWORD(singleImplName);
   KEYWORD(resByArg);
   KEYWORD(byArg);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 60b7824342aa38..03a266931632cf 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -10047,6 +10047,9 @@ bool LLParser::parseWpdRes(WholeProgramDevirtResolution 
&WPDRes) {
   case lltok::kw_branchFunnel:
     WPDRes.TheKind = WholeProgramDevirtResolution::BranchFunnel;
     break;
+  case lltok::kw_speculative:
+    WPDRes.TheKind = WholeProgramDevirtResolution::Speculative;
+    break;
   default:
     return error(Lex.getLoc(), "unexpected WholeProgramDevirtResolution kind");
   }
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 1cbcfb195764b3..a30ff85e33160b 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -3402,6 +3402,8 @@ 
getWholeProgDevirtResKindName(WholeProgramDevirtResolution::Kind K) {
     return "singleImpl";
   case WholeProgramDevirtResolution::BranchFunnel:
     return "branchFunnel";
+  case WholeProgramDevirtResolution::Speculative:
+    return "speculative";
   }
   llvm_unreachable("invalid WholeProgramDevirtResolution kind");
 }
@@ -3496,7 +3498,8 @@ void AssemblyWriter::printWPDRes(const 
WholeProgramDevirtResolution &WPDRes) {
   Out << "wpdRes: (kind: ";
   Out << getWholeProgDevirtResKindName(WPDRes.TheKind);
 
-  if (WPDRes.TheKind == WholeProgramDevirtResolution::SingleImpl)
+  if (WPDRes.TheKind == WholeProgramDevirtResolution::SingleImpl ||
+      WPDRes.TheKind == WholeProgramDevirtResolution::Speculative)
     Out << ", singleImplName: \"" << WPDRes.SingleImplName << "\"";
 
   if (!WPDRes.ResByArg.empty()) {
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp 
b/llvm/lib/Passes/PassBuilderPipelines.cpp
index 125c8e442f27b6..b4ce758e314e94 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -1620,8 +1620,7 @@ 
PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
     MPM.addPass(AssignGUIDPass());
     MPM.addPass(WholeProgramDevirtPass(
         /*ExportSummary*/ nullptr,
-        /*ImportSummary*/ nullptr,
-        /*DevirtSpeculatively*/ PTO.DevirtualizeSpeculatively));
+        /*ImportSummary*/ nullptr));
     MPM.addPass(DropTypeTestsPass());
     // Given that the devirtualization creates more opportunities for inlining,
     // we run the Inliner again here to maximize the optimization gain we
diff --git a/llvm/lib/Passes/PassesOptions.td b/llvm/lib/Passes/PassesOptions.td
index 4398d5c06bff2b..d37930c7ca39d8 100644
--- a/llvm/lib/Passes/PassesOptions.td
+++ b/llvm/lib/Passes/PassesOptions.td
@@ -38,7 +38,7 @@ defm : BoolField<"enable-constraint-elimination", "true",
 // TODO: There is a similar flag in WPD pass, we should consolidate them by
 // parsing the option only once in PassBuilder and share it across both places.
 defm : BoolField<"enable-devirtualize-speculatively", "false",
-  "Enable speculative devirtualization optimization">;
+  "Enable speculative devirtualization without LTO">;
 defm : BoolField<"enable-dfa-jump-thread", "true",
   "Enable DFA jump threading">;
 defm : BoolField<"enable-global-analyses", "true",
diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp 
b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
index 88c57d2195bbda..ba0718882d77e0 100644
--- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
+++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
@@ -160,8 +160,6 @@ static cl::opt<std::string> ClWriteSummary(
              "bitcode, otherwise YAML"),
     cl::Hidden);
 
-// TODO: This option eventually should support any public visibility vtables
-// with/out LTO.
 static cl::opt<bool> ClDevirtualizeSpeculatively(
     "devirtualize-speculatively",
     cl::desc("Enable speculative devirtualization optimization"),
@@ -611,11 +609,9 @@ struct DevirtModule {
   std::map<CallInst *, unsigned> NumUnsafeUsesForTypeTest;
   PatternList FunctionsToSkip;
 
-  const bool DevirtSpeculatively;
   DevirtModule(Module &M, ModuleAnalysisManager &MAM,
                ModuleSummaryIndex *ExportSummary,
-               const ModuleSummaryIndex *ImportSummary,
-               bool DevirtSpeculatively)
+               const ModuleSummaryIndex *ImportSummary)
       : M(M), MAM(MAM),
         FAM(MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager()),
         ExportSummary(ExportSummary), ImportSummary(ImportSummary),
@@ -628,8 +624,7 @@ struct DevirtModule {
         RemarksEnabled(areRemarksEnabled()),
         OREGetter([&](Function &F) -> OptimizationRemarkEmitter & {
           return FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
-        }),
-        DevirtSpeculatively(DevirtSpeculatively) {
+        }) {
     assert(!(ExportSummary && ImportSummary));
     FunctionsToSkip.init(SkipFunctionNames);
   }
@@ -645,18 +640,18 @@ struct DevirtModule {
       std::vector<VTableBits> &Bits,
       DenseMap<Metadata *, std::set<TypeMemberInfo>> &TypeIdMap);
 
-  bool
-  tryFindVirtualCallTargets(std::vector<VirtualCallTarget> &TargetsForSlot,
-                            const std::set<TypeMemberInfo> &TypeMemberInfos,
-                            uint64_t ByteOffset,
-                            ModuleSummaryIndex *ExportSummary);
+  bool tryFindVirtualCallTargets(
+      std::vector<VirtualCallTarget> &TargetsForSlot,
+      const std::set<TypeMemberInfo> &TypeMemberInfos, uint64_t ByteOffset,
+      ModuleSummaryIndex *ExportSummary, bool &HasPublicTarget);
 
   void applySingleImplDevirt(VTableSlotInfo &SlotInfo, Constant *TheFn,
-                             bool &IsExported);
+                             bool HasPublicTarget, bool &IsExported);
   bool trySingleImplDevirt(ModuleSummaryIndex *ExportSummary,
                            MutableArrayRef<VirtualCallTarget> TargetsForSlot,
                            VTableSlotInfo &SlotInfo,
-                           WholeProgramDevirtResolution *Res);
+                           WholeProgramDevirtResolution *Res,
+                           bool HasPublicTarget);
 
   void applyICallBranchFunnel(VTableSlotInfo &SlotInfo, Function &JT,
                               bool &IsExported);
@@ -743,8 +738,7 @@ struct DevirtModule {
 
   // Lower the module using the action and summary passed as command line
   // arguments. For testing purposes only.
-  static bool runForTesting(Module &M, ModuleAnalysisManager &MAM,
-                            bool DevirtSpeculatively);
+  static bool runForTesting(Module &M, ModuleAnalysisManager &MAM);
 };
 
 struct DevirtIndex {
@@ -779,13 +773,14 @@ struct DevirtIndex {
 
   bool tryFindVirtualCallTargets(std::vector<ValueInfo> &TargetsForSlot,
                                  const TypeIdCompatibleVtableInfo TIdInfo,
-                                 uint64_t ByteOffset);
+                                 uint64_t ByteOffset, bool &HasPublicTarget);
 
   bool trySingleImplDevirt(MutableArrayRef<ValueInfo> TargetsForSlot,
                            VTableSlotSummary &SlotSummary,
                            VTableSlotInfo &SlotInfo,
                            WholeProgramDevirtResolution *Res,
-                           std::set<ValueInfo> &DevirtTargets);
+                           std::set<ValueInfo> &DevirtTargets,
+                           bool HasPublicTarget);
 
   void run();
 };
@@ -794,22 +789,17 @@ struct DevirtIndex {
 PreservedAnalyses WholeProgramDevirtPass::run(Module &M,
                                               ModuleAnalysisManager &MAM) {
   if (UseCommandLine) {
-    if (!DevirtModule::runForTesting(M, MAM, ClDevirtualizeSpeculatively))
+    if (!DevirtModule::runForTesting(M, MAM))
       return PreservedAnalyses::all();
     return PreservedAnalyses::none();
   }
 
   std::optional<ModuleSummaryIndex> Index;
-  if (!ExportSummary && !ImportSummary && DevirtSpeculatively) {
-    // Build the ExportSummary from the module.
-    assert(!ExportSummary &&
-           "ExportSummary is expected to be empty in non-LTO mode");
+  if (!ExportSummary && !ImportSummary && ClDevirtualizeSpeculatively) {
     ProfileSummaryInfo PSI(M);
-    Index.emplace(buildModuleSummaryIndex(M, nullptr, &PSI));
-    ExportSummary = Index.has_value() ? &Index.value() : nullptr;
+    ExportSummary = &Index.emplace(buildModuleSummaryIndex(M, nullptr, &PSI));
   }
-  if (!DevirtModule(M, MAM, ExportSummary, ImportSummary, DevirtSpeculatively)
-           .run())
+  if (!DevirtModule(M, MAM, ExportSummary, ImportSummary).run())
     return PreservedAnalyses::all();
   return PreservedAnalyses::none();
 }
@@ -907,9 +897,7 @@ void llvm::updatePublicTypeTestCalls(Module &M,
       CI->replaceAllUsesWith(NewCI);
       CI->eraseFromParent();
     }
-  } else {
-    // TODO: Don't replace public type tests when speculative devirtualization
-    // gets enabled in LTO mode.
+  } else if (!ClDevirtualizeSpeculatively) {
     auto *True = ConstantInt::getTrue(M.getContext());
     for (Use &U : make_early_inc_range(PublicTypeTestFunc->uses())) {
       auto *CI = cast<CallInst>(U.getUser());
@@ -1014,8 +1002,7 @@ static Error 
checkCombinedSummaryForTesting(ModuleSummaryIndex *Summary) {
   return ErrorSuccess();
 }
 
-bool DevirtModule::runForTesting(Module &M, ModuleAnalysisManager &MAM,
-                                 bool DevirtSpeculatively) {
+bool DevirtModule::runForTesting(Module &M, ModuleAnalysisManager &MAM) {
   std::unique_ptr<ModuleSummaryIndex> Summary =
       std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);
 
@@ -1044,8 +1031,7 @@ bool DevirtModule::runForTesting(Module &M, 
ModuleAnalysisManager &MAM,
                    ClSummaryAction == PassSummaryAction::Export ? Summary.get()
                                                                 : nullptr,
                    ClSummaryAction == PassSummaryAction::Import ? Summary.get()
-                                                                : nullptr,
-                   DevirtSpeculatively)
+                                                                : nullptr)
           .run();
 
   if (!ClWriteSummary.empty()) {
@@ -1104,16 +1090,19 @@ void DevirtModule::buildTypeIdentifierMap(
 bool DevirtModule::tryFindVirtualCallTargets(
     std::vector<VirtualCallTarget> &TargetsForSlot,
     const std::set<TypeMemberInfo> &TypeMemberInfos, uint64_t ByteOffset,
-    ModuleSummaryIndex *ExportSummary) {
+    ModuleSummaryIndex *ExportSummary, bool &HasPublicTarget) {
+  HasPublicTarget = false;
+
   for (const TypeMemberInfo &TM : TypeMemberInfos) {
     if (!TM.Bits->GV->isConstant())
       return false;
 
-    // Without DevirtSpeculatively, we cannot perform whole program
-    // devirtualization analysis on a vtable with public LTO visibility.
-    if (!DevirtSpeculatively && TM.Bits->GV->getVCallVisibility() ==
-                                    GlobalObject::VCallVisibilityPublic)
-      return false;
+    if (TM.Bits->GV->getVCallVisibility() ==
+        GlobalObject::VCallVisibilityPublic) {
+      HasPublicTarget = true;
+      if (!ClDevirtualizeSpeculatively)
+        return false;
+    }
 
     Function *Fn = nullptr;
     Constant *C = nullptr;
@@ -1131,12 +1120,6 @@ bool DevirtModule::tryFindVirtualCallTargets(
     if (Fn->getName() == "__cxa_pure_virtual")
       continue;
 
-    // In most cases empty functions will be overridden by the
-    // implementation of the derived class, so we can skip them.
-    if (DevirtSpeculatively && Fn->getReturnType()->isVoidTy() &&
-        Fn->getInstructionCount() <= 1)
-      continue;
-
     // We can disregard unreachable functions as possible call targets, as
     // unreachable functions shouldn't be called.
     if (mustBeUnreachableFunction(Fn, ExportSummary))
@@ -1158,7 +1141,10 @@ bool DevirtModule::tryFindVirtualCallTargets(
 
 bool DevirtIndex::tryFindVirtualCallTargets(
     std::vector<ValueInfo> &TargetsForSlot,
-    const TypeIdCompatibleVtableInfo TIdInfo, uint64_t ByteOffset) {
+    const TypeIdCompatibleVtableInfo TIdInfo, uint64_t ByteOffset,
+    bool &HasPublicTarget) {
+  HasPublicTarget = false;
+
   for (const TypeIdOffsetVtableInfo &P : TIdInfo) {
     // Find a representative copy of the vtable initializer.
     // We can have multiple available_externally, linkonce_odr and weak_odr
@@ -1187,8 +1173,11 @@ bool DevirtIndex::tryFindVirtualCallTargets(
         VS = CurVS;
         // We cannot perform whole program devirtualization analysis on a 
vtable
         // with public LTO visibility.
-        if (VS->getVCallVisibility() == GlobalObject::VCallVisibilityPublic)
-          return false;
+        if (VS->getVCallVisibility() == GlobalObject::VCallVisibilityPublic) {
+          HasPublicTarget = true;
+          if (!ClDevirtualizeSpeculatively)
+            return false;
+        }
         break;
       }
     }
@@ -1214,7 +1203,8 @@ bool DevirtIndex::tryFindVirtualCallTargets(
 }
 
 void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo,
-                                         Constant *TheFn, bool &IsExported) {
+                                         Constant *TheFn, bool HasPublicTarget,
+                                         bool &IsExported) {
   // Don't devirtualize function if we're told to skip it
   // in -wholeprogramdevirt-skip.
   if (FunctionsToSkip.match(TheFn->stripPointerCasts()->getName()))
@@ -1257,7 +1247,7 @@ void DevirtModule::applySingleImplDevirt(VTableSlotInfo 
&SlotInfo,
       // add support to compare the virtual function pointer to the
       // devirtualized target. In case of a mismatch, fall back to indirect
       // call.
-      if (DevirtCheckMode == WPDCheckMode::Fallback || DevirtSpeculatively) {
+      if (DevirtCheckMode == WPDCheckMode::Fallback || HasPublicTarget) {
         MDNode *Weights = 
MDBuilder(M.getContext()).createLikelyBranchWeights();
         // Version the indirect call site. If the called value is equal to the
         // given callee, 'NewInst' will be executed, otherwise the original 
call
@@ -1278,6 +1268,7 @@ void DevirtModule::applySingleImplDevirt(VTableSlotInfo 
&SlotInfo,
       // In either trapping or non-checking mode, devirtualize original call.
       else {
         // Devirtualize unconditionally.
+        assert(!HasPublicTarget);
         CB.setCalledOperand(Callee);
         // Since the call site is now direct, we must clear metadata that
         // is only appropriate for indirect calls. This includes !prof and
@@ -1295,7 +1286,7 @@ void DevirtModule::applySingleImplDevirt(VTableSlotInfo 
&SlotInfo,
       }
 
       // This use is no longer unsafe.
-      if (VCallSite.NumUnsafeUses)
+      if (!HasPublicTarget && VCallSite.NumUnsafeUses)
         --*VCallSite.NumUnsafeUses;
     }
     if (CSInfo.isExported())
@@ -1338,7 +1329,7 @@ static bool addCalls(VTable...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/233380
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to