GlobalDCE: Don't drop any COMDAT members
authorDavid Majnemer <david.majnemer@gmail.com>
Tue, 7 Oct 2014 07:07:19 +0000 (07:07 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Tue, 7 Oct 2014 07:07:19 +0000 (07:07 +0000)
If we require a single member of a comdat, require all of the other
members as well.

This fixes PR20981.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219191 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/IPO/GlobalDCE.cpp
test/Transforms/GlobalDCE/pr20981.ll [new file with mode: 0644]

index e50cdb7358cf8aed23454d892b9bd2cbed408ae3..f4d5536b37b4e2ac5a7d5b7150a7be21be41015e 100644 (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,24 +105,7 @@ 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
@@ -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.
diff --git a/test/Transforms/GlobalDCE/pr20981.ll b/test/Transforms/GlobalDCE/pr20981.ll
new file mode 100644 (file)
index 0000000..92d2840
--- /dev/null
@@ -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
+}