[PATCH] CodeGen: Emit globals with a constant initializer but no definition as available_externally.
Benjamin Kramer
benny.kra at gmail.com
Thu Oct 24 00:19:43 PDT 2013
Add some clarification and address review comments.
Hi rjmccall, rsmith,
http://llvm-reviews.chandlerc.com/D1982
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D1982?vs=5049&id=5114#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
@@ -1275,6 +1275,16 @@
return !isTriviallyRecursive(F);
}
+bool CodeGenModule::shouldEmitGlobalVariable(const VarDecl *VD) {
+ if (GetLLVMLinkageVarDefinition(VD, /*isConstant=*/true) ==
+ llvm::Function::AvailableExternallyLinkage) {
+ assert(isTypeConstant(D->getType(), /*ExcludeCtor=*/true) &&
+ "available_externally variable should be constant!");
+ return CodeGenOpts.OptimizationLevel != 0;
+ }
+ return true;
+}
+
/// 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()
@@ -1325,8 +1335,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()");
}
@@ -1569,6 +1584,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())
@@ -1851,6 +1876,16 @@
llvm::GlobalValue::LinkageTypes
CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant) {
+ // Check for definitionless vars. We can emit them with available_externally
+ // linkage. We check this before calling GetGVALinkageForVariable because it
+ // can happen for explicit template instantiations that would cause an
+ // assertion failure otherwise.
+ 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
@@ -390,6 +390,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.3.patch
Type: text/x-patch
Size: 4043 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131024/9ad9ec22/attachment.bin>
More information about the cfe-commits
mailing list