[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"