GlobalDCE: Don't drop any COMDAT members

If we require a single member of a comdat, require all of the other
members as well.

This fixes PR20981.

llvm-svn: 219191
This commit is contained in:
David Majnemer 2014-10-07 07:07:19 +00:00
parent 7348322390
commit e025321d36
2 changed files with 31 additions and 25 deletions

View File

@ -78,9 +78,6 @@ bool GlobalDCE::runOnModule(Module &M) {
// Remove empty functions from the global ctors list.
Changed |= optimizeGlobalCtorsList(M, isEmptyFunction);
typedef std::multimap<const Comdat *, GlobalValue *> 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<GlobalVariable>(G)) {
// If this is a global variable, we must make sure to add any global values
// referenced by the initializer to the alive set.

View File

@ -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
}