From: Duncan P. N. Exon Smith Date: Wed, 26 Aug 2015 22:50:16 +0000 (+0000) Subject: DI: Make Subprogram definitions 'distinct' X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=9f0965e28b2fb66194283aa9fbf53466d303857f;p=oota-llvm.git DI: Make Subprogram definitions 'distinct' Change `DIBuilder` always to produce 'distinct' nodes when creating `DISubprogram` definitions. I measured a ~5% memory improvement in the link step (of ld64) when using `-flto -g`. `DISubprogram`s are used in two ways in the debug info graph. Some are definitions, point at actual functions, and can't really be shared between compile units. With full debug info, these point down at their variables, forming uniquing cycles. These uniquing cycles are expensive to link between modules, since all unique nodes that reference them transitively need to be duplicated (see commit message for r244181 for more details). Others are declarations, primarily used for member functions in the type hierarchy. Definitions never show up there; instead, a definition points at its corresponding declaration node. I started by making all subprograms 'distinct'. However, that was too big a hammer: memory usage *increased* ~5% (net increase vs. this patch of ~10%) because the 'distinct' declarations undermine LTO type uniquing. This is a targeted fix for the definitions (where uniquing is an observable problem). A couple of notes: - There's an accompanying commit to update IRGen testcases in clang. - ^ That's what I'm using to test this commit. - In a follow-up, I'll change the verifier to require 'distinct' on definitions and add an upgrade to `BitcodeReader`. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@246098 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp index 3e5a50a8952..d1257ce78df 100644 --- a/lib/IR/DIBuilder.cpp +++ b/lib/IR/DIBuilder.cpp @@ -675,6 +675,13 @@ DISubprogram *DIBuilder::createFunction(DIScopeRef Context, StringRef Name, Flags, isOptimized, Fn, TParams, Decl); } +template +static DISubprogram *getSubprogram(bool IsDistinct, Ts &&... Args) { + if (IsDistinct) + return DISubprogram::getDistinct(std::forward(Args)...); + return DISubprogram::get(std::forward(Args)...); +} + DISubprogram *DIBuilder::createFunction(DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DISubroutineType *Ty, @@ -684,12 +691,13 @@ DISubprogram *DIBuilder::createFunction(DIScope *Context, StringRef Name, MDNode *TParams, MDNode *Decl) { assert(Ty->getTag() == dwarf::DW_TAG_subroutine_type && "function types should be subroutines"); - auto *Node = DISubprogram::get( - VMContext, DIScopeRef::get(getNonCompileUnitScope(Context)), Name, - LinkageName, File, LineNo, Ty, isLocalToUnit, isDefinition, ScopeLine, - nullptr, 0, 0, Flags, isOptimized, Fn, cast_or_null(TParams), - cast_or_null(Decl), - MDTuple::getTemporary(VMContext, None).release()); + auto *Node = getSubprogram(/* IsDistinct = */ isDefinition, VMContext, + DIScopeRef::get(getNonCompileUnitScope(Context)), + Name, LinkageName, File, LineNo, Ty, isLocalToUnit, + isDefinition, ScopeLine, nullptr, 0, 0, Flags, + isOptimized, Fn, cast_or_null(TParams), + cast_or_null(Decl), + MDTuple::getTemporary(VMContext, None).release()); if (isDefinition) AllSubprograms.push_back(Node); @@ -723,11 +731,12 @@ DIBuilder::createMethod(DIScope *Context, StringRef Name, StringRef LinkageName, "Methods should have both a Context and a context that isn't " "the compile unit."); // FIXME: Do we want to use different scope/lines? - auto *SP = DISubprogram::get( - VMContext, DIScopeRef::get(cast(Context)), Name, LinkageName, F, - LineNo, Ty, isLocalToUnit, isDefinition, LineNo, - DITypeRef::get(VTableHolder), VK, VIndex, Flags, isOptimized, Fn, - cast_or_null(TParam), nullptr, nullptr); + auto *SP = getSubprogram(/* IsDistinct = */ isDefinition, VMContext, + DIScopeRef::get(cast(Context)), Name, + LinkageName, F, LineNo, Ty, isLocalToUnit, + isDefinition, LineNo, DITypeRef::get(VTableHolder), + VK, VIndex, Flags, isOptimized, Fn, + cast_or_null(TParam), nullptr, nullptr); if (isDefinition) AllSubprograms.push_back(SP);