From 51dda4dab6f7e62b41fc9136a5a61dccb63461f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= Date: Thu, 9 Oct 2025 14:57:56 +0200 Subject: [PATCH 1/8] Pre-Commit test: [LLVM] Maintain element type of @llvm.compiler.used/@llvm.used if it already exists This new test fails with: /home/juamarti/llvm/_llvm/llvm/lib/IR/Constants.cpp:1327: static Constant *llvm::ConstantArray::getImpl(ArrayType *, ArrayRef): Assertion `C->getType() == Ty->getElementType() && "Wrong type in array element initializer"' failed. --- .../Transforms/Utils/ModuleUtilsTest.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/llvm/unittests/Transforms/Utils/ModuleUtilsTest.cpp b/llvm/unittests/Transforms/Utils/ModuleUtilsTest.cpp index d4094c5307060..0cc408af43bc5 100644 --- a/llvm/unittests/Transforms/Utils/ModuleUtilsTest.cpp +++ b/llvm/unittests/Transforms/Utils/ModuleUtilsTest.cpp @@ -69,6 +69,23 @@ TEST(ModuleUtils, AppendToUsedList2) { EXPECT_EQ(1, getListSize(*M, "llvm.used")); } +TEST(ModuleUtils, AppendToUsedList3) { + LLVMContext C; + + std::unique_ptr M = parseIR(C, R"( + @x = addrspace(1) global [2 x i32] zeroinitializer, align 4 + @y = addrspace(2) global [2 x i32] zeroinitializer, align 4 + @llvm.compiler.used = appending global [1 x ptr addrspace (3)] [ptr addrspace(3) addrspacecast (ptr addrspace (1) @x to ptr addrspace(3))] + )"); + GlobalVariable *X = M->getNamedGlobal("x"); + GlobalVariable *Y = M->getNamedGlobal("y"); + EXPECT_EQ(1, getListSize(*M, "llvm.compiler.used")); + appendToCompilerUsed(*M, X); + EXPECT_EQ(1, getListSize(*M, "llvm.compiler.used")); + appendToCompilerUsed(*M, Y); + EXPECT_EQ(2, getListSize(*M, "llvm.compiler.used")); +} + using AppendFnType = decltype(&appendToGlobalCtors); using TransformFnType = decltype(&transformGlobalCtors); using ParamType = std::tuple; From 5fc418cdd7ef4fb37b873cab36a9aa77ad3b7552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= Date: Thu, 9 Oct 2025 14:34:32 +0200 Subject: [PATCH 2/8] [LLVM] Maintain element type of @llvm.compiler.used/@llvm.used if it already exists At the moment, the pointer type stored in the llvm.compiler.used/llvm.used is not well fixed. The frontend uses a pointer to the default address space (which may not be 0; for example, it is 4 for SPIRV). This patch makes `appendToUsed/appendToCompilerUsed` match the behaviour in BitcodeWriter.cpp: if the variable already exists, preserve its element type, otherwise use `ptr addrspace (0)`. This fixes the following error in the newly added test: UtilsTests: /home/juamarti/llvm/_llvm/llvm/lib/IR/Constants.cpp:1327: static Constant *llvm::ConstantArray::getImpl(ArrayType *, ArrayRef): Assertion `C->getType() == Ty->getElementType() && "Wrong type in array element initializer"' failed. --- llvm/lib/Transforms/Utils/ModuleUtils.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp index 596849ecab742..d1acb0ff1ad6b 100644 --- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp +++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp @@ -138,10 +138,11 @@ static void appendToUsedList(Module &M, StringRef Name, ArrayRef SmallSetVector Init; collectUsedGlobals(GV, Init); + Type *ArrayEltTy = GV ? GV->getValueType()->getArrayElementType() + : PointerType::getUnqual(M.getContext()); if (GV) GV->eraseFromParent(); - Type *ArrayEltTy = llvm::PointerType::getUnqual(M.getContext()); for (auto *V : Values) Init.insert(ConstantExpr::getPointerBitCastOrAddrSpaceCast(V, ArrayEltTy)); From 94711ebce860a86c3b1c60736732c81360924dd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= Date: Thu, 9 Oct 2025 14:34:24 +0200 Subject: [PATCH 3/8] [NFC][BitcodeWriter] Use appendToCompilerUsed instead of custom implementation --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 70 ++++++++++------------- llvm/lib/Bitcode/Writer/CMakeLists.txt | 1 + 2 files changed, 31 insertions(+), 40 deletions(-) diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 8ff3aa9817571..af66e13641126 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -75,6 +75,7 @@ #include "llvm/Support/SHA1.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" #include #include #include @@ -5864,25 +5865,25 @@ static const char *getSectionNameForCommandline(const Triple &T) { void llvm::embedBitcodeInModule(llvm::Module &M, llvm::MemoryBufferRef Buf, bool EmbedBitcode, bool EmbedCmdline, const std::vector &CmdArgs) { - // Save llvm.compiler.used and remove it. - SmallVector UsedArray; - SmallVector UsedGlobals; - GlobalVariable *Used = collectUsedGlobalVariables(M, UsedGlobals, true); - Type *UsedElementType = Used ? Used->getValueType()->getArrayElementType() - : PointerType::getUnqual(M.getContext()); - for (auto *GV : UsedGlobals) { - if (GV->getName() != "llvm.embedded.module" && - GV->getName() != "llvm.cmdline") - UsedArray.push_back( - ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, UsedElementType)); - } - if (Used) - Used->eraseFromParent(); // Embed the bitcode for the llvm module. std::string Data; ArrayRef ModuleData; Triple T(M.getTargetTriple()); + SmallVector NewGlobals; + + auto IsCmdOrBitcode = [&](Constant *C) { + GlobalVariable *GV = dyn_cast(C); + StringRef Name = GV ? GV->getName() : ""; + if (EmbedBitcode && Name == "llvm.embedded.module") + return true; + if (EmbedCmdline && Name == "llvm.cmdline") + return true; + return false; + }; + + if (EmbedBitcode || EmbedCmdline) + removeFromUsedLists(M, IsCmdOrBitcode); if (EmbedBitcode) { if (Buf.getBufferSize() == 0 || @@ -5901,23 +5902,22 @@ void llvm::embedBitcodeInModule(llvm::Module &M, llvm::MemoryBufferRef Buf, } llvm::Constant *ModuleConstant = llvm::ConstantDataArray::get(M.getContext(), ModuleData); - llvm::GlobalVariable *GV = new llvm::GlobalVariable( + llvm::GlobalVariable *EmbeddedModule = new llvm::GlobalVariable( M, ModuleConstant->getType(), true, llvm::GlobalValue::PrivateLinkage, ModuleConstant); - GV->setSection(getSectionNameForBitcode(T)); + EmbeddedModule->setSection(getSectionNameForBitcode(T)); // Set alignment to 1 to prevent padding between two contributions from input // sections after linking. - GV->setAlignment(Align(1)); - UsedArray.push_back( - ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, UsedElementType)); + EmbeddedModule->setAlignment(Align(1)); + NewGlobals.push_back(EmbeddedModule); if (llvm::GlobalVariable *Old = M.getGlobalVariable("llvm.embedded.module", true)) { assert(Old->hasZeroLiveUses() && "llvm.embedded.module can only be used once in llvm.compiler.used"); - GV->takeName(Old); + EmbeddedModule->takeName(Old); Old->eraseFromParent(); } else { - GV->setName("llvm.embedded.module"); + EmbeddedModule->setName("llvm.embedded.module"); } // Skip if only bitcode needs to be embedded. @@ -5927,30 +5927,20 @@ void llvm::embedBitcodeInModule(llvm::Module &M, llvm::MemoryBufferRef Buf, CmdArgs.size()); llvm::Constant *CmdConstant = llvm::ConstantDataArray::get(M.getContext(), CmdData); - GV = new llvm::GlobalVariable(M, CmdConstant->getType(), true, - llvm::GlobalValue::PrivateLinkage, - CmdConstant); - GV->setSection(getSectionNameForCommandline(T)); - GV->setAlignment(Align(1)); - UsedArray.push_back( - ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV, UsedElementType)); + GlobalVariable *CmdLine = new llvm::GlobalVariable( + M, CmdConstant->getType(), true, llvm::GlobalValue::PrivateLinkage, + CmdConstant); + CmdLine->setSection(getSectionNameForCommandline(T)); + CmdLine->setAlignment(Align(1)); if (llvm::GlobalVariable *Old = M.getGlobalVariable("llvm.cmdline", true)) { assert(Old->hasZeroLiveUses() && "llvm.cmdline can only be used once in llvm.compiler.used"); - GV->takeName(Old); + CmdLine->takeName(Old); Old->eraseFromParent(); } else { - GV->setName("llvm.cmdline"); + CmdLine->setName("llvm.cmdline"); } + NewGlobals.push_back(CmdLine); + appendToCompilerUsed(M, NewGlobals); } - - if (UsedArray.empty()) - return; - - // Recreate llvm.compiler.used. - ArrayType *ATy = ArrayType::get(UsedElementType, UsedArray.size()); - auto *NewUsed = new GlobalVariable( - M, ATy, false, llvm::GlobalValue::AppendingLinkage, - llvm::ConstantArray::get(ATy, UsedArray), "llvm.compiler.used"); - NewUsed->setSection("llvm.metadata"); } diff --git a/llvm/lib/Bitcode/Writer/CMakeLists.txt b/llvm/lib/Bitcode/Writer/CMakeLists.txt index 2c508ca9fae95..5bbb872a90341 100644 --- a/llvm/lib/Bitcode/Writer/CMakeLists.txt +++ b/llvm/lib/Bitcode/Writer/CMakeLists.txt @@ -15,4 +15,5 @@ add_llvm_component_library(LLVMBitWriter ProfileData Support TargetParser + TransformUtils ) From 69ede1be9eff2d31a32b67feda26919d8f64e4bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= Date: Fri, 10 Oct 2025 09:52:55 +0200 Subject: [PATCH 4/8] [Review] Remove lambda from embedBitcodeInModule --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index af66e13641126..d42cce76d4487 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -5862,6 +5862,12 @@ static const char *getSectionNameForCommandline(const Triple &T) { llvm_unreachable("Unimplemented ObjectFormatType"); } +static auto globalInUsedHasName(StringRef Name) { + return [Name](Constant* C) { + return C->getName() == Name; + }; +} + void llvm::embedBitcodeInModule(llvm::Module &M, llvm::MemoryBufferRef Buf, bool EmbedBitcode, bool EmbedCmdline, const std::vector &CmdArgs) { @@ -5872,19 +5878,6 @@ void llvm::embedBitcodeInModule(llvm::Module &M, llvm::MemoryBufferRef Buf, Triple T(M.getTargetTriple()); SmallVector NewGlobals; - auto IsCmdOrBitcode = [&](Constant *C) { - GlobalVariable *GV = dyn_cast(C); - StringRef Name = GV ? GV->getName() : ""; - if (EmbedBitcode && Name == "llvm.embedded.module") - return true; - if (EmbedCmdline && Name == "llvm.cmdline") - return true; - return false; - }; - - if (EmbedBitcode || EmbedCmdline) - removeFromUsedLists(M, IsCmdOrBitcode); - if (EmbedBitcode) { if (Buf.getBufferSize() == 0 || !isBitcode((const unsigned char *)Buf.getBufferStart(), @@ -5912,6 +5905,7 @@ void llvm::embedBitcodeInModule(llvm::Module &M, llvm::MemoryBufferRef Buf, NewGlobals.push_back(EmbeddedModule); if (llvm::GlobalVariable *Old = M.getGlobalVariable("llvm.embedded.module", true)) { + removeFromUsedLists(M, globalInUsedHasName("llvm.embedded.module")); assert(Old->hasZeroLiveUses() && "llvm.embedded.module can only be used once in llvm.compiler.used"); EmbeddedModule->takeName(Old); @@ -5933,6 +5927,7 @@ void llvm::embedBitcodeInModule(llvm::Module &M, llvm::MemoryBufferRef Buf, CmdLine->setSection(getSectionNameForCommandline(T)); CmdLine->setAlignment(Align(1)); if (llvm::GlobalVariable *Old = M.getGlobalVariable("llvm.cmdline", true)) { + removeFromUsedLists(M, globalInUsedHasName("llvm.cmdline")); assert(Old->hasZeroLiveUses() && "llvm.cmdline can only be used once in llvm.compiler.used"); CmdLine->takeName(Old); From a5e4c7311144b4d760415633be92f0b43adb8648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= Date: Fri, 10 Oct 2025 09:54:55 +0200 Subject: [PATCH 5/8] [Review] 'addrspace (n)' -> 'addrspace(n)' --- llvm/unittests/Transforms/Utils/ModuleUtilsTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/unittests/Transforms/Utils/ModuleUtilsTest.cpp b/llvm/unittests/Transforms/Utils/ModuleUtilsTest.cpp index 0cc408af43bc5..cbdb4dcbc9a6f 100644 --- a/llvm/unittests/Transforms/Utils/ModuleUtilsTest.cpp +++ b/llvm/unittests/Transforms/Utils/ModuleUtilsTest.cpp @@ -75,7 +75,7 @@ TEST(ModuleUtils, AppendToUsedList3) { std::unique_ptr M = parseIR(C, R"( @x = addrspace(1) global [2 x i32] zeroinitializer, align 4 @y = addrspace(2) global [2 x i32] zeroinitializer, align 4 - @llvm.compiler.used = appending global [1 x ptr addrspace (3)] [ptr addrspace(3) addrspacecast (ptr addrspace (1) @x to ptr addrspace(3))] + @llvm.compiler.used = appending global [1 x ptr addrspace(3)] [ptr addrspace(3) addrspacecast (ptr addrspace(1) @x to ptr addrspace(3))] )"); GlobalVariable *X = M->getNamedGlobal("x"); GlobalVariable *Y = M->getNamedGlobal("y"); From a368f1cd7840a657c3b8944d4199f5fe173308ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= Date: Fri, 10 Oct 2025 10:40:58 +0200 Subject: [PATCH 6/8] [Review] Forgot again to run clang-format --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index d42cce76d4487..fc6bcaf598fc9 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -5863,9 +5863,7 @@ static const char *getSectionNameForCommandline(const Triple &T) { } static auto globalInUsedHasName(StringRef Name) { - return [Name](Constant* C) { - return C->getName() == Name; - }; + return [Name](Constant *C) { return C->getName() == Name; }; } void llvm::embedBitcodeInModule(llvm::Module &M, llvm::MemoryBufferRef Buf, From e686175ece054671ea9fcc124ab725cd05b7d7ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= Date: Thu, 16 Oct 2025 09:51:00 +0200 Subject: [PATCH 7/8] [Review] Move llvm.used/llvm.compiler.used helpers from ModuleUtils to GlobalValue; and remove dependency between BitcodeWriter & TransformUtils --- llvm/include/llvm/IR/GlobalValue.h | 12 +++ .../llvm/Transforms/Utils/ModuleUtils.h | 12 --- llvm/lib/Bitcode/Writer/CMakeLists.txt | 1 - llvm/lib/CodeGen/JMCInstrumenter.cpp | 1 - llvm/lib/IR/Globals.cpp | 78 +++++++++++++++++++ .../Target/AMDGPU/AMDGPUCtorDtorLowering.cpp | 1 - .../Target/NVPTX/NVPTXCtorDtorLowering.cpp | 1 - llvm/lib/Transforms/Utils/ModuleUtils.cpp | 77 ------------------ .../Utils/SampleProfileLoaderBaseUtil.cpp | 1 - 9 files changed, 90 insertions(+), 94 deletions(-) diff --git a/llvm/include/llvm/IR/GlobalValue.h b/llvm/include/llvm/IR/GlobalValue.h index 83e695cdd27d9..8f6726bd99335 100644 --- a/llvm/include/llvm/IR/GlobalValue.h +++ b/llvm/include/llvm/IR/GlobalValue.h @@ -684,6 +684,18 @@ class GlobalValue : public Constant { LLVM_ABI bool canBeOmittedFromSymbolTable() const; }; +/// Adds global values to the llvm.used list. +LLVM_ABI void appendToUsed(Module &M, ArrayRef Values); + +/// Adds global values to the llvm.compiler.used list. +LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef Values); + +/// Removes global values from the llvm.used and llvm.compiler.used arrays. \p +/// ShouldRemove should return true for any initializer field that should not be +/// included in the replacement global. +LLVM_ABI void removeFromUsedLists(Module &M, + function_ref ShouldRemove); + } // end namespace llvm #endif // LLVM_IR_GLOBALVALUE_H diff --git a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h index 4036c4e947c75..98bb4579f3a6c 100644 --- a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h +++ b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h @@ -96,18 +96,6 @@ getOrCreateSanitizerCtorAndInitFunctions( /// the list of public globals in the module. LLVM_ABI bool nameUnamedGlobals(Module &M); -/// Adds global values to the llvm.used list. -LLVM_ABI void appendToUsed(Module &M, ArrayRef Values); - -/// Adds global values to the llvm.compiler.used list. -LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef Values); - -/// Removes global values from the llvm.used and llvm.compiler.used arrays. \p -/// ShouldRemove should return true for any initializer field that should not be -/// included in the replacement global. -LLVM_ABI void removeFromUsedLists(Module &M, - function_ref ShouldRemove); - /// Filter out potentially dead comdat functions where other entries keep the /// entire comdat group alive. /// diff --git a/llvm/lib/Bitcode/Writer/CMakeLists.txt b/llvm/lib/Bitcode/Writer/CMakeLists.txt index 5bbb872a90341..2c508ca9fae95 100644 --- a/llvm/lib/Bitcode/Writer/CMakeLists.txt +++ b/llvm/lib/Bitcode/Writer/CMakeLists.txt @@ -15,5 +15,4 @@ add_llvm_component_library(LLVMBitWriter ProfileData Support TargetParser - TransformUtils ) diff --git a/llvm/lib/CodeGen/JMCInstrumenter.cpp b/llvm/lib/CodeGen/JMCInstrumenter.cpp index e2aaebedf5a4f..b1c05294ac4b5 100644 --- a/llvm/lib/CodeGen/JMCInstrumenter.cpp +++ b/llvm/lib/CodeGen/JMCInstrumenter.cpp @@ -36,7 +36,6 @@ #include "llvm/Pass.h" #include "llvm/Support/DJB.h" #include "llvm/Support/Path.h" -#include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp index c3a472b0cc66d..609c463d95d40 100644 --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "LLVMContextImpl.h" +#include "llvm/ADT/SetVector.h" #include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" @@ -671,3 +672,80 @@ void GlobalIFunc::applyAlongResolverPath( DenseSet Aliases; findBaseObject(getResolver(), Aliases, Op); } + +static void collectUsedGlobals(GlobalVariable *GV, + SmallSetVector &Init) { + if (!GV || !GV->hasInitializer()) + return; + + auto *CA = cast(GV->getInitializer()); + for (Use &Op : CA->operands()) + Init.insert(cast(Op)); +} + +static void appendToUsedList(Module &M, StringRef Name, + ArrayRef Values) { + GlobalVariable *GV = M.getGlobalVariable(Name); + + SmallSetVector Init; + collectUsedGlobals(GV, Init); + Type *ArrayEltTy = GV ? GV->getValueType()->getArrayElementType() + : PointerType::getUnqual(M.getContext()); + if (GV) + GV->eraseFromParent(); + + for (auto *V : Values) + Init.insert(ConstantExpr::getPointerBitCastOrAddrSpaceCast(V, ArrayEltTy)); + + if (Init.empty()) + return; + + ArrayType *ATy = ArrayType::get(ArrayEltTy, Init.size()); + GV = new GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage, + ConstantArray::get(ATy, Init.getArrayRef()), Name); + GV->setSection("llvm.metadata"); +} + +void llvm::appendToUsed(Module &M, ArrayRef Values) { + appendToUsedList(M, "llvm.used", Values); +} + +void llvm::appendToCompilerUsed(Module &M, ArrayRef Values) { + appendToUsedList(M, "llvm.compiler.used", Values); +} + +static void removeFromUsedList(Module &M, StringRef Name, + function_ref ShouldRemove) { + GlobalVariable *GV = M.getNamedGlobal(Name); + if (!GV) + return; + + SmallSetVector Init; + collectUsedGlobals(GV, Init); + + Type *ArrayEltTy = cast(GV->getValueType())->getElementType(); + + SmallVector NewInit; + for (Constant *MaybeRemoved : Init) { + if (!ShouldRemove(MaybeRemoved->stripPointerCasts())) + NewInit.push_back(MaybeRemoved); + } + + if (!NewInit.empty()) { + ArrayType *ATy = ArrayType::get(ArrayEltTy, NewInit.size()); + GlobalVariable *NewGV = + new GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage, + ConstantArray::get(ATy, NewInit), "", GV, + GV->getThreadLocalMode(), GV->getAddressSpace()); + NewGV->setSection(GV->getSection()); + NewGV->takeName(GV); + } + + GV->eraseFromParent(); +} + +void llvm::removeFromUsedLists(Module &M, + function_ref ShouldRemove) { + removeFromUsedList(M, "llvm.used", ShouldRemove); + removeFromUsedList(M, "llvm.compiler.used", ShouldRemove); +} diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCtorDtorLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCtorDtorLowering.cpp index a774ad53b5bed..bd1727571f41a 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCtorDtorLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUCtorDtorLowering.cpp @@ -19,7 +19,6 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Value.h" #include "llvm/Pass.h" -#include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; diff --git a/llvm/lib/Target/NVPTX/NVPTXCtorDtorLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXCtorDtorLowering.cpp index 4e069398d540f..18618ca19beee 100644 --- a/llvm/lib/Target/NVPTX/NVPTXCtorDtorLowering.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXCtorDtorLowering.cpp @@ -24,7 +24,6 @@ #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MD5.h" -#include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp index d1acb0ff1ad6b..81ddcf06c49d2 100644 --- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp +++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp @@ -123,83 +123,6 @@ void llvm::transformGlobalDtors(Module &M, const GlobalCtorTransformFn &Fn) { transformGlobalArray("llvm.global_dtors", M, Fn); } -static void collectUsedGlobals(GlobalVariable *GV, - SmallSetVector &Init) { - if (!GV || !GV->hasInitializer()) - return; - - auto *CA = cast(GV->getInitializer()); - for (Use &Op : CA->operands()) - Init.insert(cast(Op)); -} - -static void appendToUsedList(Module &M, StringRef Name, ArrayRef Values) { - GlobalVariable *GV = M.getGlobalVariable(Name); - - SmallSetVector Init; - collectUsedGlobals(GV, Init); - Type *ArrayEltTy = GV ? GV->getValueType()->getArrayElementType() - : PointerType::getUnqual(M.getContext()); - if (GV) - GV->eraseFromParent(); - - for (auto *V : Values) - Init.insert(ConstantExpr::getPointerBitCastOrAddrSpaceCast(V, ArrayEltTy)); - - if (Init.empty()) - return; - - ArrayType *ATy = ArrayType::get(ArrayEltTy, Init.size()); - GV = new llvm::GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage, - ConstantArray::get(ATy, Init.getArrayRef()), - Name); - GV->setSection("llvm.metadata"); -} - -void llvm::appendToUsed(Module &M, ArrayRef Values) { - appendToUsedList(M, "llvm.used", Values); -} - -void llvm::appendToCompilerUsed(Module &M, ArrayRef Values) { - appendToUsedList(M, "llvm.compiler.used", Values); -} - -static void removeFromUsedList(Module &M, StringRef Name, - function_ref ShouldRemove) { - GlobalVariable *GV = M.getNamedGlobal(Name); - if (!GV) - return; - - SmallSetVector Init; - collectUsedGlobals(GV, Init); - - Type *ArrayEltTy = cast(GV->getValueType())->getElementType(); - - SmallVector NewInit; - for (Constant *MaybeRemoved : Init) { - if (!ShouldRemove(MaybeRemoved->stripPointerCasts())) - NewInit.push_back(MaybeRemoved); - } - - if (!NewInit.empty()) { - ArrayType *ATy = ArrayType::get(ArrayEltTy, NewInit.size()); - GlobalVariable *NewGV = - new GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage, - ConstantArray::get(ATy, NewInit), "", GV, - GV->getThreadLocalMode(), GV->getAddressSpace()); - NewGV->setSection(GV->getSection()); - NewGV->takeName(GV); - } - - GV->eraseFromParent(); -} - -void llvm::removeFromUsedLists(Module &M, - function_ref ShouldRemove) { - removeFromUsedList(M, "llvm.used", ShouldRemove); - removeFromUsedList(M, "llvm.compiler.used", ShouldRemove); -} - void llvm::setKCFIType(Module &M, Function &F, StringRef MangledType) { if (!M.getModuleFlag("kcfi")) return; diff --git a/llvm/lib/Transforms/Utils/SampleProfileLoaderBaseUtil.cpp b/llvm/lib/Transforms/Utils/SampleProfileLoaderBaseUtil.cpp index f7ae6ad844948..324f6194a2d72 100644 --- a/llvm/lib/Transforms/Utils/SampleProfileLoaderBaseUtil.cpp +++ b/llvm/lib/Transforms/Utils/SampleProfileLoaderBaseUtil.cpp @@ -14,7 +14,6 @@ #include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Module.h" -#include "llvm/Transforms/Utils/ModuleUtils.h" namespace llvm { From e9a62539d180a6a1b1c3de19cba33856eca5fd66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= Date: Thu, 16 Oct 2025 11:08:26 +0200 Subject: [PATCH 8/8] [Review] forgot to move the unittests --- llvm/unittests/IR/CMakeLists.txt | 1 + llvm/unittests/IR/UsedGlobalTest.cpp | 82 +++++++++++++++++++ .../Transforms/Utils/ModuleUtilsTest.cpp | 53 ------------ 3 files changed, 83 insertions(+), 53 deletions(-) create mode 100644 llvm/unittests/IR/UsedGlobalTest.cpp diff --git a/llvm/unittests/IR/CMakeLists.txt b/llvm/unittests/IR/CMakeLists.txt index d62ce66ef9d34..1e7f0932dd989 100644 --- a/llvm/unittests/IR/CMakeLists.txt +++ b/llvm/unittests/IR/CMakeLists.txt @@ -49,6 +49,7 @@ add_llvm_unittest(IRTests TypesTest.cpp UseTest.cpp UserTest.cpp + UsedGlobalTest.cpp ValueHandleTest.cpp ValueMapTest.cpp ValueTest.cpp diff --git a/llvm/unittests/IR/UsedGlobalTest.cpp b/llvm/unittests/IR/UsedGlobalTest.cpp new file mode 100644 index 0000000000000..23cedc6f774f9 --- /dev/null +++ b/llvm/unittests/IR/UsedGlobalTest.cpp @@ -0,0 +1,82 @@ +//===- UsedGlobalTest.cpp - Unit tests for Module utility ----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include "llvm/AsmParser/Parser.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/SourceMgr.h" +#include "gtest/gtest.h" + +using namespace llvm; + +static std::unique_ptr parseIR(LLVMContext &C, StringRef IR) { + SMDiagnostic Err; + std::unique_ptr Mod = parseAssemblyString(IR, Err, C); + if (!Mod) + Err.print("UsedGlobalTest", errs()); + return Mod; +} + +static int getListSize(Module &M, StringRef Name) { + auto *List = M.getGlobalVariable(Name); + if (!List) + return 0; + auto *T = cast(List->getValueType()); + return T->getNumElements(); +} + +TEST(UsedGlobal, AppendToUsedList1) { + LLVMContext C; + + std::unique_ptr M = parseIR( + C, R"(@x = addrspace(4) global [2 x i32] zeroinitializer, align 4)"); + SmallVector Globals; + for (auto &G : M->globals()) { + Globals.push_back(&G); + } + EXPECT_EQ(0, getListSize(*M, "llvm.compiler.used")); + appendToCompilerUsed(*M, Globals); + EXPECT_EQ(1, getListSize(*M, "llvm.compiler.used")); + + EXPECT_EQ(0, getListSize(*M, "llvm.used")); + appendToUsed(*M, Globals); + EXPECT_EQ(1, getListSize(*M, "llvm.used")); +} + +TEST(UsedGlobal, AppendToUsedList2) { + LLVMContext C; + + std::unique_ptr M = + parseIR(C, R"(@x = global [2 x i32] zeroinitializer, align 4)"); + SmallVector Globals; + for (auto &G : M->globals()) { + Globals.push_back(&G); + } + EXPECT_EQ(0, getListSize(*M, "llvm.compiler.used")); + appendToCompilerUsed(*M, Globals); + EXPECT_EQ(1, getListSize(*M, "llvm.compiler.used")); + + EXPECT_EQ(0, getListSize(*M, "llvm.used")); + appendToUsed(*M, Globals); + EXPECT_EQ(1, getListSize(*M, "llvm.used")); +} + +TEST(UsedGlobal, AppendToUsedList3) { + LLVMContext C; + + std::unique_ptr M = parseIR(C, R"( + @x = addrspace(1) global [2 x i32] zeroinitializer, align 4 + @y = addrspace(2) global [2 x i32] zeroinitializer, align 4 + @llvm.compiler.used = appending global [1 x ptr addrspace(3)] [ptr addrspace(3) addrspacecast (ptr addrspace(1) @x to ptr addrspace(3))] + )"); + GlobalVariable *X = M->getNamedGlobal("x"); + GlobalVariable *Y = M->getNamedGlobal("y"); + EXPECT_EQ(1, getListSize(*M, "llvm.compiler.used")); + appendToCompilerUsed(*M, X); + EXPECT_EQ(1, getListSize(*M, "llvm.compiler.used")); + appendToCompilerUsed(*M, Y); + EXPECT_EQ(2, getListSize(*M, "llvm.compiler.used")); +} diff --git a/llvm/unittests/Transforms/Utils/ModuleUtilsTest.cpp b/llvm/unittests/Transforms/Utils/ModuleUtilsTest.cpp index cbdb4dcbc9a6f..f1c984717096f 100644 --- a/llvm/unittests/Transforms/Utils/ModuleUtilsTest.cpp +++ b/llvm/unittests/Transforms/Utils/ModuleUtilsTest.cpp @@ -33,59 +33,6 @@ static int getListSize(Module &M, StringRef Name) { return T->getNumElements(); } -TEST(ModuleUtils, AppendToUsedList1) { - LLVMContext C; - - std::unique_ptr M = parseIR( - C, R"(@x = addrspace(4) global [2 x i32] zeroinitializer, align 4)"); - SmallVector Globals; - for (auto &G : M->globals()) { - Globals.push_back(&G); - } - EXPECT_EQ(0, getListSize(*M, "llvm.compiler.used")); - appendToCompilerUsed(*M, Globals); - EXPECT_EQ(1, getListSize(*M, "llvm.compiler.used")); - - EXPECT_EQ(0, getListSize(*M, "llvm.used")); - appendToUsed(*M, Globals); - EXPECT_EQ(1, getListSize(*M, "llvm.used")); -} - -TEST(ModuleUtils, AppendToUsedList2) { - LLVMContext C; - - std::unique_ptr M = - parseIR(C, R"(@x = global [2 x i32] zeroinitializer, align 4)"); - SmallVector Globals; - for (auto &G : M->globals()) { - Globals.push_back(&G); - } - EXPECT_EQ(0, getListSize(*M, "llvm.compiler.used")); - appendToCompilerUsed(*M, Globals); - EXPECT_EQ(1, getListSize(*M, "llvm.compiler.used")); - - EXPECT_EQ(0, getListSize(*M, "llvm.used")); - appendToUsed(*M, Globals); - EXPECT_EQ(1, getListSize(*M, "llvm.used")); -} - -TEST(ModuleUtils, AppendToUsedList3) { - LLVMContext C; - - std::unique_ptr M = parseIR(C, R"( - @x = addrspace(1) global [2 x i32] zeroinitializer, align 4 - @y = addrspace(2) global [2 x i32] zeroinitializer, align 4 - @llvm.compiler.used = appending global [1 x ptr addrspace(3)] [ptr addrspace(3) addrspacecast (ptr addrspace(1) @x to ptr addrspace(3))] - )"); - GlobalVariable *X = M->getNamedGlobal("x"); - GlobalVariable *Y = M->getNamedGlobal("y"); - EXPECT_EQ(1, getListSize(*M, "llvm.compiler.used")); - appendToCompilerUsed(*M, X); - EXPECT_EQ(1, getListSize(*M, "llvm.compiler.used")); - appendToCompilerUsed(*M, Y); - EXPECT_EQ(2, getListSize(*M, "llvm.compiler.used")); -} - using AppendFnType = decltype(&appendToGlobalCtors); using TransformFnType = decltype(&transformGlobalCtors); using ParamType = std::tuple;