From 9b46288d7023b4dcf4dd6a7e4ab8dabebbb33770 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 19 Sep 2014 19:43:18 +0000 Subject: [PATCH] In the Itanium ABI, move stuff to the comdat of variables with static init. Clang can already handle ------------------------------------------- struct S { static const int x; }; template struct U { static const int k; }; template const int U::k = T::x; const int S::x = 42; extern const int *f(); const int *g() { return &U::k; } int main() { return *f() + U::k; } const int *f() { return &U::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 | 9 +++++++++ test/CodeGenCXX/static-data-member.cpp | 14 ++++++++++---- test/CodeGenCXX/static-init.cpp | 7 ++++++- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 4a24e77139..ed7b4e9dad 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -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); } diff --git a/test/CodeGenCXX/static-data-member.cpp b/test/CodeGenCXX/static-data-member.cpp index eea9794948..5ec3755b40 100644 --- a/test/CodeGenCXX/static-data-member.cpp +++ b/test/CodeGenCXX/static-data-member.cpp @@ -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 int A::x = foo(); template struct A; - // 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]] diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp index d23ead47f3..a9debe3de7 100644 --- a/test/CodeGenCXX/static-init.cpp +++ b/test/CodeGenCXX/static-init.cpp @@ -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(); } -- 2.40.0