From b07b0970b1c57ea63656e425948dec83b710d38f Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 8 Oct 2014 07:23:31 +0000 Subject: [PATCH] GlobalOpt: Don't drop unused memberes of a Comdat A linkonce_odr member of a COMDAT shouldn't be dropped if we need to keep the entire COMDAT group. This fixes PR21191. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219283 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/GlobalOpt.cpp | 28 ++++++++++++++++++++-------- test/Transforms/GlobalOpt/pr21191.ll | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 test/Transforms/GlobalOpt/pr21191.ll diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 93e15e09994..891515d592f 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -88,6 +88,7 @@ namespace { const DataLayout *DL; TargetLibraryInfo *TLI; + SmallSet NotDiscardableComdats; }; } @@ -1908,8 +1909,11 @@ bool GlobalOpt::OptimizeFunctions(Module &M) { // Functions without names cannot be referenced outside this module. if (!F->hasName() && !F->isDeclaration() && !F->hasLocalLinkage()) F->setLinkage(GlobalValue::InternalLinkage); + + const Comdat *C = F->getComdat(); + bool inComdat = C && NotDiscardableComdats.count(C); F->removeDeadConstantUsers(); - if (F->isDefTriviallyDead()) { + if ((!inComdat || F->hasLocalLinkage()) && F->isDefTriviallyDead()) { F->eraseFromParent(); Changed = true; ++NumFnDeleted; @@ -1941,12 +1945,6 @@ bool GlobalOpt::OptimizeFunctions(Module &M) { bool GlobalOpt::OptimizeGlobalVars(Module &M) { bool Changed = false; - SmallSet NotDiscardableComdats; - for (const GlobalVariable &GV : M.globals()) - if (const Comdat *C = GV.getComdat()) - if (!GV.isDiscardableIfUnused()) - NotDiscardableComdats.insert(C); - for (Module::global_iterator GVI = M.global_begin(), E = M.global_end(); GVI != E; ) { GlobalVariable *GV = GVI++; @@ -1963,7 +1961,7 @@ bool GlobalOpt::OptimizeGlobalVars(Module &M) { if (GV->isDiscardableIfUnused()) { if (const Comdat *C = GV->getComdat()) - if (NotDiscardableComdats.count(C)) + if (NotDiscardableComdats.count(C) && !GV->hasLocalLinkage()) continue; Changed |= ProcessGlobal(GV, GVI); } @@ -3047,6 +3045,20 @@ bool GlobalOpt::runOnModule(Module &M) { while (LocalChange) { LocalChange = false; + NotDiscardableComdats.clear(); + for (const GlobalVariable &GV : M.globals()) + if (const Comdat *C = GV.getComdat()) + if (!GV.isDiscardableIfUnused() || !GV.use_empty()) + NotDiscardableComdats.insert(C); + for (Function &F : M) + if (const Comdat *C = F.getComdat()) + if (!F.isDefTriviallyDead()) + NotDiscardableComdats.insert(C); + for (GlobalAlias &GA : M.aliases()) + if (const Comdat *C = GA.getComdat()) + if (!GA.isDiscardableIfUnused() || !GA.use_empty()) + NotDiscardableComdats.insert(C); + // Delete functions that are trivially dead, ccc -> fastcc LocalChange |= OptimizeFunctions(M); diff --git a/test/Transforms/GlobalOpt/pr21191.ll b/test/Transforms/GlobalOpt/pr21191.ll new file mode 100644 index 00000000000..39b8eee9a25 --- /dev/null +++ b/test/Transforms/GlobalOpt/pr21191.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -globalopt -S | FileCheck %s + +$c = comdat any +; CHECK: $c = comdat any + +define linkonce_odr void @foo() comdat $c { + ret void +} +; CHECK: define linkonce_odr void @foo() comdat $c + +define linkonce_odr void @bar() comdat $c { + ret void +} +; CHECK: define linkonce_odr void @bar() comdat $c + +define void @zed() { + call void @foo() + ret void +} -- 2.11.0