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..bbf9a51d3f57d --- /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 -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