llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-llvm-ir

Author: None (luxufan)

<details>
<summary>Changes</summary>

This commit enhances the ThinLTO pipeline to support the elimination of unused 
Run-Time Type Information (RTTI) data when the `-fno-split-lto-unit` flag is 
used. Previously, dead RTTI data was not effectively removed, leading to larger 
binary sizes.

---

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


26 Files Affected:

- (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+1) 
- (added) clang/test/CodeGenCXX/typeid-type-test.cpp (+32) 
- (modified) llvm/include/llvm/Analysis/TypeMetadataUtils.h (+2) 
- (modified) llvm/include/llvm/AsmParser/LLParser.h (+1) 
- (modified) llvm/include/llvm/AsmParser/LLToken.h (+1) 
- (modified) llvm/include/llvm/Bitcode/LLVMBitCodes.h (+1) 
- (modified) llvm/include/llvm/IR/ModuleSummaryIndex.h (+22) 
- (modified) llvm/include/llvm/LTO/LTO.h (+10-2) 
- (added) llvm/include/llvm/Support/LibCXXABI.h (+49) 
- (added) llvm/include/llvm/Transforms/IPO/DeadRTTIElimination.h (+21) 
- (modified) llvm/lib/Analysis/ModuleSummaryAnalysis.cpp (+64-2) 
- (modified) llvm/lib/Analysis/TypeMetadataUtils.cpp (+61) 
- (modified) llvm/lib/AsmParser/LLLexer.cpp (+1) 
- (modified) llvm/lib/AsmParser/LLParser.cpp (+30) 
- (modified) llvm/lib/Bitcode/Reader/BitcodeReader.cpp (+13) 
- (modified) llvm/lib/Bitcode/Writer/BitcodeWriter.cpp (+15) 
- (modified) llvm/lib/IR/AsmWriter.cpp (+12) 
- (modified) llvm/lib/LTO/LTO.cpp (+25-9) 
- (modified) llvm/lib/LTO/LTOBackend.cpp (+13-3) 
- (modified) llvm/lib/Support/CMakeLists.txt (+1) 
- (added) llvm/lib/Support/LibCXXABI.cpp (+25) 
- (modified) llvm/lib/Transforms/IPO/CMakeLists.txt (+1) 
- (added) llvm/lib/Transforms/IPO/DeadRTTIElimination.cpp (+46) 
- (added) llvm/test/Assembler/thinlto-rtti-summary.ll (+20) 
- (added) llvm/test/ThinLTO/X86/rtti-clean.ll (+34) 
- (added) llvm/test/ThinLTO/X86/rtti-dont-clean.ll (+46) 


``````````diff
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp 
b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 7c463f51f63dc5c..090eb4c16ce0b47 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -1592,6 +1592,7 @@ llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction 
&CGF,
       cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getDecl());
   llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy,
                                         ClassDecl);
+  CGF.EmitTypeMetadataCodeForVCall(ClassDecl, Value, SourceLocation());
 
   if (CGM.getItaniumVTableContext().isRelativeLayout()) {
     // Load the type info.
diff --git a/clang/test/CodeGenCXX/typeid-type-test.cpp 
b/clang/test/CodeGenCXX/typeid-type-test.cpp
new file mode 100644
index 000000000000000..9408d87495c608b
--- /dev/null
+++ b/clang/test/CodeGenCXX/typeid-type-test.cpp
@@ -0,0 +1,32 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 5
+// RUN: %clang_cc1 -I%S -triple x86_64-unknown-linux -flto 
-fwhole-program-vtables -fvisibility=hidden -emit-llvm -o - %s | FileCheck %s
+
+#include <typeinfo>
+
+namespace Test1 {
+struct A { virtual void f(); };
+
+// CHECK-LABEL: define hidden noundef nonnull align 8 dereferenceable(16) ptr 
@_ZN5Test19gettypeidEPNS_1AE(
+// CHECK-SAME: ptr noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    store ptr [[A]], ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+// CHECK-NEXT:    br i1 [[TMP1]], label %[[TYPEID_BAD_TYPEID:.*]], label 
%[[TYPEID_END:.*]]
+// CHECK:       [[TYPEID_BAD_TYPEID]]:
+// CHECK-NEXT:    call void @__cxa_bad_typeid() #[[ATTR3:[0-9]+]]
+// CHECK-NEXT:    unreachable
+// CHECK:       [[TYPEID_END]]:
+// CHECK-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK-NEXT:    [[TMP2:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], 
metadata !"_ZTSN5Test11AE")
+// CHECK-NEXT:    call void @llvm.assume(i1 [[TMP2]])
+// CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], 
i64 -1
+// CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8
+// CHECK-NEXT:    ret ptr [[TMP4]]
+//
+const std::type_info &gettypeid(A *a) {
+  return typeid(*a);
+}
+
+}
diff --git a/llvm/include/llvm/Analysis/TypeMetadataUtils.h 
b/llvm/include/llvm/Analysis/TypeMetadataUtils.h
index bdb477b54b532d0..87da08dba34c745 100644
--- a/llvm/include/llvm/Analysis/TypeMetadataUtils.h
+++ b/llvm/include/llvm/Analysis/TypeMetadataUtils.h
@@ -51,6 +51,8 @@ void findDevirtualizableCallsForTypeTest(
     SmallVectorImpl<CallInst *> &Assumes, const CallInst *CI,
     DominatorTree &DT);
 
+bool hasTypeIdLoadForTypeTest(const CallInst *CI);
+
 /// Given a call to the intrinsic \@llvm.type.checked.load, find all
 /// devirtualizable call sites based on the call and return them in 
DevirtCalls.
 void findDevirtualizableCallsForTypeCheckedLoad(
diff --git a/llvm/include/llvm/AsmParser/LLParser.h 
b/llvm/include/llvm/AsmParser/LLParser.h
index c01de4a289a69a0..b5dbfdd24657d6c 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -427,6 +427,7 @@ namespace llvm {
     bool parseTypeIdEntry(unsigned ID);
     bool parseTypeIdSummary(TypeIdSummary &TIS);
     bool parseTypeIdCompatibleVtableEntry(unsigned ID);
+    bool parseTypeIdMayBeAccessed(unsigned ID);
     bool parseTypeTestResolution(TypeTestResolution &TTRes);
     bool parseOptionalWpdResolutions(
         std::map<uint64_t, WholeProgramDevirtResolution> &WPDResMap);
diff --git a/llvm/include/llvm/AsmParser/LLToken.h 
b/llvm/include/llvm/AsmParser/LLToken.h
index 7b47bc88ddb25ff..c2bdab430b68947 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -422,6 +422,7 @@ enum Kind {
   kw_args,
   kw_typeid,
   kw_typeidCompatibleVTable,
+  kw_typeidMayBeAccessed,
   kw_summary,
   kw_typeTestRes,
   kw_kind,
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h 
b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 9eb38c3e4482910..41cb7a5922088c4 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -335,6 +335,7 @@ enum GlobalValueSummarySymtabCodes {
   // CallStackRadixTreeBuilder class in ProfileData/MemProf.h for format.
   // [n x entry]
   FS_CONTEXT_RADIX_TREE_ARRAY = 32,
+  FS_RTTI = 33,
 };
 
 enum MetadataCodes {
diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h 
b/llvm/include/llvm/IR/ModuleSummaryIndex.h
index 3c586a1dd21d823..717bb37685f529a 100644
--- a/llvm/include/llvm/IR/ModuleSummaryIndex.h
+++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h
@@ -643,6 +643,19 @@ class GlobalValueSummary {
   /// Return the list of values referenced by this global value definition.
   ArrayRef<ValueInfo> refs() const { return RefEdgeList; }
 
+  /// Erase all reference whose name is equal to Name.
+  bool eraseRef(StringRef Name) {
+    bool Erased = false;
+    erase_if(RefEdgeList, [&](ValueInfo VI) {
+      if (VI.name() == Name) {
+        Erased = true;
+        return true;
+      }
+      return false;
+    });
+    return Erased;
+  }
+
   /// If this is an alias summary, returns the summary of the aliased object (a
   /// global variable or function), otherwise returns itself.
   GlobalValueSummary *getBaseObject();
@@ -1365,6 +1378,9 @@ class ModuleSummaryIndex {
   std::map<StringRef, TypeIdCompatibleVtableInfo, std::less<>>
       TypeIdCompatibleVtableMap;
 
+  /// Type identifiers that may be accessed at run time.
+  SmallVector<StringRef, 0> TypeIdMayBeAccessed;
+
   /// Mapping from original ID to GUID. If original ID can map to multiple
   /// GUIDs, it will be mapped to 0.
   DenseMap<GlobalValue::GUID, GlobalValue::GUID> OidGuidMap;
@@ -1875,6 +1891,12 @@ class ModuleSummaryIndex {
     return I->second;
   }
 
+  void addTypeIdAccessed(StringRef TypeId) {
+    TypeIdMayBeAccessed.push_back(TypeId);
+  }
+
+  const auto &getTypeIdAccessed() const { return TypeIdMayBeAccessed; }
+
   /// Collect for the given module the list of functions it defines
   /// (GUID -> Summary).
   void collectDefinedFunctionsForModule(StringRef ModulePath,
diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h
index 242a05f7d32c025..085e6eaddc4904e 100644
--- a/llvm/include/llvm/LTO/LTO.h
+++ b/llvm/include/llvm/LTO/LTO.h
@@ -386,6 +386,8 @@ class LTO {
 private:
   Config Conf;
 
+  std::string TargetTriple;
+
   struct RegularLTOState {
     RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
                     const Config &Conf);
@@ -520,11 +522,17 @@ class LTO {
                    const SymbolResolution *&ResI, const SymbolResolution 
*ResE);
 
   Error runRegularLTO(AddStreamFn AddStream);
-  Error runThinLTO(AddStreamFn AddStream, FileCache Cache,
-                   const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols);
+  Error
+  runThinLTO(AddStreamFn AddStream, FileCache Cache,
+             const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
+             function_ref<PrevailingType(GlobalValue::GUID)> isPrevailing);
 
   Error checkPartiallySplit();
 
+  std::string & getTargetTriple() { return TargetTriple; }
+
+  void setTargetTriple(std::string TT) { TargetTriple = std::move(TT); }
+
   mutable bool CalledGetMaxTasks = false;
 
   // LTO mode when using Unified LTO.
diff --git a/llvm/include/llvm/Support/LibCXXABI.h 
b/llvm/include/llvm/Support/LibCXXABI.h
new file mode 100644
index 000000000000000..37f4b43f9584563
--- /dev/null
+++ b/llvm/include/llvm/Support/LibCXXABI.h
@@ -0,0 +1,49 @@
+#ifndef LLVM_SUPPORT_LIBCXXABI_H
+#define LLVM_SUPPORT_LIBCXXABI_H
+
+#include "llvm/IR/DataLayout.h"
+#include "llvm/TargetParser/Triple.h"
+
+namespace llvm {
+
+class CXXABI {
+
+  virtual const char * getVTablePrefix() = 0;
+  virtual const char * getTypeNamePrefix() = 0;
+  virtual const char * getTypeInfoPrefix() = 0;
+
+public:
+  static std::unique_ptr<CXXABI> Create(Triple &TT);
+  virtual ~CXXABI() {}
+  virtual int64_t
+  getOffsetFromTypeInfoSlotToAddressPoint(const DataLayout &DT) = 0;
+
+  bool isVTable(StringRef Name) { return Name.starts_with(getVTablePrefix()); }
+  bool isTypeName(StringRef Name) {
+    return Name.starts_with(getTypeNamePrefix());
+  }
+  bool isTypeInfo(StringRef Name) {
+    return Name.starts_with(getTypeInfoPrefix());
+  }
+
+  std::string getTypeNameFromTypeInfo(StringRef TypeInfo);
+  std::string getTypeInfoFromVTable(StringRef VTable);
+};
+
+class Itanium final : public CXXABI {
+
+  const char * getVTablePrefix() override { return "_ZTV"; }
+  const char * getTypeNamePrefix() override { return "_ZTS"; }
+  const char * getTypeInfoPrefix() override { return "_ZTI"; }
+
+public:
+  virtual ~Itanium() {}
+
+  int64_t
+  getOffsetFromTypeInfoSlotToAddressPoint(const DataLayout &DL) override {
+    return -2 * static_cast<int64_t>(DL.getPointerSize());
+  }
+};
+
+} // namespace llvm
+#endif
diff --git a/llvm/include/llvm/Transforms/IPO/DeadRTTIElimination.h 
b/llvm/include/llvm/Transforms/IPO/DeadRTTIElimination.h
new file mode 100644
index 000000000000000..906abf3d1a9ed27
--- /dev/null
+++ b/llvm/include/llvm/Transforms/IPO/DeadRTTIElimination.h
@@ -0,0 +1,21 @@
+#ifndef LLVM_TRANSFORMS_IPO_DEADRTTIELIMINATION_H
+#define LLVM_TRANSFORMS_IPO_DEADRTTIELIMINATION_H
+
+#include "llvm/IR/ModuleSummaryIndex.h"
+#include "llvm/Support/LibCXXABI.h"
+#include "llvm/TargetParser/Triple.h"
+
+namespace llvm {
+class DeadRTTIElimIndex {
+  ModuleSummaryIndex &ExportSummary;
+  std::unique_ptr<CXXABI> ABI;
+
+public:
+  DeadRTTIElimIndex(ModuleSummaryIndex &ExportSummary, Triple &TT)
+      : ExportSummary(ExportSummary), ABI(CXXABI::Create(TT)) {}
+
+  void run();
+};
+} // namespace llvm
+
+#endif // LLVM_TRANSFORMS_SCALAR_DEADRTTIELIMINATION_H
diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp 
b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
index 611d4bfbc69e8fe..ec0aa81d05f8a04 100644
--- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
+++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
@@ -52,6 +52,7 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/LibCXXABI.h"
 #include <cassert>
 #include <cstdint>
 #include <vector>
@@ -202,7 +203,7 @@ static void addVCallToSet(
 /// If this intrinsic call requires that we add information to the function
 /// summary, do so via the non-constant reference arguments.
 static void addIntrinsicToSummary(
-    const CallInst *CI,
+    ModuleSummaryIndex &Index, const CallInst *CI,
     SetVector<GlobalValue::GUID, std::vector<GlobalValue::GUID>> &TypeTests,
     SetVector<FunctionSummary::VFuncId, std::vector<FunctionSummary::VFuncId>>
         &TypeTestAssumeVCalls,
@@ -241,6 +242,10 @@ static void addIntrinsicToSummary(
       addVCallToSet(Call, Guid, TypeTestAssumeVCalls,
                     TypeTestAssumeConstVCalls);
 
+    if (Triple(CI->getModule()->getTargetTriple()).getOS() == Triple::Linux &&
+        hasTypeIdLoadForTypeTest(CI))
+      Index.addTypeIdAccessed(TypeId->getString());
+
     break;
   }
 
@@ -431,7 +436,7 @@ static void computeFunctionSummary(
       if (CalledFunction) {
         if (CI && CalledFunction->isIntrinsic()) {
           addIntrinsicToSummary(
-              CI, TypeTests, TypeTestAssumeVCalls, TypeCheckedLoadVCalls,
+              Index, CI, TypeTests, TypeTestAssumeVCalls, 
TypeCheckedLoadVCalls,
               TypeTestAssumeConstVCalls, TypeCheckedLoadConstVCalls, DT);
           continue;
         }
@@ -911,6 +916,61 @@ static void setLiveRoot(ModuleSummaryIndex &Index, 
StringRef Name) {
       Summary->setLive(true);
 }
 
+static bool hasNonVTableUsers(const User *U, CXXABI *ABI) {
+  LLVM_DEBUG(dbgs() << "Check if " << *U << "has vtable users\n");
+  if (isa<Instruction>(U)) {
+    // If the type info is used in dynamic_cast or exception handling,
+    // its user must be the instruction.
+    return true;
+  }
+
+  // The virtual table type is either a struct of arrays. For example:
+  // @vtable = constant { [3 x ptr] } { [3 x ptr] [ ptr null, ptr @rtti, ptr 
@vf] }
+  //
+  // In this case, the user of @rtti is an anonymous ConstantArray.
+  // Therefore, if the user of the type information is anonymous,
+  // we need to perform a depth-first search (DFS) to locate its named users.
+  //
+  // And we also need to iterate its users if the current user is the type
+  // info global variable itself.
+  StringRef Name = U->getName();
+  if (Name.empty() || ABI->isTypeInfo(Name)) {
+    for (const User *It : U->users())
+      if (hasNonVTableUsers(It, ABI))
+        return true;
+    return false;
+  }
+
+  if (!ABI->isVTable(Name))
+    return true;
+
+  return false;
+}
+
+static void analyzeRTTIVars(ModuleSummaryIndex &Index, const Module &M) {
+  Triple TT(M.getTargetTriple());
+
+  std::unique_ptr<CXXABI> ABI = CXXABI::Create(TT);
+  if (!ABI)
+    return;
+
+  for (const GlobalVariable &GV : M.globals()) {
+    if (!ABI->isTypeInfo(GV.getName()))
+      continue;
+
+    if (hasNonVTableUsers(&GV, ABI.get())) {
+      std::string TypeName =
+          ABI->getTypeNameFromTypeInfo(GV.getName());
+      const GlobalVariable *TypeNameGV = M.getNamedGlobal(TypeName);
+      if (TypeNameGV)
+        Index.addTypeIdAccessed(TypeNameGV->getName());
+      else
+        Index.addTypeIdAccessed(Index.saveString(TypeName));
+      break;
+    }
+  }
+}
+
 ModuleSummaryIndex llvm::buildModuleSummaryIndex(
     const Module &M,
     std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback,
@@ -1019,6 +1079,8 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
           mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("ThinLTO")))
     IsThinLTO = MD->getZExtValue();
 
+  analyzeRTTIVars(Index, M);
+
   // Compute summaries for all functions defined in module, and save in the
   // index.
   for (const auto &F : M) {
diff --git a/llvm/lib/Analysis/TypeMetadataUtils.cpp 
b/llvm/lib/Analysis/TypeMetadataUtils.cpp
index 9ec0785eb5034d6..9271f9c3d5b0baa 100644
--- a/llvm/lib/Analysis/TypeMetadataUtils.cpp
+++ b/llvm/lib/Analysis/TypeMetadataUtils.cpp
@@ -17,6 +17,7 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Support/LibCXXABI.h"
 
 using namespace llvm;
 
@@ -50,6 +51,42 @@ findCallsAtConstantOffset(SmallVectorImpl<DevirtCallSite> 
&DevirtCalls,
   }
 }
 
+static bool hasTypeIdLoadAtConstantOffset(const Module *M, Value *VPtr,
+                                          int64_t Offset, const CallInst *CI,
+                                          CXXABI *ABI) {
+  Triple TT(M->getTargetTriple());
+  bool HasTypeIdLoad = false;
+  for (const Use &U : VPtr->uses()) {
+    Value *User = U.getUser();
+    if (isa<BitCastInst>(User)) {
+      HasTypeIdLoad |= hasTypeIdLoadAtConstantOffset(M, User, Offset, CI, ABI);
+    } else if (isa<LoadInst>(User)) {
+      if (Offset ==
+          ABI->getOffsetFromTypeInfoSlotToAddressPoint(M->getDataLayout()))
+        return true;
+    } else if (auto GEP = dyn_cast<GetElementPtrInst>(User)) {
+      // Take into account the GEP offset.
+      if (VPtr == GEP->getPointerOperand() && GEP->hasAllConstantIndices()) {
+        SmallVector<Value *, 8> Indices(drop_begin(GEP->operands()));
+        int64_t GEPOffset = M->getDataLayout().getIndexedOffsetInType(
+            GEP->getSourceElementType(), Indices);
+        HasTypeIdLoad |=
+            hasTypeIdLoadAtConstantOffset(M, User, Offset + GEPOffset, CI, 
ABI);
+      }
+    } else if (auto *Call = dyn_cast<CallInst>(User)) {
+      if (Call->getIntrinsicID() == llvm::Intrinsic::load_relative) {
+        if (auto *LoadOffset = dyn_cast<ConstantInt>(Call->getOperand(1))) {
+          HasTypeIdLoad |=
+              hasTypeIdLoadAtConstantOffset(M, User, Offset, CI, ABI);
+        }
+      }
+    } else {
+      HasTypeIdLoad = true;
+    }
+  }
+  return HasTypeIdLoad;
+}
+
 // Search for virtual calls that load from VPtr and add them to DevirtCalls.
 static void findLoadCallsAtConstantOffset(
     const Module *M, SmallVectorImpl<DevirtCallSite> &DevirtCalls, Value *VPtr,
@@ -103,6 +140,30 @@ void llvm::findDevirtualizableCallsForTypeTest(
         M, DevirtCalls, CI->getArgOperand(0)->stripPointerCasts(), 0, CI, DT);
 }
 
+bool llvm::hasTypeIdLoadForTypeTest(const CallInst *CI) {
+  assert(CI->getCalledFunction()->getIntrinsicID() == Intrinsic::type_test ||
+         CI->getCalledFunction()->getIntrinsicID() ==
+             Intrinsic::public_type_test);
+  Triple TT(CI->getModule()->getTargetTriple());
+  std::unique_ptr<CXXABI> ABI = CXXABI::Create(TT);
+  if (!ABI)
+    return false;
+  SmallVector<CallInst *, 1> Assumes;
+
+  const Module *M = CI->getParent()->getParent()->getParent();
+
+  // Find llvm.assume intrinsics for this llvm.type.test call.
+  for (const Use &CIU : CI->uses())
+    if (auto *Assume = dyn_cast<AssumeInst>(CIU.getUser()))
+      Assumes.push_back(Assume);
+
+  if (!Assumes.empty())
+    return hasTypeIdLoadAtConstantOffset(
+        M, CI->getArgOperand(0)->stripPointerCasts(), 0, CI, ABI.get());
+
+  return false;
+}
+
 void llvm::findDevirtualizableCallsForTypeCheckedLoad(
     SmallVectorImpl<DevirtCallSite> &DevirtCalls,
     SmallVectorImpl<Instruction *> &LoadedPtrs,
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 5ea507c009bdc61..b6d09f0992c7994 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -826,6 +826,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(args);
   KEYWORD(typeid);
   KEYWORD(typeidCompatibleVTable);
+  KEYWORD(typeidMayBeAccessed);
   KEYWORD(summary);
   KEYWORD(typeTestRes);
   KEYWORD(kind);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index be6166f0c41694f..e33ef2e13755c54 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -1118,6 +1118,9 @@ bool LLParser::parseSummaryEntry() {
   case lltok::kw_typeidCompatibleVTable:
     result = parseTypeIdCompatibleVtableEntry(SummaryID);
     break;
+  case lltok::kw_typeidMayBeAccessed:
+    result = parseTypeIdMayBeAccessed(SummaryID);
+    break;
   case lltok::kw_flags:
     result = parseSummaryIndexFlags();
     break;
@@ -8918,6 +8921,33 @@ bool LLParser::parseTypeIdSummary(TypeIdSummary &TIS) {
 static ValueInfo EmptyVI =
     ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8);
 
+bool LLParser::parseTypeIdMayBeAccessed(unsigned ID) {
+  assert(Lex.getKind() == lltok::kw_typeidMayBeAccessed);
+  Lex.Lex();
+
+  std::string Name;
+  if (parseToken(lltok::colon, "expected ':' here") ||
+      parseToken(lltok::lparen, "expected '(' here") ||
+      parseToken(lltok::kw_name, "expected 'name' here") ||
+      parseToken(lltok::colon, "expected ':' here") ||
+      parseStringConstant(Name))
+    return true;
+
+  Index->addTypeIdAccessed(Index->saveString(Name));
+
+  while (Lex.getKind() != lltok::rparen) {
+    if (parseToken(lltok::comma, "expected ',' here") ||
+        parseStringConstant(Name))
+      return true;
+    Index->addTypeIdAccessed(Index->saveString(Name));
+  }
+
+  if (parseToken(lltok::rparen, "expected ')' here"))
+    return true;
+
+  return false;
+}
+
 /// TypeIdCompatibleVtableEntry
 ///   ::= 'typeidCompatibleVTable' ':' '(' 'name' ':' STRINGCONSTANT ','
 ///   TypeIdCompatibleVtableInfo
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp 
b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 56f5ff4b20e5dbf..434b3ef8a586702 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -1015,6 +1015,7 @@ class ModuleSummaryIndexBitcodeReader : public 
BitcodeReaderBase {
   void parseTypeIdCompatibleVtableSummaryRecord(ArrayRef<uint64_t> Record);
   void parseTypeIdCompatibleVtableInfo(ArrayRef<uint64_t> Record, size_t &Slot,
                                        TypeIdCompatibleVtableInfo &TypeId);
+  void parseTypeIdAccessed(ArrayRef<uint64_t> Record);
   std::vector<FunctionSummary::ParamAccess>
   parseParamAccesses(ArrayRef<uint64_t> Record);
   SmallVector<unsigned> parseAllocInfoContext(ArrayRef<uint64_t> Record,
@@ -7575,6 +7576,14 @@ void 
ModuleSummaryIndexBitcodeReader::parseTypeIdCompatibleVtableInfo...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/126336
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to