[PATCH] CodeGen: Emit globals with a constant initializer but no definition as available_externally.

Benjamin Kramer benny.kra at gmail.com
Sat Oct 19 08:49:04 PDT 2013


Hi rjmccall, rsmith,

This can happen with static const members (PR17612). It has the advantage
over just making constant folding smarter that it also enables the optimizer
to fold more complicated patterns, such as passing the static const member
by reference.

We only do this at -O1 or higher.

http://llvm-reviews.chandlerc.com/D1982

Files:
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenModule.h
  test/CodeGenCXX/constexpr-available-externally.cpp

Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -1240,6 +1240,13 @@
   return !isTriviallyRecursive(F);
 }
 
+bool CodeGenModule::shouldEmitGlobalVariable(const VarDecl *VD) {
+  if (GetLLVMLinkageVarDefinition(VD, /*isConstant=*/true) !=
+      llvm::Function::AvailableExternallyLinkage)
+    return true;
+  return CodeGenOpts.OptimizationLevel != 0;
+}
+
 /// If the type for the method's class was generated by
 /// CGDebugInfo::createContextChain(), the cache contains only a
 /// limited DIType without any declarations. Since EmitFunctionStart()
@@ -1290,8 +1297,12 @@
     return EmitGlobalFunctionDefinition(GD);
   }
   
-  if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    if (!shouldEmitGlobalVariable(VD))
+      return;
+
     return EmitGlobalVarDefinition(VD);
+  }
   
   llvm_unreachable("Invalid argument to EmitGlobalDefinition()");
 }
@@ -1534,6 +1545,14 @@
         CXXThreadLocals.push_back(std::make_pair(D, GV));
       setTLSMode(GV, *D);
     }
+
+    if (D->hasInit() && !D->hasDefinition(Context) &&
+        isTypeConstant(D->getType(), /*ExcludeCtor=*/true)) {
+      assert(GetLLVMLinkageVarDefinition(D, /*isConstant=*/true) ==
+                 llvm::GlobalValue::AvailableExternallyLinkage &&
+             "Global variable should be available_externally!");
+      DeferredDeclsToEmit.push_back(D);
+    }
   }
 
   if (AddrSpace != Ty->getAddressSpace())
@@ -1852,6 +1871,10 @@
     // Itanium-specified entry point, which has the normal linkage of the
     // variable.
     return llvm::GlobalValue::InternalLinkage;
+  else if (D->hasInit() && !D->hasDefinition(Context) &&
+           isTypeConstant(D->getType(), /*ExcludeCtor=*/true))
+    return llvm::GlobalValue::AvailableExternallyLinkage;
+
   return llvm::GlobalVariable::ExternalLinkage;
 }
 
Index: lib/CodeGen/CodeGenModule.h
===================================================================
--- lib/CodeGen/CodeGenModule.h
+++ lib/CodeGen/CodeGenModule.h
@@ -386,6 +386,7 @@
 
   bool isTriviallyRecursive(const FunctionDecl *F);
   bool shouldEmitFunction(GlobalDecl GD);
+  bool shouldEmitGlobalVariable(const VarDecl *D);
 
   /// @name Cache for Blocks Runtime Globals
   /// @{
Index: test/CodeGenCXX/constexpr-available-externally.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/constexpr-available-externally.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -emit-llvm -O1 -std=c++11 -disable-llvm-optzns -o - %s | FileCheck %s
+
+// PR17612
+// CHECK: @_ZN6Object3fooE = available_externally constant %struct.Literal { i32 1 }
+// CHECK: @_ZN6Object3barE = available_externally constant i32 42
+
+struct Literal {
+  int i;
+  constexpr Literal(int i) : i(i) {}
+};
+
+struct Object {
+  static constexpr Literal foo = Literal(1);
+  static const int bar = 42;
+};
+
+void bar(const int &);
+
+int f() {
+  Literal l = Object::foo;
+  bar(Object::bar);
+  return l.i;
+
+// CHECK-LABEL: @_Z1fv
+// CHECK: call void @llvm.memcpy{{[^(]*}}(i8* %{{[^,]*}}, i8* bitcast (%struct.Literal* @_ZN6Object3fooE to i8*)
+// CHECK: call void @_Z3barRKi(i32* @_ZN6Object3barE)
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1982.1.patch
Type: text/x-patch
Size: 3310 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131019/4ef0f2b7/attachment.bin>


More information about the cfe-commits mailing list