Thanks!<span></span><br><br>On Tuesday, September 23, 2014, Reid Kleckner <<a href="mailto:reid@kleckner.net">reid@kleckner.net</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rnk<br>
Date: Tue Sep 23 17:33:01 2014<br>
New Revision: 218337<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=218337&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=218337&view=rev</a><br>
Log:<br>
GlobalOpt: Preserve comdats of unoptimized initializers<br>
<br>
Rather than slurping in and splatting out the whole ctor list, preserve<br>
the existing array entries without trying to understand them.  Only<br>
remove the entries that we know we can optimize away.  This way we don't<br>
need to wire through priority and comdats or anything else we might add.<br>
<br>
Fixes a linker issue where the .init_array or .ctors entry would point<br>
to discarded initialization code if the comdat group from the TU with<br>
the faulty global_ctors entry was dropped.<br>
<br>
Added:<br>
    llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll<br>
Modified:<br>
    llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp<br>
<br>
Modified: llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp?rev=218337&r1=218336&r2=218337&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp?rev=218337&r1=218336&r2=218337&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp Tue Sep 23 17:33:01 2014<br>
@@ -11,6 +11,7 @@<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
<br>
+#include "llvm/ADT/BitVector.h"<br>
 #include "llvm/Transforms/Utils/CtorUtils.h"<br>
 #include "llvm/IR/Constants.h"<br>
 #include "llvm/IR/Function.h"<br>
@@ -24,41 +25,22 @@<br>
 namespace llvm {<br>
<br>
 namespace {<br>
-/// Given a specified llvm.global_ctors list, install the<br>
-/// specified array.<br>
-void installGlobalCtors(GlobalVariable *GCL,<br>
-                        const std::vector<Function *> &Ctors) {<br>
-  // If we made a change, reassemble the initializer list.<br>
-  Constant *CSVals[3];<br>
-<br>
-  StructType *StructTy =<br>
-      cast<StructType>(GCL->getType()->getElementType()->getArrayElementType());<br>
-<br>
-  // Create the new init list.<br>
-  std::vector<Constant *> CAList;<br>
-  for (Function *F : Ctors) {<br>
-    Type *Int32Ty = Type::getInt32Ty(GCL->getContext());<br>
-    if (F) {<br>
-      CSVals[0] = ConstantInt::get(Int32Ty, 65535);<br>
-      CSVals[1] = F;<br>
-    } else {<br>
-      CSVals[0] = ConstantInt::get(Int32Ty, 0x7fffffff);<br>
-      CSVals[1] = Constant::getNullValue(StructTy->getElementType(1));<br>
-    }<br>
-    // FIXME: Only allow the 3-field form in LLVM 4.0.<br>
-    size_t NumElts = StructTy->getNumElements();<br>
-    if (NumElts > 2)<br>
-      CSVals[2] = Constant::getNullValue(StructTy->getElementType(2));<br>
-    CAList.push_back(<br>
-        ConstantStruct::get(StructTy, makeArrayRef(CSVals, NumElts)));<br>
-  }<br>
-<br>
-  // Create the array initializer.<br>
-  Constant *CA =<br>
-      ConstantArray::get(ArrayType::get(StructTy, CAList.size()), CAList);<br>
+/// Given a specified llvm.global_ctors list, remove the listed elements.<br>
+void removeGlobalCtors(GlobalVariable *GCL, const BitVector &CtorsToRemove) {<br>
+  // Filter out the initializer elements to remove.<br>
+  ConstantArray *OldCA = cast<ConstantArray>(GCL->getInitializer());<br>
+  SmallVector<Constant *, 10> CAList;<br>
+  for (unsigned I = 0, E = OldCA->getNumOperands(); I < E; ++I)<br>
+    if (!CtorsToRemove.test(I))<br>
+      CAList.push_back(OldCA->getOperand(I));<br>
+<br>
+  // Create the new array initializer.<br>
+  ArrayType *ATy =<br>
+      ArrayType::get(OldCA->getType()->getElementType(), CAList.size());<br>
+  Constant *CA = ConstantArray::get(ATy, CAList);<br>
<br>
   // If we didn't change the number of elements, don't create a new GV.<br>
-  if (CA->getType() == GCL->getInitializer()->getType()) {<br>
+  if (CA->getType() == OldCA->getType()) {<br>
     GCL->setInitializer(CA);<br>
     return;<br>
   }<br>
@@ -82,7 +64,7 @@ void installGlobalCtors(GlobalVariable *<br>
<br>
 /// Given a llvm.global_ctors list that we can understand,<br>
 /// return a list of the functions and null terminator as a vector.<br>
-std::vector<Function*> parseGlobalCtors(GlobalVariable *GV) {<br>
+std::vector<Function *> parseGlobalCtors(GlobalVariable *GV) {<br>
   if (GV->getInitializer()->isNullValue())<br>
     return std::vector<Function *>();<br>
   ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());<br>
@@ -147,17 +129,15 @@ bool optimizeGlobalCtorsList(Module &M,<br>
   bool MadeChange = false;<br>
<br>
   // Loop over global ctors, optimizing them when we can.<br>
-  for (unsigned i = 0; i != Ctors.size(); ++i) {<br>
+  unsigned NumCtors = Ctors.size();<br>
+  BitVector CtorsToRemove(NumCtors);<br>
+  for (unsigned i = 0; i != Ctors.size() && NumCtors > 0; ++i) {<br>
     Function *F = Ctors[i];<br>
     // Found a null terminator in the middle of the list, prune off the rest of<br>
     // the list.<br>
-    if (!F) {<br>
-      if (i != Ctors.size() - 1) {<br>
-        Ctors.resize(i + 1);<br>
-        MadeChange = true;<br>
-      }<br>
-      break;<br>
-    }<br>
+    if (!F)<br>
+      continue;<br>
+<br>
     DEBUG(dbgs() << "Optimizing Global Constructor: " << *F << "\n");<br>
<br>
     // We cannot simplify external ctor functions.<br>
@@ -166,9 +146,10 @@ bool optimizeGlobalCtorsList(Module &M,<br>
<br>
     // If we can evaluate the ctor at compile time, do.<br>
     if (ShouldRemove(F)) {<br>
-      Ctors.erase(Ctors.begin() + i);<br>
+      Ctors[i] = nullptr;<br>
+      CtorsToRemove.set(i);<br>
+      NumCtors--;<br>
       MadeChange = true;<br>
-      --i;<br>
       continue;<br>
     }<br>
   }<br>
@@ -176,7 +157,7 @@ bool optimizeGlobalCtorsList(Module &M,<br>
   if (!MadeChange)<br>
     return false;<br>
<br>
-  installGlobalCtors(GlobalCtors, Ctors);<br>
+  removeGlobalCtors(GlobalCtors, CtorsToRemove);<br>
   return true;<br>
 }<br>
<br>
<br>
Added: llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll?rev=218337&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll?rev=218337&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll (added)<br>
+++ llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll Tue Sep 23 17:33:01 2014<br>
@@ -0,0 +1,37 @@<br>
+; RUN: opt -globalopt -S < %s | FileCheck %s<br>
+<br>
+$comdat_global = comdat any<br>
+<br>
+@comdat_global = weak_odr global i8 0, comdat $comdat_global<br>
+@simple_global = internal global i8 0<br>
+; CHECK: @comdat_global = weak_odr global i8 0, comdat $comdat_global<br>
+; CHECK: @simple_global = internal global i8 42<br>
+<br>
+@llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [<br>
+    { i32, void ()*, i8* } { i32 65535, void ()* @init_comdat_global, i8* @comdat_global },<br>
+    { i32, void ()*, i8* } { i32 65535, void ()* @init_simple_global, i8* null }<br>
+]<br>
+; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }]<br>
+; CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()* @init_comdat_global, i8* @comdat_global }]<br>
+<br>
+define void @init_comdat_global() {<br>
+  store i8 42, i8* @comdat_global<br>
+  ret void<br>
+}<br>
+; CHECK: define void @init_comdat_global()<br>
+<br>
+define internal void @init_simple_global() comdat $comdat_global {<br>
+  store i8 42, i8* @simple_global<br>
+  ret void<br>
+}<br>
+; CHECK-NOT: @init_simple_global()<br>
+<br>
+define i8* @use_simple() {<br>
+  ret i8* @simple_global<br>
+}<br>
+; CHECK: define i8* @use_simple()<br>
+<br>
+define i8* @use_comdat() {<br>
+  ret i8* @comdat_global<br>
+}<br>
+; CHECK: define i8* @use_comdat()<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="javascript:;" onclick="_e(event, 'cvml', 'llvm-commits@cs.uiuc.edu')">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote>