]> granicus.if.org Git - clang/commitdiff
In the Itanium ABI, move stuff to the comdat of variables with static init.
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 19 Sep 2014 19:43:18 +0000 (19:43 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 19 Sep 2014 19:43:18 +0000 (19:43 +0000)
Clang can already handle

-------------------------------------------
struct S {
  static const int x;
};
template<typename T> struct U {
  static const int k;
};
template<typename T> const int U<T>::k = T::x;

const int S::x = 42;
extern const int *f();
const int *g() { return &U<S>::k; }
int main() {
  return *f() + U<S>::k;
}

const int *f() { return &U<S>::k; }
-------------------------------------------

since r217264 which puts the .inint_array section in the same COMDAT
as the variable.

This patch allows the linker to more easily delete some dead code and data by
putting the guard variable and init function in the same COMDAT.

This is a fixed version of r218089.

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

lib/CodeGen/ItaniumCXXABI.cpp
test/CodeGenCXX/static-data-member.cpp
test/CodeGenCXX/static-init.cpp

index 4a24e77139f72bc08fb1ff5ffffb2bbb89911a59..ed7b4e9dadd2f00466716bd1fb791ce0e58e16c6 100644 (file)
@@ -1666,6 +1666,15 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
     // If the variable is thread-local, so is its guard variable.
     guard->setThreadLocalMode(var->getThreadLocalMode());
 
+    // The ABI says: It is suggested that it be emitted in the same COMDAT group
+    // as the associated data object
+    if (!D.isLocalVarDecl() && var->isWeakForLinker() && CGM.supportsCOMDAT()) {
+      llvm::Comdat *C = CGM.getModule().getOrInsertComdat(var->getName());
+      guard->setComdat(C);
+      var->setComdat(C);
+      CGF.CurFn->setComdat(C);
+    }
+
     CGM.setStaticLocalDeclGuardAddress(&D, guard);
   }
 
index eea979494843b2cbc6040ac1973083b9e82fbbbb..5ec3755b4034fd119375c1e0237e775af37a79de 100644 (file)
@@ -1,9 +1,13 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | \
+// RUN: FileCheck --check-prefix=MACHO %s
 
 // CHECK: @_ZN5test11A1aE = constant i32 10, align 4
 // CHECK: @_ZN5test212_GLOBAL__N_11AIiE1xE = internal global i32 0, align 4
-// CHECK: @_ZN5test31AIiE1xE = weak_odr global i32 0, align 4
-// CHECK: @_ZGVN5test31AIiE1xE = weak_odr global i64 0
+// CHECK: @_ZN5test31AIiE1xE = weak_odr global i32 0, comdat $_ZN5test31AIiE1xE, align 4
+// CHECK: @_ZGVN5test31AIiE1xE = weak_odr global i64 0, comdat $_ZN5test31AIiE1xE
+// MACHO: @_ZGVN5test31AIiE1xE = weak_odr global i64 0
+// MACHO-NOT: comdat
 
 // CHECK: _ZN5test51U2k0E = global i32 0
 // CHECK: _ZN5test51U2k1E = global i32 0
@@ -60,7 +64,9 @@ namespace test3 {
   template <class T> int A<T>::x = foo();
   template struct A<int>;
 
-  // CHECK-LABEL: define internal void @__cxx_global_var_init1()
+  // CHECK-LABEL: define internal void @__cxx_global_var_init1() {{.*}} comdat $_ZN5test31AIiE1xE
+  // MACHO-LABEL: define internal void @__cxx_global_var_init1()
+  // MACHO-NOT: comdat
   // CHECK:      [[GUARDBYTE:%.*]] = load i8* bitcast (i64* @_ZGVN5test31AIiE1xE to i8*)
   // CHECK-NEXT: [[UNINITIALIZED:%.*]] = icmp eq i8 [[GUARDBYTE]], 0
   // CHECK-NEXT: br i1 [[UNINITIALIZED]]
index d23ead47f385570beecc5fcad142805ca5bbc609..a9debe3de76506b649c2cf3f7754245189c30d8b 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linuxs -emit-llvm -o - | FileCheck %s
 
 // CHECK: @_ZZ1hvE1i = internal global i32 0, align 4
 // CHECK: @base_req = global [4 x i8] c"foo\00", align 1
@@ -6,8 +6,11 @@
 
 // CHECK: @_ZZN5test31BC1EvE1u = internal global { i8, [3 x i8] } { i8 97, [3 x i8] undef }, align 4
 // CHECK: @_ZZN5test1L6getvarEiE3var = internal constant [4 x i32] [i32 1, i32 0, i32 2, i32 4], align 16
+
 // CHECK: @_ZZ2h2vE1i = linkonce_odr global i32 0
+// CHECK-NOT: comdat
 // CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0
+// CHECK-NOT: comdat
 
 struct A {
   A();
@@ -34,6 +37,8 @@ void h() {
   static const int i = a();
 }
 
+// CHECK: define linkonce_odr void @_Z2h2v()
+// CHECK-NOT: comdat
 inline void h2() {
   static int i = a();
 }