[ThinLTO][WPD]Skip virtual function entries in combined index when virtual function elimination is off
diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
index 611d4bf..18a65da 100644
--- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
+++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
@@ -814,7 +814,7 @@
/// Record vtable definition \p V for each type metadata it references.
static void
recordTypeIdCompatibleVtableReferences(ModuleSummaryIndex &Index,
- const GlobalVariable &V,
+ const GlobalVariable &V, const bool VFE,
SmallVectorImpl<MDNode *> &Types) {
for (MDNode *Type : Types) {
auto TypeID = Type->getOperand(1).get();
@@ -824,16 +824,21 @@
cast<ConstantAsMetadata>(Type->getOperand(0))->getValue())
->getZExtValue();
- if (auto *TypeId = dyn_cast<MDString>(TypeID))
- Index.getOrInsertTypeIdCompatibleVtableSummary(TypeId->getString())
- .push_back({Offset, Index.getOrInsertValueInfo(&V)});
+ if (auto *TypeId = dyn_cast<MDString>(TypeID)) {
+ StringRef TypeIdStr = TypeId->getString();
+ // Skip virtual function entries if VFE is not enabled.
+ if (!VFE && TypeIdStr.ends_with(".virtual"))
+ continue;
+ Index.getOrInsertTypeIdCompatibleVtableSummary(TypeIdStr).push_back(
+ {Offset, Index.getOrInsertValueInfo(&V)});
+ }
}
}
static void computeVariableSummary(ModuleSummaryIndex &Index,
const GlobalVariable &V,
DenseSet<GlobalValue::GUID> &CantBePromoted,
- const Module &M,
+ const Module &M, const bool VFE,
SmallVectorImpl<MDNode *> &Types) {
SetVector<ValueInfo, SmallVector<ValueInfo, 0>> RefEdges;
SmallPtrSet<const User *, 8> Visited;
@@ -858,7 +863,7 @@
computeVTableFuncs(Index, V, M, VTableFuncs);
// Record this vtable definition for each type metadata it references.
- recordTypeIdCompatibleVtableReferences(Index, V, Types);
+ recordTypeIdCompatibleVtableReferences(Index, V, VFE, Types);
}
}
@@ -911,20 +916,25 @@
Summary->setLive(true);
}
+// If \p M has a integer module flag with \p Name, returns true if the value is
+// non-zero and false if the value is zero. If the module flag does not exist,
+// returns \p Default.
+static bool getModuleFlag(const Module &M, StringRef Name,
+ bool Default = false) {
+ if (auto *MD = mdconst::extract_or_null<ConstantInt>(M.getModuleFlag(Name)))
+ return MD->getZExtValue() != 0;
+ return Default;
+}
+
ModuleSummaryIndex llvm::buildModuleSummaryIndex(
const Module &M,
std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback,
ProfileSummaryInfo *PSI,
std::function<const StackSafetyInfo *(const Function &F)> GetSSICallback) {
assert(PSI);
- bool EnableSplitLTOUnit = false;
- bool UnifiedLTO = false;
- if (auto *MD = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("EnableSplitLTOUnit")))
- EnableSplitLTOUnit = MD->getZExtValue();
- if (auto *MD =
- mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("UnifiedLTO")))
- UnifiedLTO = MD->getZExtValue();
+ const bool EnableSplitLTOUnit = getModuleFlag(M, "EnableSplitLTOUnit");
+ const bool UnifiedLTO = getModuleFlag(M, "UnifiedLTO");
+
ModuleSummaryIndex Index(/*HaveGVs=*/true, EnableSplitLTOUnit, UnifiedLTO);
// Identify the local values in the llvm.used and llvm.compiler.used sets,
@@ -1014,10 +1024,7 @@
});
}
- bool IsThinLTO = true;
- if (auto *MD =
- mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("ThinLTO")))
- IsThinLTO = MD->getZExtValue();
+ const bool IsThinLTO = getModuleFlag(M, "ThinLTO", /*Default=*/true);
// Compute summaries for all functions defined in module, and save in the
// index.
@@ -1042,13 +1049,15 @@
CantBePromoted, IsThinLTO, GetSSICallback);
}
+ const bool VFE = getModuleFlag(M, "Virtual Function Elim");
+
// Compute summaries for all variables defined in module, and save in the
// index.
SmallVector<MDNode *, 2> Types;
for (const GlobalVariable &G : M.globals()) {
if (G.isDeclaration())
continue;
- computeVariableSummary(Index, G, CantBePromoted, M, Types);
+ computeVariableSummary(Index, G, CantBePromoted, M, VFE, Types);
}
// Compute summaries for all aliases defined in module, and save in the
diff --git a/llvm/test/Assembler/thinlto-vtable-summary-vfe.ll b/llvm/test/Assembler/thinlto-vtable-summary-vfe.ll
new file mode 100644
index 0000000..d47d9b3
--- /dev/null
+++ b/llvm/test/Assembler/thinlto-vtable-summary-vfe.ll
@@ -0,0 +1,31 @@
+;; Test that a virtual function has a typeidCompatibleVTable entry when virtual
+;; function elimination is enabled.
+
+; RUN: opt %s -S -module-summary | FileCheck %s
+
+;; These summary entries should get numbered differently.
+; CHECK: ^2 = gv: (name: "_ZTS1A"
+; CHECK: ^6 = typeidCompatibleVTable: (name: "_ZTS1A"
+; CHECK: typeidCompatibleVTable: (name: "_ZTSM1AFivE.virtual"
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@_ZTV1A = dso_local unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI1A, ptr @_ZN1A3fooEv] }, align 8, !type !0, !type !1
+@_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr]
+@_ZTS1A = dso_local constant [3 x i8] c"1A\00", align 1
+@_ZTI1A = dso_local constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS1A }
+
+define i32 @_ZN1A3fooEv(ptr %this) {
+entry:
+ %this.addr = alloca ptr
+ store ptr %this, ptr %this.addr
+ %this1 = load ptr, ptr %this.addr
+ ret i32 1
+}
+
+!llvm.module.flags = !{!2}
+
+!0 = !{i64 16, !"_ZTS1A"}
+!1 = !{i64 16, !"_ZTSM1AFivE.virtual"}
+!2 = !{i32 1, !"Virtual Function Elim", i32 1}
diff --git a/llvm/test/Assembler/thinlto-vtable-summary2.ll b/llvm/test/Assembler/thinlto-vtable-summary2.ll
index 862b7ab..6c5d479 100644
--- a/llvm/test/Assembler/thinlto-vtable-summary2.ll
+++ b/llvm/test/Assembler/thinlto-vtable-summary2.ll
@@ -7,8 +7,11 @@
; RUN: opt %s -S -module-summary -o - | llvm-as -o - | llvm-dis -o - | FileCheck %s
;; These summary entries should get numbered differently.
+;; When virtual function elimination is not enabled (the default case),
+;; there is no need to generate typeidCompatibleVTable entries for virtual functions.
; CHECK: ^2 = gv: (name: "_ZTS1A"
; CHECK: ^6 = typeidCompatibleVTable: (name: "_ZTS1A"
+; CHECK-NOT: typeidCompatibleVTable: (name: "_ZTSM1AFivE.virtual"
; ModuleID = 'thinlto-vtable-summary2.cc'
source_filename = "thinlto-vtable-summary2.cc"