diff options
author | David Majnemer <david.majnemer@gmail.com> | 2014-10-08 07:23:31 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2014-10-08 07:23:31 +0000 |
commit | 1b3b70e371d10ec9a1272bd10f7e08d43e63b511 (patch) | |
tree | cc1162a0e626dfd12a80e43ae07fdc73079227b7 /llvm/lib/Transforms | |
parent | e2ff5b9223b9da46fbdbae2877dd6de91d3cc133 (diff) | |
download | bcm5719-llvm-1b3b70e371d10ec9a1272bd10f7e08d43e63b511.tar.gz bcm5719-llvm-1b3b70e371d10ec9a1272bd10f7e08d43e63b511.zip |
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.
llvm-svn: 219283
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/IPO/GlobalOpt.cpp | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index 93e15e09994..891515d592f 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -88,6 +88,7 @@ namespace { const DataLayout *DL; TargetLibraryInfo *TLI; + SmallSet<const Comdat *, 8> 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<const Comdat *, 8> 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); |