From aefb27206bd95ea40fb5f5dff49b7ad5fa74d8a0 Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Tue, 18 Nov 2025 21:54:18 +0100 Subject: [PATCH 1/2] [GlobalOpt]: Remove metadata when referenced global variable is removed --- llvm/lib/Transforms/IPO/GlobalOpt.cpp | 43 ++++++++++++++++--- .../Transforms/GlobalOpt/dead_metadata.ll | 11 +++++ 2 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 llvm/test/Transforms/GlobalOpt/dead_metadata.ll diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index c3dede31540d6..d8b220d08d7e5 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -1322,8 +1322,38 @@ static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) { return true; } +// Iterate over all globals in the module and remove any metadata that +// references to the given GV. +static void removeMetadataReferencesToGlobal(Module &M, GlobalValue &GV) { + for (auto &MGV : M.globals()) { + SmallVector, 4> MDs; + MGV.getAllMetadata(MDs); + + for (auto &pair : MDs) { + auto Node = pair.second; + + for (const llvm::MDOperand &Op : Node->operands()) { + llvm::Metadata *MD = Op.get(); + if (!MD) + continue; + + auto *VM = llvm::dyn_cast(MD); + if (!VM) + continue; + + auto *V = llvm::dyn_cast(VM->getValue()); + if (!V) + continue; + + if (V == &GV) + MGV.eraseMetadata(pair.first); + } + } + } +} + static bool -deleteIfDead(GlobalValue &GV, +deleteIfDead(Module &M, GlobalValue &GV, SmallPtrSetImpl &NotDiscardableComdats, function_ref DeleteFnCallback = nullptr) { GV.removeDeadConstantUsers(); @@ -1348,6 +1378,9 @@ deleteIfDead(GlobalValue &GV, if (DeleteFnCallback) DeleteFnCallback(*F); } + + removeMetadataReferencesToGlobal(M, GV); + ReplaceableMetadataImpl::SalvageDebugInfo(GV); GV.eraseFromParent(); ++NumDeleted; @@ -1950,7 +1983,7 @@ OptimizeFunctions(Module &M, if (!F.hasName() && !F.isDeclaration() && !F.hasLocalLinkage()) F.setLinkage(GlobalValue::InternalLinkage); - if (deleteIfDead(F, NotDiscardableComdats, DeleteFnCallback)) { + if (deleteIfDead(M, F, NotDiscardableComdats, DeleteFnCallback)) { Changed = true; continue; } @@ -2062,7 +2095,7 @@ OptimizeGlobalVars(Module &M, GV.setInitializer(New); } - if (deleteIfDead(GV, NotDiscardableComdats)) { + if (deleteIfDead(M, GV, NotDiscardableComdats)) { Changed = true; continue; } @@ -2278,7 +2311,7 @@ OptimizeGlobalAliases(Module &M, if (!J.hasName() && !J.isDeclaration() && !J.hasLocalLinkage()) J.setLinkage(GlobalValue::InternalLinkage); - if (deleteIfDead(J, NotDiscardableComdats)) { + if (deleteIfDead(M, J, NotDiscardableComdats)) { Changed = true; continue; } @@ -2478,7 +2511,7 @@ DeleteDeadIFuncs(Module &M, SmallPtrSetImpl &NotDiscardableComdats) { bool Changed = false; for (GlobalIFunc &IF : make_early_inc_range(M.ifuncs())) - if (deleteIfDead(IF, NotDiscardableComdats)) { + if (deleteIfDead(M, IF, NotDiscardableComdats)) { NumIFuncsDeleted++; Changed = true; } diff --git a/llvm/test/Transforms/GlobalOpt/dead_metadata.ll b/llvm/test/Transforms/GlobalOpt/dead_metadata.ll new file mode 100644 index 0000000000000..e0cf1546d4829 --- /dev/null +++ b/llvm/test/Transforms/GlobalOpt/dead_metadata.ll @@ -0,0 +1,11 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -O3 -passes=globalopt < %s | FileCheck %s + +@a = global i32 0, !associated !0 +@b = external global i32, !associated !1 + +!0 = !{ptr @b} +!1 = !{ptr @a} + +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; CHECK: @a = local_unnamed_addr global i32 \ No newline at end of file From 2b13cecac8c1c31e2139efa2758758681fbd3b9f Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Sun, 23 Nov 2025 16:49:43 +0100 Subject: [PATCH 2/2] [GlobalOpt]: Fixed RUN command --- llvm/test/Transforms/GlobalOpt/dead_metadata.ll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/Transforms/GlobalOpt/dead_metadata.ll b/llvm/test/Transforms/GlobalOpt/dead_metadata.ll index e0cf1546d4829..bbf9a51d3f57d 100644 --- a/llvm/test/Transforms/GlobalOpt/dead_metadata.ll +++ b/llvm/test/Transforms/GlobalOpt/dead_metadata.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -O3 -passes=globalopt < %s | FileCheck %s +; RUN: opt -S -passes=globalopt < %s | FileCheck %s @a = global i32 0, !associated !0 @b = external global i32, !associated !1