[llvm] r218129 - Omit DW_TAG_subprograms for subprograms without inlined subroutines when producing -gmlt data

Alexey Samsonov vonosmas at gmail.com
Fri Sep 19 18:03:02 PDT 2014


Thanks, this is awesome! Note that we might want to keep CU ranges
emission, as it speeds up address symbolizing: it's far quicker to scan CU
ranges and build address->CU relation, than load and parse all the
.debug_line section.

On Fri, Sep 19, 2014 at 10:03 AM, David Blaikie <dblaikie at gmail.com> wrote:

> Author: dblaikie
> Date: Fri Sep 19 12:03:16 2014
> New Revision: 218129
>
> URL: http://llvm.org/viewvc/llvm-project?rev=218129&view=rev
> Log:
> Omit DW_TAG_subprograms for subprograms without inlined subroutines when
> producing -gmlt data
>
> To reduce the size of -gmlt data, skip the subprograms without any
> inlined subroutines. Since we've now got the ability to make these
> determinations in the backend (funnily enough - we added the flag so we
> wouldn't produce ranges under -gmlt, but with this change we use the
> flag, but go back to producing ranges under -gmlt).
>
> Instead, just produce CU ranges to inform the consumer which parts of
> the code are described by this CU's line table. Tools could inspect the
> line table directly to compute the range, but the CU ranges only seem to
> be about 0.5% of object/executable size, so I'm not too worried about
> teaching llvm-symbolizer that trick just yet - it's certainly a possible
> piece of future work.
>
> Update an llvm-symbolizer test just to demonstrate that this schema is
> acceptable there (if it wasn't, the compiler-rt tests would catch this,
> but good to have an in-llvm-tree test for llvm-symbolizer's behavior
> here)
>
> Building the clang binary with -gmlt with this patch reduces the total
> size of object files by 5.1% (5.56% without ranges) without compression
> and the executable by 4.37% (4.75% without ranges).
>
> Modified:
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
>     llvm/trunk/test/DebugInfo/Inputs/dwarfdump-inl-test.elf-x86-64
>     llvm/trunk/test/DebugInfo/gmlt.ll
>     llvm/trunk/test/DebugInfo/llvm-symbolizer.test
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=218129&r1=218128&r2=218129&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Fri Sep 19 12:03:16
> 2014
> @@ -856,12 +856,14 @@ void DwarfDebug::finishSubprogramDefinit
>            // If this subprogram has an abstract definition, reference that
>            SPCU->addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE);
>        } else {
> -        if (!D)
> +        if (!D && TheCU.getEmissionKind() != DIBuilder::LineTablesOnly)
>            // Lazily construct the subprogram if we didn't see either
> concrete or
> -          // inlined versions during codegen.
> +          // inlined versions during codegen. (except in -gmlt ^ where we
> want
> +          // to omit these entirely)
>            D = SPCU->getOrCreateSubprogramDIE(SP);
> -        // And attach the attributes
> -        SPCU->applySubprogramAttributesToDefinition(SP, *D);
> +        if (D)
> +          // And attach the attributes
> +          SPCU->applySubprogramAttributesToDefinition(SP, *D);
>        }
>      }
>    }
> @@ -1690,6 +1692,24 @@ void DwarfDebug::endFunction(const Machi
>    LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
>    DwarfCompileUnit &TheCU = *SPMap.lookup(FnScope->getScopeNode());
>
> +  // Add the range of this function to the list of ranges for the CU.
> +  TheCU.addRange(RangeSpan(FunctionBeginSym, FunctionEndSym));
> +
> +  // Under -gmlt, skip building the subprogram if there are no inlined
> +  // subroutines inside it.
> +  if (TheCU.getCUNode().getEmissionKind() == DIBuilder::LineTablesOnly &&
> +      LScopes.getAbstractScopesList().empty()) {
> +    assert(ScopeVariables.empty());
> +    assert(CurrentFnArguments.empty());
> +    assert(DbgValues.empty());
> +    assert(AbstractVariables.empty());
> +    LabelsBeforeInsn.clear();
> +    LabelsAfterInsn.clear();
> +    PrevLabel = nullptr;
> +    CurFn = nullptr;
> +    return;
> +  }
> +
>    // Construct abstract scopes.
>    for (LexicalScope *AScope : LScopes.getAbstractScopesList()) {
>      DISubprogram SP(AScope->getScopeNode());
> @@ -1710,10 +1730,6 @@ void DwarfDebug::endFunction(const Machi
>    if (!CurFn->getTarget().Options.DisableFramePointerElim(*CurFn))
>      TheCU.addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr);
>
> -  // Add the range of this function to the list of ranges for the CU.
> -  RangeSpan Span(FunctionBeginSym, FunctionEndSym);
> -  TheCU.addRange(std::move(Span));
> -
>    // Clear debug info
>    // Ownership of DbgVariables is a bit subtle - ScopeVariables owns all
> the
>    // DbgVariables except those that are also in AbstractVariables (since
> they
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=218129&r1=218128&r2=218129&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp Fri Sep 19 12:03:16
> 2014
> @@ -2049,23 +2049,20 @@ void DwarfUnit::emitHeader(const MCSymbo
>  }
>
>  void DwarfCompileUnit::addRange(RangeSpan Range) {
> -  // Only add a range for this unit if we're emitting full debug.
> -  if (getCUNode().getEmissionKind() == DIBuilder::FullDebug) {
> -    bool SameAsPrevCU = this == DD->getPrevCU();
> -    DD->setPrevCU(this);
> -    // If we have no current ranges just add the range and return,
> otherwise,
> -    // check the current section and CU against the previous section and
> CU we
> -    // emitted into and the subprogram was contained within. If these are
> the
> -    // same then extend our current range, otherwise add this as a new
> range.
> -    if (CURanges.empty() || !SameAsPrevCU ||
> -        (&CURanges.back().getEnd()->getSection() !=
> -         &Range.getEnd()->getSection())) {
> -      CURanges.push_back(Range);
> -      return;
> -    }
> -
> -    CURanges.back().setEnd(Range.getEnd());
> +  bool SameAsPrevCU = this == DD->getPrevCU();
> +  DD->setPrevCU(this);
> +  // If we have no current ranges just add the range and return,
> otherwise,
> +  // check the current section and CU against the previous section and CU
> we
> +  // emitted into and the subprogram was contained within. If these are
> the
> +  // same then extend our current range, otherwise add this as a new
> range.
> +  if (CURanges.empty() || !SameAsPrevCU ||
> +      (&CURanges.back().getEnd()->getSection() !=
> +       &Range.getEnd()->getSection())) {
> +    CURanges.push_back(Range);
> +    return;
>    }
> +
> +  CURanges.back().setEnd(Range.getEnd());
>  }
>
>  void DwarfCompileUnit::initStmtList(MCSymbol *DwarfLineSectionSym) {
>
> Modified: llvm/trunk/test/DebugInfo/Inputs/dwarfdump-inl-test.elf-x86-64
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/Inputs/dwarfdump-inl-test.elf-x86-64?rev=218129&r1=218128&r2=218129&view=diff
>
> ==============================================================================
> Binary files - no diff available.
>
> Modified: llvm/trunk/test/DebugInfo/gmlt.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/gmlt.ll?rev=218129&r1=218128&r2=218129&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/gmlt.ll (original)
> +++ llvm/trunk/test/DebugInfo/gmlt.ll Fri Sep 19 12:03:16 2014
> @@ -1,33 +1,72 @@
>  ; REQUIRES: object-emission
>  ; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump - | FileCheck %s
>
> -; Generated from the following source compiled with clang -gmlt:
> -; void f1(void) {}
> -; void f2(void) __attribute__((section("__TEXT,__bar"))) {}
> +; Generated from the following source compiled with clang++ -gmlt:
> +; void f1() {}
> +; void __attribute__((section("__TEXT,__bar"))) f2() {}
> +; void __attribute__((always_inline)) f3() { f1(); }
> +; void f4() { f3(); }
>
>  ; Check that
> -;  * -gmlt ('Emission Kind' of 'LineTablesOnly' in the CU debug info
> metadata)
> -;    doesn't produce ranges.
> -;  * if no ranges are produced, no debug_ranges list (not even an empty
> one) is
> -;    emitted.
> -
> -; -gmlt means no DW_AT_ranges on the CU, even though there are parts of
> the CU
> -; in different sections and this would normally necessitate a DW_AT_ranges
> -; attribute on the CU.
> +;  * -gmlt includes no DW_TAG_subprograms for subprograms without inlined
> +;    subroutines.
> +;  * yet still produces DW_AT_ranges and a range list in debug_ranges that
> +;    describes those subprograms
> +
>  ; CHECK: DW_TAG_compile_unit
> -; CHECK-NOT: DW_AT_ranges
> +; CHECK:   DW_AT_ranges [DW_FORM_sec_offset] (0x00000000)
>  ; CHECK-NOT: {{DW_TAG|NULL}}
> +
> +
> +; FIXME: Emitting separate abstract definitions is inefficient when we
> could
> +; just attach the DW_AT_name to the inlined_subroutine directly. Except
> that
> +; would produce many string relocations. Implement string indexing in the
> +; skeleton CU to address the relocation problem, then remove abstract
> +; definitions from -gmlt here.
> +
> +; CHECK: [[F3_ABS_DEF:.*]]:  DW_TAG_subprogram
> +; CHECK-NEXT:     DW_AT_name {{.*}} "f3"
> +
> +; FIXME: We don't really need DW_AT_inline, consumers can ignore this due
> to
> +; the absence of high_pc/low_pc/ranges and know that they just need it for
> +; retrieving the name of a concrete inlined instance
> +
> +; CHECK-NEXT:     DW_AT_inline
> +; CHECK-NOT: {{DW_TAG|DW_AT|NULL}}
> +
>  ; Check that we only provide the minimal attributes on a subprogram to
> save space.
>  ; CHECK:   DW_TAG_subprogram
>  ; CHECK-NEXT:     DW_AT_low_pc
>  ; CHECK-NEXT:     DW_AT_high_pc
>  ; CHECK-NEXT:     DW_AT_name
> -; CHECK-NOT: DW_AT
> -; CHECK: {{DW_TAG|NULL}}
> +; CHECK-NOT: {{DW_TAG|DW_AT}}
> +; CHECK:     DW_TAG_inlined_subroutine
> +
> +; As mentioned above - replace DW_AT_abstract_origin with DW_AT_name to
> save
> +; space once we have support for string indexing in non-dwo sections
>
> -; FIXME: We probably want to avoid printing out anything if the section
> isn't there.
> +; CHECK-NEXT:       DW_AT_abstract_origin {{.*}} {[[F3_ABS_DEF]]}
> +; CHECK-NEXT:       DW_AT_low_pc
> +; CHECK-NEXT:       DW_AT_high_pc
> +; CHECK-NEXT:       DW_AT_call_file
> +; CHECK-NEXT:       DW_AT_call_line
> +
> +; Make sure we don't have any other subprograms here (subprograms with no
> +; inlined subroutines are omitted by design to save space)
> +
> +; CHECK-NOT: {{DW_TAG|DW_AT}}
> +; CHECK: NULL
> +; CHECK-NOT: {{DW_TAG|DW_AT}}
> +; CHECK: NULL
> +
> +
> +; FIXME: llvm-dwarfdump should detect the relocations here and realize
> that the
> +; first two "end of list" are really just unrelocated values describing
> the two
> +; functions in the CU.
>  ; CHECK: .debug_ranges contents:
> -; CHECK-NOT: 00000000 <End of list>
> +; CHECK: 00000000 <End of list>
> +; CHECK: 00000010 <End of list>
> +; CHECK: 00000020 <End of list>
>
>  ; Check that we don't emit any pubnames or pubtypes under -gmlt
>  ; CHECK: .debug_pubnames contents:
> @@ -37,33 +76,56 @@
>  ; CHECK-NOT: Offset
>
>  ; Function Attrs: nounwind uwtable
> -define void @f1() #0 {
> +define void @_Z2f1v() #0 {
> +entry:
> +  ret void, !dbg !13
> +}
> +
> +; Function Attrs: nounwind uwtable
> +define void @_Z2f2v() #0 section "__TEXT,__bar" {
> +entry:
> +  ret void, !dbg !14
> +}
> +
> +; Function Attrs: alwaysinline nounwind uwtable
> +define void @_Z2f3v() #1 {
>  entry:
> -  ret void, !dbg !11
> +  call void @_Z2f1v(), !dbg !15
> +  ret void, !dbg !16
>  }
>
>  ; Function Attrs: nounwind uwtable
> -define void @f2() #0 section "__TEXT,__bar" {
> +define void @_Z2f4v() #0 {
>  entry:
> -  ret void, !dbg !12
> +  call void @_Z2f1v() #2, !dbg !17
> +  ret void, !dbg !19
>  }
>
>  attributes #0 = { nounwind uwtable "less-precise-fpmad"="false"
> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"
> "no-infs-fp-math"="false" "no-nans-fp-math"="false"
> "stack-protector-buffer-size"="8" "unsafe-fp-math"="false"
> "use-soft-float"="false" }
> +attributes #1 = { alwaysinline nounwind uwtable
> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +attributes #2 = { nounwind }
>
>  !llvm.dbg.cu = !{!0}
> -!llvm.module.flags = !{!8, !9}
> -!llvm.ident = !{!10}
> +!llvm.module.flags = !{!10, !11}
> +!llvm.ident = !{!12}
>
> -!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version
> 3.6.0 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata
> !3, metadata !2, metadata !2, metadata !"", i32 2} ; [ DW_TAG_compile_unit
> ] [/tmp/dbginfo/cu-line-tables.c] [DW_LANG_C99]
> -!1 = metadata !{metadata !"cu-line-tables.c", metadata !"/tmp/dbginfo"}
> +!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version
> 3.6.0 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata
> !3, metadata !2, metadata !2, metadata !"", i32 2} ; [ DW_TAG_compile_unit
> ] [/tmp/dbginfo/gmlt.cpp] [DW_LANG_C_plus_plus]
> +!1 = metadata !{metadata !"gmlt.cpp", metadata !"/tmp/dbginfo"}
>  !2 = metadata !{}
> -!3 = metadata !{metadata !4, metadata !7}
> -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"f1",
> metadata !"f1", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0,
> i32 0, null, i32 256, i1 false, void ()* @f1, null, null, metadata !2, i32
> 1} ; [ DW_TAG_subprogram ] [line 1] [def] [f1]
> -!5 = metadata !{i32 786473, metadata !1}          ; [ DW_TAG_file_type ]
> [/tmp/dbginfo/cu-line-tables.c]
> +!3 = metadata !{metadata !4, metadata !7, metadata !8, metadata !9}
> +!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"f1",
> metadata !"f1", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0,
> i32 0, null, i32 256, i1 false, void ()* @_Z2f1v, null, null, metadata !2,
> i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [f1]
> +!5 = metadata !{i32 786473, metadata !1}          ; [ DW_TAG_file_type ]
> [/tmp/dbginfo/gmlt.cpp]
>  !6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64
> 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [
> DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
> -!7 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"f2",
> metadata !"f2", metadata !"", i32 2, metadata !6, i1 false, i1 true, i32 0,
> i32 0, null, i32 256, i1 false, void ()* @f2, null, null, metadata !2, i32
> 2} ; [ DW_TAG_subprogram ] [line 2] [def] [f2]
> -!8 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
> -!9 = metadata !{i32 2, metadata !"Debug Info Version", i32 1}
> -!10 = metadata !{metadata !"clang version 3.6.0 "}
> -!11 = metadata !{i32 1, i32 16, metadata !4, null}
> -!12 = metadata !{i32 2, i32 48, metadata !7, null}
> +!7 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"f2",
> metadata !"f2", metadata !"", i32 2, metadata !6, i1 false, i1 true, i32 0,
> i32 0, null, i32 256, i1 false, void ()* @_Z2f2v, null, null, metadata !2,
> i32 2} ; [ DW_TAG_subprogram ] [line 2] [def] [f2]
> +!8 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"f3",
> metadata !"f3", metadata !"", i32 3, metadata !6, i1 false, i1 true, i32 0,
> i32 0, null, i32 256, i1 false, void ()* @_Z2f3v, null, null, metadata !2,
> i32 3} ; [ DW_TAG_subprogram ] [line 3] [def] [f3]
> +!9 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"f4",
> metadata !"f4", metadata !"", i32 4, metadata !6, i1 false, i1 true, i32 0,
> i32 0, null, i32 256, i1 false, void ()* @_Z2f4v, null, null, metadata !2,
> i32 4} ; [ DW_TAG_subprogram ] [line 4] [def] [f4]
> +!10 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
> +!11 = metadata !{i32 2, metadata !"Debug Info Version", i32 1}
> +!12 = metadata !{metadata !"clang version 3.6.0 "}
> +!13 = metadata !{i32 1, i32 12, metadata !4, null}
> +!14 = metadata !{i32 2, i32 53, metadata !7, null}
> +!15 = metadata !{i32 3, i32 44, metadata !8, null}
> +!16 = metadata !{i32 3, i32 50, metadata !8, null}
> +!17 = metadata !{i32 3, i32 44, metadata !8, metadata !18}
> +!18 = metadata !{i32 4, i32 13, metadata !9, null}
> +!19 = metadata !{i32 4, i32 19, metadata !9, null}
>
> Modified: llvm/trunk/test/DebugInfo/llvm-symbolizer.test
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/llvm-symbolizer.test?rev=218129&r1=218128&r2=218129&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/llvm-symbolizer.test (original)
> +++ llvm/trunk/test/DebugInfo/llvm-symbolizer.test Fri Sep 19 12:03:16 2014
> @@ -6,9 +6,9 @@ RUN: echo "%p/Inputs/dwarfdump-test.elf-
>  RUN: echo "%p/Inputs/dwarfdump-test2.elf-x86-64 0x4004e8" >> %t.input
>  RUN: echo "%p/Inputs/dwarfdump-test2.elf-x86-64 0x4004f4" >> %t.input
>  RUN: echo "%p/Inputs/dwarfdump-test4.elf-x86-64 0x62c" >> %t.input
> -RUN: echo "%p/Inputs/dwarfdump-inl-test.elf-x86-64 0x710" >> %t.input
> -RUN: echo "%p/Inputs/dwarfdump-inl-test.elf-x86-64 0x7d1" >> %t.input
> -RUN: echo "%p/Inputs/dwarfdump-inl-test.elf-x86-64 0x785" >> %t.input
> +RUN: echo "%p/Inputs/dwarfdump-inl-test.elf-x86-64 0x8dc" >> %t.input
> +RUN: echo "%p/Inputs/dwarfdump-inl-test.elf-x86-64 0xa05" >> %t.input
> +RUN: echo "%p/Inputs/dwarfdump-inl-test.elf-x86-64 0x987" >> %t.input
>  RUN: echo "%p/Inputs/dwarfdump-inl-test.high_pc.elf-x86-64 0x568" >>
> %t.input
>  RUN: echo "\"%p/Inputs/dwarfdump-test3.elf-x86-64 space\" 0x640" >>
> %t.input
>  RUN: echo "\"%p/Inputs/dwarfdump-test3.elf-x86-64 space\" 0x633" >>
> %t.input
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>



-- 
Alexey Samsonov
vonosmas at gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140919/c9dbaaec/attachment.html>


More information about the llvm-commits mailing list