From: Rafael Espindola Date: Mon, 9 Dec 2013 14:59:08 +0000 (+0000) Subject: When we decide to output a deferred decl, remember the llvm GlobalValue. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9c8da1b492c33dce3367c7edd3d3bcf1560535e9;p=clang When we decide to output a deferred decl, remember the llvm GlobalValue. We can reuse it to avoid a DenseMap+StringMap lookup to find if it was already emitted or not. This fixes a 2010 TODO. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@196785 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 4f7886b34d..583ee88bd6 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -233,6 +233,10 @@ void CodeGenModule::checkAliases() { } } +void CodeGenModule::clear() { + DeferredDeclsToEmit.clear(); +} + void CodeGenModule::Release() { EmitDeferred(); applyReplacements(); @@ -1002,22 +1006,19 @@ void CodeGenModule::EmitDeferred() { // Stop if we're out of both deferred v-tables and deferred declarations. if (DeferredDeclsToEmit.empty()) break; - GlobalDecl D = DeferredDeclsToEmit.back(); + DeferredGlobal &G = DeferredDeclsToEmit.back(); + GlobalDecl D = G.GD; + llvm::GlobalValue *GV = G.GV; DeferredDeclsToEmit.pop_back(); + assert(GV == GetGlobalValue(getMangledName(D))); // Check to see if we've already emitted this. This is necessary // for a couple of reasons: first, decls can end up in the // deferred-decls queue multiple times, and second, decls can end // up with definitions in unusual ways (e.g. by an extern inline // function acquiring a strong function redefinition). Just // ignore these cases. - // - // TODO: That said, looking this up multiple times is very wasteful. - StringRef Name = getMangledName(D); - llvm::GlobalValue *CGRef = GetGlobalValue(Name); - assert(CGRef && "Deferred decl wasn't referenced?"); - - if (!CGRef->isDeclaration()) + if(!GV->isDeclaration()) continue; // Otherwise, emit the definition and move on to the next one. @@ -1226,8 +1227,8 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // If the value has already been used, add it directly to the // DeferredDeclsToEmit list. StringRef MangledName = getMangledName(GD); - if (GetGlobalValue(MangledName)) - DeferredDeclsToEmit.push_back(GD); + if (llvm::GlobalValue *GV = GetGlobalValue(MangledName)) + addDeferredDeclToEmit(GV, GD); else { // Otherwise, remember that we saw a deferred decl with this name. The // first use of the mangled name will cause it to move into @@ -1428,7 +1429,7 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName, if (D && isa(D) && getCXXABI().useThunkForDtorVariant(cast(D), GD.getDtorType())) - DeferredDeclsToEmit.push_back(GD); + addDeferredDeclToEmit(F, GD); // This is the first use or definition of a mangled name. If there is a // deferred decl with this name, remember that we need to emit it at the end @@ -1438,7 +1439,7 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName, // Move the potentially referenced deferred decl to the // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we // don't need it anymore). - DeferredDeclsToEmit.push_back(DDI->second); + addDeferredDeclToEmit(F, DDI->second); DeferredDecls.erase(DDI); // Otherwise, if this is a sized deallocation function, emit a weak @@ -1446,7 +1447,7 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName, // for it at the end of the translation unit. } else if (D && cast(D) ->getCorrespondingUnsizedGlobalDeallocationFunction()) { - DeferredDeclsToEmit.push_back(GD); + addDeferredDeclToEmit(F, GD); // Otherwise, there are cases we have to worry about where we're // using a declaration for which we must emit a definition but where @@ -1469,10 +1470,10 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName, if (FD->isImplicit() && !ForVTable) { assert(FD->isUsed() && "Sema didn't mark implicit function as used!"); - DeferredDeclsToEmit.push_back(GD.getWithDecl(FD)); + addDeferredDeclToEmit(F, GD.getWithDecl(FD)); break; } else if (FD->doesThisDeclarationHaveABody()) { - DeferredDeclsToEmit.push_back(GD.getWithDecl(FD)); + addDeferredDeclToEmit(F, GD.getWithDecl(FD)); break; } } @@ -1574,6 +1575,13 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, return llvm::ConstantExpr::getBitCast(Entry, Ty); } + unsigned AddrSpace = GetGlobalVarAddressSpace(D, Ty->getAddressSpace()); + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(getModule(), Ty->getElementType(), false, + llvm::GlobalValue::ExternalLinkage, + 0, MangledName, 0, + llvm::GlobalVariable::NotThreadLocal, AddrSpace); + // This is the first use or definition of a mangled name. If there is a // deferred decl with this name, remember that we need to emit it at the end // of the file. @@ -1581,17 +1589,10 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, if (DDI != DeferredDecls.end()) { // Move the potentially referenced deferred decl to the DeferredDeclsToEmit // list, and remove it from DeferredDecls (since we don't need it anymore). - DeferredDeclsToEmit.push_back(DDI->second); + addDeferredDeclToEmit(GV, DDI->second); DeferredDecls.erase(DDI); } - unsigned AddrSpace = GetGlobalVarAddressSpace(D, Ty->getAddressSpace()); - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(getModule(), Ty->getElementType(), false, - llvm::GlobalValue::ExternalLinkage, - 0, MangledName, 0, - llvm::GlobalVariable::NotThreadLocal, AddrSpace); - // Handle things which are present even on external declarations. if (D) { // FIXME: This code is overly simple and should be merged with other global diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 098aa03552..ec61c596a0 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -273,7 +273,15 @@ class CodeGenModule : public CodeGenTypeCache { /// DeferredDeclsToEmit - This is a list of deferred decls which we have seen /// that *are* actually referenced. These get code generated when the module /// is done. - std::vector DeferredDeclsToEmit; + struct DeferredGlobal { + DeferredGlobal(llvm::GlobalValue *GV, GlobalDecl GD) : GV(GV), GD(GD) {} + llvm::AssertingVH GV; + GlobalDecl GD; + }; + std::vector DeferredDeclsToEmit; + void addDeferredDeclToEmit(llvm::GlobalValue *GV, GlobalDecl GD) { + DeferredDeclsToEmit.push_back(DeferredGlobal(GV, GD)); + } /// List of alias we have emitted. Used to make sure that what they point to /// is defined once we get to the end of the of the translation unit. @@ -433,6 +441,8 @@ public: ~CodeGenModule(); + void clear(); + /// Release - Finalize LLVM code generation. void Release(); diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp index bc7acbc39c..6b81ce7fb0 100644 --- a/lib/CodeGen/ModuleBuilder.cpp +++ b/lib/CodeGen/ModuleBuilder.cpp @@ -117,6 +117,8 @@ namespace { virtual void HandleTranslationUnit(ASTContext &Ctx) { if (Diags.hasErrorOccurred()) { + if (Builder) + Builder->clear(); M.reset(); return; }