tejohnson updated this revision to Diff 235509.
tejohnson added a comment.

Implement suggested name change.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71911/new/

https://reviews.llvm.org/D71911

Files:
  clang/lib/CodeGen/CGVTables.cpp
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/test/CodeGenCXX/vcall-visibility-metadata.cpp
  llvm/include/llvm/IR/GlobalObject.h
  llvm/include/llvm/IR/ModuleSummaryIndex.h
  llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
  llvm/lib/AsmParser/LLLexer.cpp
  llvm/lib/AsmParser/LLParser.cpp
  llvm/lib/AsmParser/LLToken.h
  llvm/lib/Bitcode/Reader/BitcodeReader.cpp
  llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
  llvm/lib/IR/AsmWriter.cpp
  llvm/lib/IR/Metadata.cpp
  llvm/lib/Transforms/IPO/GlobalDCE.cpp
  llvm/lib/Transforms/IPO/GlobalSplit.cpp
  llvm/test/Assembler/thinlto-vtable-summary.ll
  llvm/test/Transforms/GlobalDCE/virtual-functions-base-call.ll
  llvm/test/Transforms/GlobalDCE/virtual-functions-base-pointer-call.ll
  llvm/test/Transforms/GlobalDCE/virtual-functions-derived-call.ll
  llvm/test/Transforms/GlobalDCE/virtual-functions-derived-pointer-call.ll
  llvm/test/Transforms/GlobalDCE/virtual-functions-novfe.ll
  llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-post-lto.ll
  llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-pre-lto.ll
  llvm/test/Transforms/GlobalDCE/virtual-functions.ll
  llvm/test/Transforms/GlobalDCE/vtable-rtti.ll

Index: llvm/test/Transforms/GlobalDCE/vtable-rtti.ll
===================================================================
--- llvm/test/Transforms/GlobalDCE/vtable-rtti.ll
+++ llvm/test/Transforms/GlobalDCE/vtable-rtti.ll
@@ -39,9 +39,10 @@
 declare dso_local noalias nonnull i8* @_Znwm(i64)
 @_ZTVN10__cxxabiv117__class_type_infoE = external dso_local global i8*
 
-!llvm.module.flags = !{!3}
+!llvm.module.flags = !{!3, !4}
 
 !0 = !{i64 16, !"_ZTS1A"}
 !1 = !{i64 16, !"_ZTSM1AFvvE.virtual"}
 !2 = !{i64 2} ; translation-unit vcall visibility
 !3 = !{i32 1, !"LTOPostLink", i32 1}
+!4 = !{i32 1, !"Virtual Function Elim", i32 1}
Index: llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-pre-lto.ll
===================================================================
--- llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-pre-lto.ll
+++ llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-pre-lto.ll
@@ -85,10 +85,11 @@
 
 declare dso_local noalias nonnull i8* @_Znwm(i64)
 
-!llvm.module.flags = !{}
+!llvm.module.flags = !{!5}
 
 !0 = !{i64 16, !"_ZTS1A"}
 !1 = !{i64 16, !"_ZTSM1AFvvE.virtual"}
 !2 = !{i64 0} ; public vcall visibility
 !3 = !{i64 1} ; linkage-unit vcall visibility
 !4 = !{i64 2} ; translation-unit vcall visibility
+!5 = !{i32 1, !"Virtual Function Elim", i32 1}
Index: llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-post-lto.ll
===================================================================
--- llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-post-lto.ll
+++ llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-post-lto.ll
@@ -85,7 +85,7 @@
 
 declare dso_local noalias nonnull i8* @_Znwm(i64)
 
-!llvm.module.flags = !{!5}
+!llvm.module.flags = !{!5, !6}
 
 !0 = !{i64 16, !"_ZTS1A"}
 !1 = !{i64 16, !"_ZTSM1AFvvE.virtual"}
@@ -93,3 +93,4 @@
 !3 = !{i64 1} ; linkage-unit vcall visibility
 !4 = !{i64 2} ; translation-unit vcall visibility
 !5 = !{i32 1, !"LTOPostLink", i32 1}
+!6 = !{i32 1, !"Virtual Function Elim", i32 1}
Index: llvm/test/Transforms/GlobalDCE/virtual-functions.ll
===================================================================
--- llvm/test/Transforms/GlobalDCE/virtual-functions.ll
+++ llvm/test/Transforms/GlobalDCE/virtual-functions.ll
@@ -48,8 +48,11 @@
   ret i32 %call1
 }
 
+!llvm.module.flags = !{!4}
+
 !0 = !{i64 16, !"_ZTS1A"}
 !1 = !{i64 16, !"_ZTSM1AFivE.virtual"}
 !2 = !{i64 24, !"_ZTSM1AFivE.virtual"}
 !3 = !{i64 2}
+!4 = !{i32 1, !"Virtual Function Elim", i32 1}
 !9 = !{}
Index: llvm/test/Transforms/GlobalDCE/virtual-functions-novfe.ll
===================================================================
--- llvm/test/Transforms/GlobalDCE/virtual-functions-novfe.ll
+++ llvm/test/Transforms/GlobalDCE/virtual-functions-novfe.ll
@@ -1,3 +1,5 @@
+; Tests that VFE is not performed when the Virtual Function Elim metadata set
+; to 0. This is the same as virtual-functions.ll otherwise.
 ; RUN: opt < %s -globaldce -S | FileCheck %s
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
@@ -11,14 +13,12 @@
 ; intrinsic. Function test_A makes a call to A::foo, but there is no call to
 ; A::bar anywhere, so A::bar can be deleted, and its vtable slot replaced with
 ; null.
+; However, with the metadata set to 0 we should not perform this VFE.
 
 %struct.A = type { i32 (...)** }
 
-; The pointer to A::bar in the vtable can be removed, because it will never be
-; loaded. We replace it with null to keep the layout the same. Because it is at
-; the end of the vtable we could potentially shrink the vtable, but don't
-; currently do that.
-; CHECK: @_ZTV1A = internal unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* null, i8* bitcast (i32 (%struct.A*)* @_ZN1A3fooEv to i8*), i8* null] }
+; We should retain @_ZN1A3barEv in the vtable.
+; CHECK: @_ZTV1A = internal unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* null, i8* bitcast (i32 (%struct.A*)* @_ZN1A3fooEv to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3barEv to i8*)] }
 @_ZTV1A = internal unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* null, i8* bitcast (i32 (%struct.A*)* @_ZN1A3fooEv to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3barEv to i8*)] }, align 8, !type !0, !type !1, !type !2, !vcall_visibility !3
 
 ; A::foo is called, so must be retained.
@@ -28,8 +28,9 @@
   ret i32 42
 }
 
-; A::bar is not used, so can be deleted.
-; CHECK-NOT: define internal i32 @_ZN1A3barEv(
+; A::bar is not used, so can be deleted with VFE, however, we should not be
+; performing that elimination here.
+; CHECK: define internal i32 @_ZN1A3barEv(
 define internal i32 @_ZN1A3barEv(%struct.A* nocapture readnone %this) {
 entry:
   ret i32 1337
@@ -48,8 +49,11 @@
   ret i32 %call1
 }
 
+!llvm.module.flags = !{!4}
+
 !0 = !{i64 16, !"_ZTS1A"}
 !1 = !{i64 16, !"_ZTSM1AFivE.virtual"}
 !2 = !{i64 24, !"_ZTSM1AFivE.virtual"}
 !3 = !{i64 2}
+!4 = !{i32 1, !"Virtual Function Elim", i32 0}
 !9 = !{}
Index: llvm/test/Transforms/GlobalDCE/virtual-functions-derived-pointer-call.ll
===================================================================
--- llvm/test/Transforms/GlobalDCE/virtual-functions-derived-pointer-call.ll
+++ llvm/test/Transforms/GlobalDCE/virtual-functions-derived-pointer-call.ll
@@ -110,6 +110,8 @@
 
 declare { i8*, i1 } @llvm.type.checked.load(i8*, i32, metadata)
 
+!llvm.module.flags = !{!7}
+
 !0 = !{i64 16, !"_ZTS1A"}
 !1 = !{i64 16, !"_ZTSM1AFiiE.virtual"}
 !2 = !{i64 24, !"_ZTSM1AFifE.virtual"}
@@ -117,4 +119,5 @@
 !4 = !{i64 16, !"_ZTS1B"}
 !5 = !{i64 16, !"_ZTSM1BFiiE.virtual"}
 !6 = !{i64 24, !"_ZTSM1BFifE.virtual"}
+!7 = !{i32 1, !"Virtual Function Elim", i32 1}
 !12 = !{}
Index: llvm/test/Transforms/GlobalDCE/virtual-functions-derived-call.ll
===================================================================
--- llvm/test/Transforms/GlobalDCE/virtual-functions-derived-call.ll
+++ llvm/test/Transforms/GlobalDCE/virtual-functions-derived-call.ll
@@ -70,9 +70,12 @@
 
 declare { i8*, i1 } @llvm.type.checked.load(i8*, i32, metadata) #2
 
+!llvm.module.flags = !{!5}
+
 !0 = !{i64 16, !"_ZTS1A"}
 !1 = !{i64 16, !"_ZTSM1AFivE.virtual"}
 !2 = !{i64 2}
 !3 = !{i64 16, !"_ZTS1B"}
 !4 = !{i64 16, !"_ZTSM1BFivE.virtual"}
+!5 = !{i32 1, !"Virtual Function Elim", i32 1}
 !10 = !{}
Index: llvm/test/Transforms/GlobalDCE/virtual-functions-base-pointer-call.ll
===================================================================
--- llvm/test/Transforms/GlobalDCE/virtual-functions-base-pointer-call.ll
+++ llvm/test/Transforms/GlobalDCE/virtual-functions-base-pointer-call.ll
@@ -108,6 +108,8 @@
 
 declare { i8*, i1 } @llvm.type.checked.load(i8*, i32, metadata)
 
+!llvm.module.flags = !{!7}
+
 !0 = !{i64 16, !"_ZTS1A"}
 !1 = !{i64 16, !"_ZTSM1AFiiE.virtual"}
 !2 = !{i64 24, !"_ZTSM1AFifE.virtual"}
@@ -115,4 +117,5 @@
 !4 = !{i64 16, !"_ZTS1B"}
 !5 = !{i64 16, !"_ZTSM1BFiiE.virtual"}
 !6 = !{i64 24, !"_ZTSM1BFifE.virtual"}
+!7 = !{i32 1, !"Virtual Function Elim", i32 1}
 !12 = !{}
Index: llvm/test/Transforms/GlobalDCE/virtual-functions-base-call.ll
===================================================================
--- llvm/test/Transforms/GlobalDCE/virtual-functions-base-call.ll
+++ llvm/test/Transforms/GlobalDCE/virtual-functions-base-call.ll
@@ -70,9 +70,12 @@
 
 declare { i8*, i1 } @llvm.type.checked.load(i8*, i32, metadata) #2
 
+!llvm.module.flags = !{!5}
+
 !0 = !{i64 16, !"_ZTS1A"}
 !1 = !{i64 16, !"_ZTSM1AFivE.virtual"}
 !2 = !{i64 2}
 !3 = !{i64 16, !"_ZTS1B"}
 !4 = !{i64 16, !"_ZTSM1BFivE.virtual"}
+!5 = !{i32 1, !"Virtual Function Elim", i32 1}
 !10 = !{}
Index: llvm/test/Assembler/thinlto-vtable-summary.ll
===================================================================
--- llvm/test/Assembler/thinlto-vtable-summary.ll
+++ llvm/test/Assembler/thinlto-vtable-summary.ll
@@ -29,9 +29,9 @@
 
 ^0 = module: (path: "<stdin>", hash: (0, 0, 0, 0, 0))
 ^1 = gv: (name: "_ZN1A1nEi") ; guid = 1621563287929432257
-^2 = gv: (name: "_ZTV1B", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0), vTableFuncs: ((virtFunc: ^3, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^3, ^1)))) ; guid = 5283576821522790367
+^2 = gv: (name: "_ZTV1B", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0, vcall_visibility: 0), vTableFuncs: ((virtFunc: ^3, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^3, ^1)))) ; guid = 5283576821522790367
 ^3 = gv: (name: "_ZN1B1fEi") ; guid = 7162046368816414394
-^4 = gv: (name: "_ZTV1C", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0), vTableFuncs: ((virtFunc: ^5, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^1, ^5)))) ; guid = 13624023785555846296
+^4 = gv: (name: "_ZTV1C", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0, vcall_visibility: 0), vTableFuncs: ((virtFunc: ^5, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^1, ^5)))) ; guid = 13624023785555846296
 ^5 = gv: (name: "_ZN1C1fEi") ; guid = 14876272565662207556
 ^6 = typeidCompatibleVTable: (name: "_ZTS1A", summary: ((offset: 16, ^2), (offset: 16, ^4))) ; guid = 7004155349499253778
 ^7 = typeidCompatibleVTable: (name: "_ZTS1B", summary: ((offset: 16, ^2))) ; guid = 6203814149063363976
Index: llvm/lib/Transforms/IPO/GlobalSplit.cpp
===================================================================
--- llvm/lib/Transforms/IPO/GlobalSplit.cpp
+++ llvm/lib/Transforms/IPO/GlobalSplit.cpp
@@ -111,6 +111,9 @@
                             ConstantInt::get(Int32Ty, ByteOffset - SplitBegin)),
                         Type->getOperand(1)}));
     }
+
+    if (GV.hasMetadata(LLVMContext::MD_vcall_visibility))
+      SplitGV->setVCallVisibilityMetadata(GV.getVCallVisibility());
   }
 
   for (User *U : GV.users()) {
Index: llvm/lib/Transforms/IPO/GlobalDCE.cpp
===================================================================
--- llvm/lib/Transforms/IPO/GlobalDCE.cpp
+++ llvm/lib/Transforms/IPO/GlobalDCE.cpp
@@ -263,6 +263,15 @@
   if (!ClEnableVFE)
     return;
 
+  // If the Virtual Function Elim module flag is present and set to zero, then
+  // the vcall_visibility metadata was inserted for another optimization (WPD)
+  // and we may not have type checked loads on all accesses to the vtable.
+  // Don't attempt VFE in that case.
+  auto *Val = mdconst::dyn_extract_or_null<ConstantInt>(
+      M.getModuleFlag("Virtual Function Elim"));
+  if (!Val || Val->getZExtValue() == 0)
+    return;
+
   ScanVTables(M);
 
   if (VFESafeVTables.empty())
Index: llvm/lib/IR/Metadata.cpp
===================================================================
--- llvm/lib/IR/Metadata.cpp
+++ llvm/lib/IR/Metadata.cpp
@@ -1499,7 +1499,10 @@
                      TypeID}));
 }
 
-void GlobalObject::addVCallVisibilityMetadata(VCallVisibility Visibility) {
+void GlobalObject::setVCallVisibilityMetadata(VCallVisibility Visibility) {
+  // Remove any existing vcall visibility metadata first in case we are
+  // updating.
+  eraseMetadata(LLVMContext::MD_vcall_visibility);
   addMetadata(LLVMContext::MD_vcall_visibility,
               *MDNode::get(getContext(),
                            {ConstantAsMetadata::get(ConstantInt::get(
Index: llvm/lib/IR/AsmWriter.cpp
===================================================================
--- llvm/lib/IR/AsmWriter.cpp
+++ llvm/lib/IR/AsmWriter.cpp
@@ -2896,10 +2896,14 @@
 }
 
 void AssemblyWriter::printGlobalVarSummary(const GlobalVarSummary *GS) {
+  auto VTableFuncs = GS->vTableFuncs();
   Out << ", varFlags: (readonly: " << GS->VarFlags.MaybeReadOnly << ", "
-      << "writeonly: " << GS->VarFlags.MaybeWriteOnly << ")";
+      << "writeonly: " << GS->VarFlags.MaybeWriteOnly;
+  if (!VTableFuncs.empty())
+    Out << ", "
+        << "vcall_visibility: " << GS->VarFlags.VCallVisibility;
+  Out << ")";
 
-  auto VTableFuncs = GS->vTableFuncs();
   if (!VTableFuncs.empty()) {
     Out << ", vTableFuncs: (";
     FieldSeparator FS;
Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
===================================================================
--- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1028,7 +1028,8 @@
 }
 
 static uint64_t getEncodedGVarFlags(GlobalVarSummary::GVarFlags Flags) {
-  uint64_t RawFlags = Flags.MaybeReadOnly | (Flags.MaybeWriteOnly << 1);
+  uint64_t RawFlags = Flags.MaybeReadOnly | (Flags.MaybeWriteOnly << 1) |
+                      Flags.VCallVisibility << 2;
   return RawFlags;
 }
 
Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp
===================================================================
--- llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -985,8 +985,9 @@
 
 // Decode the flags for GlobalVariable in the summary
 static GlobalVarSummary::GVarFlags getDecodedGVarFlags(uint64_t RawFlags) {
-  return GlobalVarSummary::GVarFlags((RawFlags & 0x1) ? true : false,
-                                     (RawFlags & 0x2) ? true : false);
+  return GlobalVarSummary::GVarFlags(
+      (RawFlags & 0x1) ? true : false, (RawFlags & 0x2) ? true : false,
+      (GlobalObject::VCallVisibility)(RawFlags >> 2));
 }
 
 static GlobalValue::VisibilityTypes getDecodedVisibility(unsigned Val) {
Index: llvm/lib/AsmParser/LLToken.h
===================================================================
--- llvm/lib/AsmParser/LLToken.h
+++ llvm/lib/AsmParser/LLToken.h
@@ -421,6 +421,7 @@
   kw_sizeM1,
   kw_bitMask,
   kw_inlineBits,
+  kw_vcall_visibility,
   kw_wpdResolutions,
   kw_wpdRes,
   kw_indir,
Index: llvm/lib/AsmParser/LLParser.cpp
===================================================================
--- llvm/lib/AsmParser/LLParser.cpp
+++ llvm/lib/AsmParser/LLParser.cpp
@@ -8856,6 +8856,11 @@
         return true;
       GVarFlags.MaybeWriteOnly = Flag;
       break;
+    case lltok::kw_vcall_visibility:
+      if (ParseRest(Flag))
+        return true;
+      GVarFlags.VCallVisibility = Flag;
+      break;
     default:
       return Error(Lex.getLoc(), "expected gvar flag type");
     }
Index: llvm/lib/AsmParser/LLLexer.cpp
===================================================================
--- llvm/lib/AsmParser/LLLexer.cpp
+++ llvm/lib/AsmParser/LLLexer.cpp
@@ -788,6 +788,7 @@
   KEYWORD(sizeM1);
   KEYWORD(bitMask);
   KEYWORD(inlineBits);
+  KEYWORD(vcall_visibility);
   KEYWORD(wpdResolutions);
   KEYWORD(wpdRes);
   KEYWORD(indir);
Index: llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
===================================================================
--- llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
+++ llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
@@ -599,7 +599,8 @@
   bool CanBeInternalized =
       !V.hasComdat() && !V.hasAppendingLinkage() && !V.isInterposable() &&
       !V.hasAvailableExternallyLinkage() && !V.hasDLLExportStorageClass();
-  GlobalVarSummary::GVarFlags VarFlags(CanBeInternalized, CanBeInternalized);
+  GlobalVarSummary::GVarFlags VarFlags(CanBeInternalized, CanBeInternalized,
+                                       V.getVCallVisibility());
   auto GVarSummary = std::make_unique<GlobalVarSummary>(Flags, VarFlags,
                                                          RefEdges.takeVector());
   if (NonRenamableLocal)
Index: llvm/include/llvm/IR/ModuleSummaryIndex.h
===================================================================
--- llvm/include/llvm/IR/ModuleSummaryIndex.h
+++ llvm/include/llvm/IR/ModuleSummaryIndex.h
@@ -757,14 +757,20 @@
 
 public:
   struct GVarFlags {
-    GVarFlags(bool ReadOnly, bool WriteOnly)
-        : MaybeReadOnly(ReadOnly), MaybeWriteOnly(WriteOnly) {}
+    GVarFlags(
+        bool ReadOnly, bool WriteOnly,
+        GlobalObject::VCallVisibility Vis = GlobalObject::VCallVisibilityPublic)
+        : MaybeReadOnly(ReadOnly), MaybeWriteOnly(WriteOnly),
+          VCallVisibility(Vis) {}
 
     // In permodule summaries both MaybeReadOnly and MaybeWriteOnly
     // bits are set, because attribute propagation occurs later on
     // thin link phase.
     unsigned MaybeReadOnly : 1;
     unsigned MaybeWriteOnly : 1;
+    // Set from metadata on vtable definitions during the module summary
+    // analysis.
+    unsigned VCallVisibility : 2;
   } VarFlags;
 
   GlobalVarSummary(GVFlags Flags, GVarFlags VarFlags,
@@ -782,6 +788,12 @@
   void setWriteOnly(bool WO) { VarFlags.MaybeWriteOnly = WO; }
   bool maybeReadOnly() const { return VarFlags.MaybeReadOnly; }
   bool maybeWriteOnly() const { return VarFlags.MaybeWriteOnly; }
+  void setVCallVisibility(GlobalObject::VCallVisibility Vis) {
+    VarFlags.VCallVisibility = Vis;
+  }
+  GlobalObject::VCallVisibility getVCallVisibility() const {
+    return (GlobalObject::VCallVisibility)VarFlags.VCallVisibility;
+  }
 
   void setVTableFuncs(VTableFuncList Funcs) {
     assert(!VTableFuncs);
Index: llvm/include/llvm/IR/GlobalObject.h
===================================================================
--- llvm/include/llvm/IR/GlobalObject.h
+++ llvm/include/llvm/IR/GlobalObject.h
@@ -178,7 +178,7 @@
   void copyMetadata(const GlobalObject *Src, unsigned Offset);
 
   void addTypeMetadata(unsigned Offset, Metadata *TypeID);
-  void addVCallVisibilityMetadata(VCallVisibility Visibility);
+  void setVCallVisibilityMetadata(VCallVisibility Visibility);
   VCallVisibility getVCallVisibility() const;
 
 protected:
Index: clang/test/CodeGenCXX/vcall-visibility-metadata.cpp
===================================================================
--- clang/test/CodeGenCXX/vcall-visibility-metadata.cpp
+++ clang/test/CodeGenCXX/vcall-visibility-metadata.cpp
@@ -1,4 +1,8 @@
-// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -emit-llvm -fvirtual-function-elimination -fwhole-program-vtables -o - %s | FileCheck %s
+// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -emit-llvm -fvirtual-function-elimination -fwhole-program-vtables -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VFE
+// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -emit-llvm -fwhole-program-vtables -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOVFE
+
+// Check that in ThinLTO we also get vcall_visibility summary entries in the bitcode
+// RUN: %clang_cc1 -flto=thin -flto-unit -triple x86_64-unknown-linux -emit-llvm-bc -fwhole-program-vtables -o - %s | llvm-dis -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOVFE --check-prefix=CHECK-SUMMARY
 
 
 // Anonymous namespace.
@@ -83,6 +87,15 @@
   return new G();
 }
 
-
 // CHECK-DAG: [[VIS_DSO]] = !{i64 1}
 // CHECK-DAG: [[VIS_TU]] = !{i64 2}
+// CHECK-VFE-DAG: !{i32 1, !"Virtual Function Elim", i32 1}
+// CHECK-NOVFE-DAG: !{i32 1, !"Virtual Function Elim", i32 0}
+
+// CHECK-SUMMARY-DAG: gv: (name: "_ZTV1B", {{.*}} vcall_visibility: 1
+// CHECK-SUMMARY-DAG: gv: (name: "_ZTVN12_GLOBAL__N_11FE", {{.*}} vcall_visibility: 0
+// CHECK-SUMMARY-DAG: gv: (name: "_ZTV1D", {{.*}} vcall_visibility: 0
+// CHECK-SUMMARY-DAG: gv: (name: "_ZTV1C", {{.*}} vcall_visibility: 0
+// CHECK-SUMMARY-DAG: gv: (name: "_ZTV1E", {{.*}} vcall_visibility: 0
+// CHECK-SUMMARY-DAG: gv: (name: "_ZTVN12_GLOBAL__N_11AE", {{.*}} vcall_visibility: 2
+// CHECK-SUMMARY-DAG: gv: (name: "_ZTVN12_GLOBAL__N_11GE", {{.*}} vcall_visibility: 1
Index: clang/lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -670,6 +670,10 @@
                             CGM.HasHiddenLTOVisibility(RD);
   bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&
                            CGM.HasHiddenLTOVisibility(RD);
+  // Emit type test when WPD enabled, as we need to ignore vcall_visibility
+  // used without type checked loads when attempting VFE.
+  bool ShouldEmitWPDInfo = CGM.getCodeGenOpts().WholeProgramVTables &&
+                           CGM.HasHiddenLTOVisibility(RD);
   llvm::Value *VirtualFn = nullptr;
 
   {
@@ -677,8 +681,9 @@
     llvm::Value *TypeId = nullptr;
     llvm::Value *CheckResult = nullptr;
 
-    if (ShouldEmitCFICheck || ShouldEmitVFEInfo) {
-      // If doing CFI or VFE, we will need the metadata node to check against.
+    if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) {
+      // If doing CFI, VFE or WPD, we will need the metadata node to check
+      // against.
       llvm::Metadata *MD =
           CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0));
       TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
@@ -702,7 +707,7 @@
     } else {
       // When not doing VFE, emit a normal load, as it allows more
       // optimisations than type.checked.load.
-      if (ShouldEmitCFICheck) {
+      if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {
         CheckResult = Builder.CreateCall(
             CGM.getIntrinsic(llvm::Intrinsic::type_test),
             {Builder.CreateBitCast(VFPAddr, CGF.Int8PtrTy), TypeId});
@@ -713,7 +718,8 @@
                                             "memptr.virtualfn");
     }
     assert(VirtualFn && "Virtual fuction pointer not created!");
-    assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || CheckResult) &&
+    assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo ||
+            CheckResult) &&
            "Check result required but not created!");
 
     if (ShouldEmitCFICheck) {
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -542,6 +542,14 @@
     getModule().addModuleFlag(llvm::Module::Override, "Cross-DSO CFI", 1);
   }
 
+  if (CodeGenOpts.WholeProgramVTables) {
+    // Indicate whether VFE was enabled for this module, so that the
+    // vcall_visibility metadata added under whole program vtables is handled
+    // appropriately in the optimizer.
+    getModule().addModuleFlag(llvm::Module::Error, "Virtual Function Elim",
+                              CodeGenOpts.VirtualFunctionElimination);
+  }
+
   if (LangOpts.Sanitize.has(SanitizerKind::CFIICall)) {
     getModule().addModuleFlag(llvm::Module::Override,
                               "CFI Canonical Jump Tables",
Index: clang/lib/CodeGen/CGVTables.cpp
===================================================================
--- clang/lib/CodeGen/CGVTables.cpp
+++ clang/lib/CodeGen/CGVTables.cpp
@@ -1126,9 +1126,10 @@
     }
   }
 
-  if (getCodeGenOpts().VirtualFunctionElimination) {
+  if (getCodeGenOpts().VirtualFunctionElimination ||
+      getCodeGenOpts().WholeProgramVTables) {
     llvm::GlobalObject::VCallVisibility TypeVis = GetVCallVisibilityLevel(RD);
     if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)
-      VTable->addVCallVisibilityMetadata(TypeVis);
+      VTable->setVCallVisibilityMetadata(TypeVis);
   }
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to