[cfe-commits] r124984 - in /cfe/trunk: lib/CodeGen/CGVTables.cpp lib/CodeGen/CGVTables.h test/CodeGenCXX/thunks-available-externally.cpp

Anders Carlsson andersca at mac.com
Sun Feb 6 10:31:40 PST 2011


Author: andersca
Date: Sun Feb  6 12:31:40 2011
New Revision: 124984

URL: http://llvm.org/viewvc/llvm-project?rev=124984&view=rev
Log:
When building with optimizations, emit thunks with available_externally linkage so devirtualized function calls can also be de-thunked.


Added:
    cfe/trunk/test/CodeGenCXX/thunks-available-externally.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGVTables.cpp
    cfe/trunk/lib/CodeGen/CGVTables.h

Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=124984&r1=124983&r2=124984&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVTables.cpp Sun Feb  6 12:31:40 2011
@@ -2679,7 +2679,8 @@
   setThunkVisibility(CGM, MD, Thunk, Fn);
 }
 
-void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk)
+void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk, 
+                               bool UseAvailableExternallyLinkage)
 {
   llvm::Constant *Entry = CGM.GetAddrOfThunk(GD, Thunk);
   
@@ -2714,9 +2715,37 @@
     OldThunkFn->eraseFromParent();
   }
 
-  // Actually generate the thunk body.
   llvm::Function *ThunkFn = cast<llvm::Function>(Entry);
+
+  if (!ThunkFn->isDeclaration()) {
+    if (UseAvailableExternallyLinkage) {
+      // There is already a thunk emitted for this function, do nothing.
+      return;
+    }
+
+    // We should never be able to get a function with a definition here.
+    assert(false && "Shouldn't have an already existing definition");
+  }
+
+  // Actually generate the thunk body.
   CodeGenFunction(CGM).GenerateThunk(ThunkFn, GD, Thunk);
+
+  if (UseAvailableExternallyLinkage)
+    ThunkFn->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
+}
+
+void CodeGenVTables::MaybeEmitThunkAvailableExternally(GlobalDecl GD,
+                                                       const ThunkInfo &Thunk) {
+  // We only want to do this when building with optimizations.
+  if (!CGM.getCodeGenOpts().OptimizationLevel)
+    return;
+
+  // We can't emit thunks for member functions with incomplete types.
+  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+  if (CGM.getTypes().VerifyFuncTypeComplete(MD->getType().getTypePtr()))
+    return;
+
+  EmitThunk(GD, Thunk, /*UseAvailableExternallyLinkage=*/true);
 }
 
 void CodeGenVTables::EmitThunks(GlobalDecl GD)
@@ -2741,7 +2770,7 @@
 
   const ThunkInfoVectorTy &ThunkInfoVector = I->second;
   for (unsigned I = 0, E = ThunkInfoVector.size(); I != E; ++I)
-    EmitThunk(GD, ThunkInfoVector[I]);
+    EmitThunk(GD, ThunkInfoVector[I], /*UseAvailableExternallyLinkage=*/false);
 }
 
 void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD,
@@ -2913,7 +2942,8 @@
           const ThunkInfo &Thunk = VTableThunks[NextVTableThunkIndex].second;
         
           Init = CGM.GetAddrOfThunk(GD, Thunk);
-        
+          MaybeEmitThunkAvailableExternally(GD, Thunk);
+
           NextVTableThunkIndex++;
         } else {
           const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVTable(GD);

Modified: cfe/trunk/lib/CodeGen/CGVTables.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.h?rev=124984&r1=124983&r2=124984&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGVTables.h (original)
+++ cfe/trunk/lib/CodeGen/CGVTables.h Sun Feb  6 12:31:40 2011
@@ -183,8 +183,15 @@
   void ComputeMethodVTableIndices(const CXXRecordDecl *RD);
 
   /// EmitThunk - Emit a single thunk.
-  void EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk);
-  
+  void EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk, 
+                 bool UseAvailableExternallyLinkage);
+
+  /// MaybeEmitThunkAvailableExternally - Try to emit the given thunk with
+  /// available_externally linkage to allow for inlining of thunks.
+  /// This will be done iff optimizations are enabled and the member function
+  /// doesn't contain any incomplete types.
+  void MaybeEmitThunkAvailableExternally(GlobalDecl GD, const ThunkInfo &Thunk);
+
   /// ComputeVTableRelatedInformation - Compute and store all vtable related
   /// information (vtable layout, vbase offset offsets, thunks etc) for the
   /// given record decl.

Added: cfe/trunk/test/CodeGenCXX/thunks-available-externally.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/thunks-available-externally.cpp?rev=124984&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/thunks-available-externally.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/thunks-available-externally.cpp Sun Feb  6 12:31:40 2011
@@ -0,0 +1,70 @@
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -O3 -o - | FileCheck %s
+
+// Check that we don't assert on this case.
+namespace Test1 {
+
+struct Incomplete;
+
+struct A {
+  virtual void f();
+  virtual void g(Incomplete);
+  virtual void h();
+  virtual void i();
+  int a;
+};
+
+struct B {
+  virtual void f();
+  virtual void g(Incomplete);
+  virtual void h();
+  virtual void i();
+  int b;
+};
+
+struct C : A, B {
+  C();
+
+  virtual void f();
+  virtual void g(Incomplete);
+  virtual void h();
+  virtual void i();
+};
+
+void C::h() { }
+
+C::C() { }
+
+void C::i() { }
+
+}
+
+namespace Test2 {
+
+struct A {
+  virtual void f();
+  int a;
+};
+
+struct B {
+  virtual void f();
+  int b;
+};
+
+struct C : A, B {
+  virtual void f();
+};
+
+static void f(B* b) {
+  b->f();
+}
+
+// CHECK: define void @_ZN5Test21fEv()
+// CHECK: call void @_ZN5Test21C1fEv
+// CHECK: ret void
+// CHECK: define available_externally void @_ZThn16_N5Test21C1fEv
+void f() {
+  C c;
+  f(&c);
+}
+
+}





More information about the cfe-commits mailing list