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

Benjamin Kramer benny.kra at gmail.com
Sun Oct 20 04:31:59 PDT 2013


  Fixed a crasher during selfhost and tightened up asserts.

Hi rjmccall, rsmith,

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

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D1982?vs=5046&id=5049#toc

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,13 @@
     return EmitGlobalFunctionDefinition(GD);
   }
   
-  if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    // At -O0, don't generate IR for vars with available_externally linkage.
+    if (!shouldEmitGlobalVariable(VD))
+      return;
+
     return EmitGlobalVarDefinition(VD);
+  }
   
   llvm_unreachable("Invalid argument to EmitGlobalDefinition()");
 }
@@ -1534,6 +1546,16 @@
         CXXThreadLocals.push_back(std::make_pair(D, GV));
       setTLSMode(GV, *D);
     }
+
+    // If the variable has an initializer but no definition we can emit it with
+    // available_externally linkage.
+    if (D->hasInit() && !D->hasDefinition(Context)) {
+      assert(!D->getType().isVolatileQualified());
+      assert(GetLLVMLinkageVarDefinition(D, /*isConstant=*/true) ==
+                 llvm::GlobalValue::AvailableExternallyLinkage &&
+             "Global variable should be available_externally!");
+      DeferredDeclsToEmit.push_back(D);
+    }
   }
 
   if (AddrSpace != Ty->getAddressSpace())
@@ -1816,6 +1838,14 @@
 
 llvm::GlobalValue::LinkageTypes
 CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant) {
+  // Check for definitionless vars. We can emit them with available_externally
+  // linkage.
+  if (D->hasInit() && !D->hasDefinition(Context)) {
+    assert(isTypeConstant(D->getType(), /*ExcludeCtor=*/true) &&
+           "Variable with init but no definition should be constant!");
+    return llvm::GlobalValue::AvailableExternallyLinkage;
+  }
+
   GVALinkage Linkage = getContext().GetGVALinkageForVariable(D);
   if (Linkage == GVA_Internal)
     return llvm::Function::InternalLinkage;
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.2.patch
Type: text/x-patch
Size: 3730 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131020/192742cc/attachment.bin>


More information about the cfe-commits mailing list