r234961 - Move the logic to avoid double global emission from Sema to CodeGen
Reid Kleckner
reid at kleckner.net
Tue Apr 14 18:08:07 PDT 2015
Author: rnk
Date: Tue Apr 14 20:08:06 2015
New Revision: 234961
URL: http://llvm.org/viewvc/llvm-project?rev=234961&view=rev
Log:
Move the logic to avoid double global emission from Sema to CodeGen
Reverts the code changes from r234675 but keeps the test case.
We were already maintaining a DenseMap of globals with dynamic
initializers anyway.
Fixes the test case from PR23234.
Added:
cfe/trunk/test/CodeGenCXX/auto-variable-template.cpp
Modified:
cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.h
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=234961&r1=234960&r2=234961&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Tue Apr 14 20:08:06 2015
@@ -298,6 +298,11 @@ void
CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
llvm::GlobalVariable *Addr,
bool PerformInit) {
+ // Check if we've already initialized this decl.
+ auto I = DelayedCXXInitPosition.find(D);
+ if (I != DelayedCXXInitPosition.end() && I->second == ~0U)
+ return;
+
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
SmallString<256> FnName;
{
@@ -327,11 +332,9 @@ CodeGenModule::EmitCXXGlobalVarDeclInitF
CXXThreadLocalInitVars.push_back(Addr);
} else if (PerformInit && ISA) {
EmitPointerToInitFunc(D, Addr, Fn, ISA);
- DelayedCXXInitPosition.erase(D);
} else if (auto *IPA = D->getAttr<InitPriorityAttr>()) {
OrderGlobalInits Key(IPA->getPriority(), PrioritizedCXXGlobalInits.size());
PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
- DelayedCXXInitPosition.erase(D);
} else if (isTemplateInstantiation(D->getTemplateSpecializationKind())) {
// C++ [basic.start.init]p2:
// Definitions of explicitly specialized class template static data
@@ -346,24 +349,24 @@ CodeGenModule::EmitCXXGlobalVarDeclInitF
// minor startup time optimization. In the MS C++ ABI, there are no guard
// variables, so this COMDAT key is required for correctness.
AddGlobalCtor(Fn, 65535, COMDATKey);
- DelayedCXXInitPosition.erase(D);
} else if (D->hasAttr<SelectAnyAttr>()) {
// SelectAny globals will be comdat-folded. Put the initializer into a
// COMDAT group associated with the global, so the initializers get folded
// too.
AddGlobalCtor(Fn, 65535, COMDATKey);
- DelayedCXXInitPosition.erase(D);
} else {
- llvm::DenseMap<const Decl *, unsigned>::iterator I =
- DelayedCXXInitPosition.find(D);
+ I = DelayedCXXInitPosition.find(D); // Re-do lookup in case of re-hash.
if (I == DelayedCXXInitPosition.end()) {
CXXGlobalInits.push_back(Fn);
- } else {
- assert(CXXGlobalInits[I->second] == nullptr);
+ } else if (I->second != ~0U) {
+ assert(I->second < CXXGlobalInits.size() &&
+ CXXGlobalInits[I->second] == nullptr);
CXXGlobalInits[I->second] = Fn;
- DelayedCXXInitPosition.erase(I);
}
}
+
+ // Remember that we already emitted the initializer for this global.
+ DelayedCXXInitPosition[D] = ~0U;
}
void CodeGenModule::EmitCXXThreadLocalInitFunc() {
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=234961&r1=234960&r2=234961&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Tue Apr 14 20:08:06 2015
@@ -400,7 +400,8 @@ private:
/// When a C++ decl with an initializer is deferred, null is
/// appended to CXXGlobalInits, and the index of that null is placed
/// here so that the initializer will be performed in the correct
- /// order.
+ /// order. Once the decl is emitted, the index is replaced with ~0U to ensure
+ /// that we don't re-emit the initializer.
llvm::DenseMap<const Decl*, unsigned> DelayedCXXInitPosition;
typedef std::pair<OrderGlobalInits, llvm::Function*> GlobalInitData;
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=234961&r1=234960&r2=234961&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Apr 14 20:08:06 2015
@@ -3865,17 +3865,6 @@ void Sema::InstantiateVariableDefinition
if (TSK == TSK_ExplicitInstantiationDeclaration)
return;
- // We may be explicitly instantiating something we've already implicitly
- // instantiated.
- VarDecl *InstantiatedDef = Var->getDefinition();
- if (InstantiatedDef)
- InstantiatedDef->setTemplateSpecializationKind(TSK, PointOfInstantiation);
-
- // If we've already instantiated the definition and we're not
- // re-instantiating it explicitly, we don't need to do anything.
- if (InstantiatedDef && TSK != TSK_ExplicitInstantiationDefinition)
- return;
-
// Make sure to pass the instantiated variable to the consumer at the end.
struct PassToConsumerRAII {
ASTConsumer &Consumer;
@@ -3889,10 +3878,14 @@ void Sema::InstantiateVariableDefinition
}
} PassToConsumerRAII(Consumer, Var);
- // If we already implicitly instantiated this, just let the consumer know that
- // it needs to handle an explicit instantiation now.
- if (InstantiatedDef && TSK == TSK_ExplicitInstantiationDefinition)
+ // If we already have a definition, we're done.
+ if (VarDecl *Def = Var->getDefinition()) {
+ // We may be explicitly instantiating something we've already implicitly
+ // instantiated.
+ Def->setTemplateSpecializationKind(Var->getTemplateSpecializationKind(),
+ PointOfInstantiation);
return;
+ }
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
if (Inst.isInvalid())
Added: cfe/trunk/test/CodeGenCXX/auto-variable-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/auto-variable-template.cpp?rev=234961&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/auto-variable-template.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/auto-variable-template.cpp Tue Apr 14 20:08:06 2015
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -std=c++14 %s -triple=x86_64-linux -emit-llvm -o - | FileCheck %s
+
+struct f {
+ void operator()() const {}
+};
+
+template <typename T> auto vtemplate = f{};
+
+int main() { vtemplate<int>(); }
+
+// CHECK: @_Z9vtemplateIiE = linkonce_odr global %struct.f undef, comdat
+
+// CHECK: define i32 @main()
+// CHECK: call void @_ZNK1fclEv(%struct.f* @_Z9vtemplateIiE)
More information about the cfe-commits
mailing list