diff --git a/llvm/lib/Transforms/IPO/GlobalDCE.cpp b/llvm/lib/Transforms/IPO/GlobalDCE.cpp index e50cdb7358cf..f4d5536b37b4 100644 --- a/llvm/lib/Transforms/IPO/GlobalDCE.cpp +++ b/llvm/lib/Transforms/IPO/GlobalDCE.cpp @@ -78,9 +78,6 @@ bool GlobalDCE::runOnModule(Module &M) { // Remove empty functions from the global ctors list. Changed |= optimizeGlobalCtorsList(M, isEmptyFunction); - typedef std::multimap ComdatGVPairsTy; - ComdatGVPairsTy ComdatGVPairs; - // Loop over the module, adding globals which are obviously necessary. for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { Changed |= RemoveUnusedGlobalValue(*I); @@ -88,8 +85,6 @@ bool GlobalDCE::runOnModule(Module &M) { if (!I->isDeclaration() && !I->hasAvailableExternallyLinkage()) { if (!I->isDiscardableIfUnused()) GlobalIsNeeded(I); - else if (const Comdat *C = I->getComdat()) - ComdatGVPairs.insert(std::make_pair(C, I)); } } @@ -101,8 +96,6 @@ bool GlobalDCE::runOnModule(Module &M) { if (!I->isDeclaration() && !I->hasAvailableExternallyLinkage()) { if (!I->isDiscardableIfUnused()) GlobalIsNeeded(I); - else if (const Comdat *C = I->getComdat()) - ComdatGVPairs.insert(std::make_pair(C, I)); } } @@ -112,26 +105,9 @@ bool GlobalDCE::runOnModule(Module &M) { // Externally visible aliases are needed. if (!I->isDiscardableIfUnused()) { GlobalIsNeeded(I); - } else if (const Comdat *C = I->getComdat()) { - ComdatGVPairs.insert(std::make_pair(C, I)); } } - for (ComdatGVPairsTy::iterator I = ComdatGVPairs.begin(), - E = ComdatGVPairs.end(); - I != E;) { - ComdatGVPairsTy::iterator UB = ComdatGVPairs.upper_bound(I->first); - bool CanDiscard = std::all_of(I, UB, [](ComdatGVPairsTy::value_type Pair) { - return Pair.second->isDiscardableIfUnused(); - }); - if (!CanDiscard) { - std::for_each(I, UB, [this](ComdatGVPairsTy::value_type Pair) { - GlobalIsNeeded(Pair.second); - }); - } - I = UB; - } - // Now that all globals which are needed are in the AliveGlobals set, we loop // through the program, deleting those which are not alive. // @@ -211,7 +187,20 @@ void GlobalDCE::GlobalIsNeeded(GlobalValue *G) { // If the global is already in the set, no need to reprocess it. if (!AliveGlobals.insert(G)) return; - + + Module *M = G->getParent(); + if (Comdat *C = G->getComdat()) { + for (Function &F : *M) + if (F.getComdat() == C) + GlobalIsNeeded(&F); + for (GlobalVariable &GV : M->globals()) + if (GV.getComdat() == C) + GlobalIsNeeded(&GV); + for (GlobalAlias &GA : M->aliases()) + if (GA.getComdat() == C) + GlobalIsNeeded(&GA); + } + if (GlobalVariable *GV = dyn_cast(G)) { // If this is a global variable, we must make sure to add any global values // referenced by the initializer to the alive set. diff --git a/llvm/test/Transforms/GlobalDCE/pr20981.ll b/llvm/test/Transforms/GlobalDCE/pr20981.ll new file mode 100644 index 000000000000..92d28408fdc3 --- /dev/null +++ b/llvm/test/Transforms/GlobalDCE/pr20981.ll @@ -0,0 +1,17 @@ +; RUN: opt < %s -globaldce -S | FileCheck %s + +$c1 = comdat any +; CHECK: $c1 = comdat any + +@a1 = linkonce_odr alias void ()* @f1 +; CHECK: @a1 = linkonce_odr alias void ()* @f1 + +define linkonce_odr void @f1() comdat $c1 { + ret void +} +; CHECK: define linkonce_odr void @f1() comdat $c1 + +define void @g() { + call void @f1() + ret void +}