[clang] [llvm] [ThinLTO] Support dead RTTI data elimination under -fno-split-lto-unit (PR #126336)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 7 19:24:49 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
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
More information about the cfe-commits
mailing list