r194095 - Produce direct calls instead of alias to linkonce_odr functions.

Rafael Espindola rafael.espindola at gmail.com
Tue Nov 5 13:37:29 PST 2013


Author: rafael
Date: Tue Nov  5 15:37:29 2013
New Revision: 194095

URL: http://llvm.org/viewvc/llvm-project?rev=194095&view=rev
Log:
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.

Modified:
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp
    cfe/trunk/test/CodeGenCXX/destructors.cpp

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=194095&r1=194094&r2=194095&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Tue Nov  5 15:37:29 2013
@@ -112,33 +112,20 @@ bool CodeGenModule::TryEmitDefinitionAsA
   // 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);
   if (Entry && !Entry->isDeclaration())
     return false;
+  if (Replacements.count(MangledName))
+    return false;
 
   // Derive the type for the alias.
   llvm::PointerType *AliasType
@@ -152,6 +139,22 @@ bool CodeGenModule::TryEmitDefinitionAsA
   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) {
+      Replacements[MangledName] = Aliasee;
+      return false;
+    }
+  }
+
   // Create the alias with no name.
   llvm::GlobalAlias *Alias = 
     new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule());

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=194095&r1=194094&r2=194095&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Nov  5 15:37:29 2013
@@ -172,6 +172,20 @@ void CodeGenModule::createCUDARuntime()
   CUDARuntime = CreateNVCUDARuntime(*this);
 }
 
+void CodeGenModule::applyReplacements() {
+  for (ReplacementsTy::iterator I = Replacements.begin(),
+                                E = Replacements.end();
+       I != E; ++I) {
+    StringRef MangledName = I->first();
+    llvm::Constant *Replacement = I->second;
+    llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+    if (!Entry)
+      continue;
+    Entry->replaceAllUsesWith(Replacement);
+    Entry->eraseFromParent();
+  }
+}
+
 void CodeGenModule::checkAliases() {
   bool Error = false;
   for (std::vector<GlobalDecl>::iterator I = Aliases.begin(),
@@ -207,6 +221,7 @@ void CodeGenModule::checkAliases() {
 
 void CodeGenModule::Release() {
   EmitDeferred();
+  applyReplacements();
   checkAliases();
   EmitCXXGlobalInitFunc();
   EmitCXXGlobalDtorFunc();

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=194095&r1=194094&r2=194095&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Tue Nov  5 15:37:29 2013
@@ -279,6 +279,9 @@ class CodeGenModule : public CodeGenType
   /// is defined once we get to the end of the of the translation unit.
   std::vector<GlobalDecl> Aliases;
 
+  typedef llvm::StringMap<llvm::TrackingVH<llvm::Constant> > ReplacementsTy;
+  ReplacementsTy Replacements;
+
   /// DeferredVTables - A queue of (optional) vtables to consider emitting.
   std::vector<const CXXRecordDecl*> DeferredVTables;
 
@@ -1082,6 +1085,9 @@ private:
   /// was deferred.
   void EmitDeferred();
 
+  /// Call replaceAllUsesWith on all pairs in Replacements.
+  void applyReplacements();
+
   void checkAliases();
 
   /// EmitDeferredVTables - Emit any vtables which we deferred and

Modified: cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp?rev=194095&r1=194094&r2=194095&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp Tue Nov  5 15:37:29 2013
@@ -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() {}

Modified: cfe/trunk/test/CodeGenCXX/destructors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/destructors.cpp?rev=194095&r1=194094&r2=194095&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/destructors.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/destructors.cpp Tue Nov  5 15:37:29 2013
@@ -9,8 +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
-// CHECK-DAG: @_ZN6test106OptionD1Ev = alias weak_odr void (%"struct.test10::Option"*)* @_ZN6test106OptionD2Ev
 
 struct A {
   int a;
@@ -46,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;
   }
@@ -367,14 +368,15 @@ namespace test9 {
 
 namespace test10 {
   // We used to crash trying to replace _ZN6test106OptionD1Ev with
-  // _ZN6test106OptionD2Ev twice. For now check that we don't try and produce
-  // an alias instead (check at the top of the file).
+  // _ZN6test106OptionD2Ev twice.
   struct Option {
     virtual ~Option() {}
   };
   template <class DataType> class opt : public Option {};
   template class opt<int>;
+  // CHECK-LABEL: define zeroext i1 @_ZN6test1016handleOccurrenceEv(
   bool handleOccurrence() {
+    // CHECK: call void @_ZN6test106OptionD2Ev(
     Option x;
     return true;
   }





More information about the cfe-commits mailing list