diff options
| author | Rafael Espindola <rafael.espindola@gmail.com> | 2013-11-05 05:22:36 +0000 |
|---|---|---|
| committer | Rafael Espindola <rafael.espindola@gmail.com> | 2013-11-05 05:22:36 +0000 |
| commit | 5d79a51a45ea9e4156acfd221e6bbe40b7ba2faa (patch) | |
| tree | 6148c66415960561c61457c43eab0e4d5c182798 | |
| parent | b4db43fad68c5c437075bcbf29d9ea5b5fc68f3a (diff) | |
| download | bcm5719-llvm-5d79a51a45ea9e4156acfd221e6bbe40b7ba2faa.tar.gz bcm5719-llvm-5d79a51a45ea9e4156acfd221e6bbe40b7ba2faa.zip | |
Produce direct calls instead of alias to linkonce_odr functions.
This is a small optimization on linux, but should help more on windows
where msvc only outputs one destructor if there would be two identical ones.
llvm-svn: 194046
| -rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 41 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/ctor-dtor-alias.cpp | 9 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/destructors.cpp | 4 |
3 files changed, 29 insertions, 25 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 25f3e6f4daa..ab45e321cbb 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -112,28 +112,13 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, // support aliases with that linkage, fail. llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl); - llvm::GlobalValue::LinkageTypes TargetLinkage - = getFunctionLinkage(TargetDecl); - - // Don't create an alias to a linker weak symbol unless we know we can do - // that in every TU. This avoids producing different COMDATs in different - // TUs. - if (llvm::GlobalValue::isWeakForLinker(TargetLinkage)) { - if (!InEveryTU) - return true; - - // In addition to making sure we produce it in every TU, we have to make - // sure llvm keeps it. - // FIXME: Instead of outputting an alias we could just replace every use of - // AliasDecl with TargetDecl. - assert(Linkage == TargetLinkage); - Linkage = llvm::GlobalValue::WeakODRLinkage; - } - // We can't use an alias if the linkage is not valid for one. if (!llvm::GlobalAlias::isValidLinkage(Linkage)) return true; + llvm::GlobalValue::LinkageTypes TargetLinkage = + getFunctionLinkage(TargetDecl); + // Check if we have it already. StringRef MangledName = getMangledName(AliasDecl); llvm::GlobalValue *Entry = GetGlobalValue(MangledName); @@ -152,6 +137,26 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, if (Ref->getType() != AliasType) Aliasee = llvm::ConstantExpr::getBitCast(Ref, AliasType); + // Don't create an alias to a linker weak symbol unless we know we can do + // that in every TU. This avoids producing different COMDATs in different + // TUs. + if (llvm::GlobalValue::isWeakForLinker(TargetLinkage)) { + if (!InEveryTU) + return true; + + assert(Linkage == TargetLinkage); + // Instead of creating as alias to a linkonce_odr, replace all of the uses + // of the aliassee. + if (TargetLinkage == llvm::GlobalValue::LinkOnceODRLinkage) { + if (!Entry) + return false; + + Entry->replaceAllUsesWith(Aliasee); + Entry->eraseFromParent(); + return false; + } + } + // Create the alias with no name. llvm::GlobalAlias *Alias = new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule()); diff --git a/clang/test/CodeGenCXX/ctor-dtor-alias.cpp b/clang/test/CodeGenCXX/ctor-dtor-alias.cpp index e658522d799..ff9bd7c5c5c 100644 --- a/clang/test/CodeGenCXX/ctor-dtor-alias.cpp +++ b/clang/test/CodeGenCXX/ctor-dtor-alias.cpp @@ -13,12 +13,11 @@ template struct foobar<void>; } namespace test2 { -// test that we produce an alias when the destrucor is linkonce_odr. Note that -// the alias itself is weak_odr to make sure we don't get a translation unit -// with just _ZN5test26foobarIvEC2Ev in it. +// test that when the destrucor is linkonce_odr we just replace every use of +// C1 with C2. -// CHECK-DAG: @_ZN5test26foobarIvEC1Ev = alias weak_odr void (%"struct.test2::foobar"*)* @_ZN5test26foobarIvEC2Ev // CHECK-DAG: define linkonce_odr void @_ZN5test26foobarIvEC2Ev( +// CHECK-DAG: call void @_ZN5test26foobarIvEC2Ev void g(); template <typename T> struct foobar { foobar() { g(); } @@ -48,9 +47,7 @@ namespace test4 { // Test that we don't produce aliases from B to A. We cannot because we cannot // guarantee that they will be present in every TU. - // CHECK-DAG: @_ZN5test41BD1Ev = alias weak_odr void (%"struct.test4::B"*)* @_ZN5test41BD2Ev // CHECK-DAG: define linkonce_odr void @_ZN5test41BD2Ev( - // CHECK-DAG: @_ZN5test41AD1Ev = alias weak_odr void (%"struct.test4::A"*)* @_ZN5test41AD2Ev // CHECK-DAG: define linkonce_odr void @_ZN5test41AD2Ev( struct A { virtual ~A() {} diff --git a/clang/test/CodeGenCXX/destructors.cpp b/clang/test/CodeGenCXX/destructors.cpp index 0030aae92ed..fa7df1babf8 100644 --- a/clang/test/CodeGenCXX/destructors.cpp +++ b/clang/test/CodeGenCXX/destructors.cpp @@ -9,7 +9,6 @@ // CHECK-DAG: @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11DD2Ev // CHECK-DAG: @_ZN5test312_GLOBAL__N_11DD2Ev = alias internal bitcast {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev // CHECK-DAG: @_ZN5test312_GLOBAL__N_11CD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev -// CHECK-DAG: @_ZN6PR752617allocator_derivedD1Ev = alias weak_odr void (%"struct.PR7526::allocator_derived"*)* @_ZN6PR752617allocator_derivedD2Ev struct A { int a; @@ -45,6 +44,9 @@ namespace PR7526 { // CHECK: call void @__cxa_call_unexpected allocator::~allocator() throw() { foo(); } + // CHECK-LABEL: define void @_ZN6PR75263fooEv() + // CHECK: call void @_ZN6PR752617allocator_derivedD2Ev + void foo() { allocator_derived ad; } |

