[llvm-branch-commits] [llvm] ad18b07 - DebugInfo: Add support for always using ranges (rather than low/high pc) in DWARFv5

David Blaikie via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jan 5 16:41:08 PST 2021


Author: David Blaikie
Date: 2021-01-05T16:36:22-08:00
New Revision: ad18b075fd63935148b460f9c6b4dce130c56b15

URL: https://github.com/llvm/llvm-project/commit/ad18b075fd63935148b460f9c6b4dce130c56b15
DIFF: https://github.com/llvm/llvm-project/commit/ad18b075fd63935148b460f9c6b4dce130c56b15.diff

LOG: DebugInfo: Add support for always using ranges (rather than low/high pc) in DWARFv5

Given the ability provided by DWARFv5 rnglists to reuse addresses in the
address pool, it can be advantageous to object file size to use range
encodings even when the range could be described by a direct low/high
pc.

Add a flag to allow enabling this in DWARFv5 for the purpose of
experimentation/data gathering.

It might be that it makes sense to enable this functionality by default
for DWARFv5 + Split DWARF at least, where the tradeoff/desire to
optimize for .o file size is more explicit and .o bytes are higher
priority than .dwo bytes.

Added: 
    llvm/test/DebugInfo/X86/ranges_always.ll

Modified: 
    llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
    llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
    llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 7cf2b566ede8..02791f2280d2 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -558,7 +558,12 @@ void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE,
 
 void DwarfCompileUnit::attachRangesOrLowHighPC(
     DIE &Die, SmallVector<RangeSpan, 2> Ranges) {
-  if (Ranges.size() == 1 || !DD->useRangesSection()) {
+  assert(!Ranges.empty());
+  if (!DD->useRangesSection() ||
+      (Ranges.size() == 1 &&
+       (!DD->alwaysUseRanges() ||
+        DD->getSectionLabel(&Ranges.front().Begin->getSection()) ==
+            Ranges.front().Begin))) {
     const RangeSpan &Front = Ranges.front();
     const RangeSpan &Back = Ranges.back();
     attachLowHighPC(Die, Front.Begin, Back.End);

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index b790434576cb..fa5d55071e17 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -151,6 +151,14 @@ static cl::opt<LinkageNameOption>
                                             "Abstract subprograms")),
                       cl::init(DefaultLinkageNames));
 
+static cl::opt<DefaultOnOff> AlwaysUseRangesInV5(
+    "always-use-ranges-in-v5", cl::Hidden,
+    cl::desc("Always use DW_AT_ranges in DWARFv5 whenever it could allow more "
+             "address pool entry sharing to reduce relocations/object size"),
+    cl::values(clEnumVal(Default, "Default for platform"),
+               clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")),
+    cl::init(Default));
+
 static constexpr unsigned ULEB128PadSize = 4;
 
 void DebugLocDwarfExpression::emitOp(uint8_t Op, const char *Comment) {
@@ -422,6 +430,19 @@ DwarfDebug::DwarfDebug(AsmPrinter *A)
   else
     EnableOpConvert = (DwarfOpConvert == Enable);
 
+  // Split DWARF would benefit object size significantly by trading reductions
+  // in address pool usage for slightly increased range list encodings.
+  if (DwarfVersion >= 5) {
+    if (AlwaysUseRangesInV5 == Default) {
+      // FIXME: In the future, enable this by default for Split DWARF where the
+      // tradeoff is more pronounced due to being able to offload the range
+      // lists to the dwo file and shrink object files/reduce relocations there.
+      AlwaysUseRanges = false;
+    } else {
+      AlwaysUseRanges = AlwaysUseRangesInV5 == Enable;
+    }
+  }
+
   Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion);
   Asm->OutStreamer->getContext().setDwarfFormat(Dwarf64 ? dwarf::DWARF64
                                                         : dwarf::DWARF32);

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 502aef481a3a..b3b8e62fb5d9 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -378,6 +378,9 @@ class DwarfDebug : public DebugHandlerBase {
   /// Avoid using DW_OP_convert due to consumer incompatibilities.
   bool EnableOpConvert;
 
+  /// Force the use of DW_AT_ranges even for single-entry range lists.
+  bool AlwaysUseRanges = false;
+
   /// DWARF5 Experimental Options
   /// @{
   AccelTableKind TheAccelTableKind;
@@ -689,6 +692,10 @@ class DwarfDebug : public DebugHandlerBase {
   /// Returns whether ranges section should be emitted.
   bool useRangesSection() const { return UseRangesSection; }
 
+  /// Returns whether range encodings should be used for single entry range
+  /// lists.
+  bool alwaysUseRanges() const { return AlwaysUseRanges; }
+
   /// Returns whether to use sections as labels rather than temp symbols.
   bool useSectionsAsReferences() const {
     return UseSectionsAsReferences;

diff  --git a/llvm/test/DebugInfo/X86/ranges_always.ll b/llvm/test/DebugInfo/X86/ranges_always.ll
new file mode 100644
index 000000000000..c361aea9e278
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/ranges_always.ll
@@ -0,0 +1,133 @@
+; RUN: llc -O0 %s -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o - -always-use-ranges-in-v5=Enable \
+; RUN:   | llvm-dwarfdump -debug-info -debug-addr -debug-rnglists -v - \
+; RUN:   | FileCheck --implicit-check-not=DW_TAG --implicit-check-not=NULL --implicit-check-not=DW_AT_low_pc --implicit-check-not=DW_AT_high_pc --implicit-check-not=DW_AT_ranges %s
+
+; Generated from the following source. f4 is used to put a hole in the CU
+; ranges while keeping f2 and f4 in the same section (as opposed to
+; -ffunction-sections, which would produce CU ranges, but each function would
+; be in a 
diff erent section, so unable to share addresses). The call to f1 at
+; the start of f3 ensures the range for the inlined subroutine doesn't share
+; the starting address with f3 (so it can be improved by using a rnglist to
+; allow it to share an address it wouldn't already be sharing).
+
+; Without f6 being in another section, technically we could use a non-zero CU
+; low_pc that could act as a base address for all the addresses in the CU & avoid
+; the need for these forced rnglists - we don't do that currently, but f6 ensures
+; that this test will remain meaningful even if that improvement is made in the
+; future. (implementing that would require detecting that all the addresses in
+; the CU ranges are in the same section, then picking the lowest such address as
+; the base address to make all other addresses relative to)
+
+; void f1();
+; __attribute__((always_inline)) inline void f2() {
+;   f1();
+; }
+; void f3() {
+;   f1();
+;   f2();
+; }
+; __attribute__((nodebug)) void f4() {
+; }
+; void f5() {
+; }
+; __attribute__((section(".other"))) void f6() {
+; }
+
+; CHECK-LABEL: .debug_info contents:
+; CHECK: DW_TAG_compile_unit
+; CHECK:   DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
+; CHECK:   DW_AT_ranges [DW_FORM_rnglistx]   (indexed (0x2) rangelist = [[CU_RANGE:.*]]
+; CHECK:   DW_TAG_subprogram
+; CHECK:     DW_AT_name {{.*}} "f2"
+; CHECK:   DW_TAG_subprogram
+; CHECK:     DW_AT_low_pc [DW_FORM_addrx]    (indexed (00000000) address = 0x0000000000000000 ".text")
+; CHECK:     DW_AT_high_pc [DW_FORM_data4]   (0x00000010)
+; CHECK:     DW_TAG_inlined_subroutine
+; CHECK:       DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = [[INL_RANGE:.*]]
+; CHECK:     NULL
+; CHECK:   DW_TAG_subprogram
+; CHECK:     DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1) rangelist = [[F5_RANGE:.*]]
+; CHECK:   DW_TAG_subprogram
+; CHECK:     DW_AT_low_pc [DW_FORM_addrx]    (indexed (00000001) address = 0x0000000000000000 ".other")
+; CHECK:     DW_AT_high_pc [DW_FORM_data4]   (0x00000006)
+; CHECK:   NULL
+
+; CHECK-LABEL: .debug_addr contents:
+; CHECK: 0x00000000: Address table
+; CHECK-NEXT: Addrs: [
+; CHECK-NEXT: 0x0000000000000000
+; CHECK-NEXT: 0x0000000000000000
+; CHECK-NEXT: ]
+
+; CHECK-LABEL: .debug_rnglists contents:
+; CHECK: 0x00000000: range list header: {{.*}}, offset_entry_count = 0x00000003
+; CHECK: ranges:
+; CHECK-NEXT: [[INL_RANGE]]: [DW_RLE_base_addressx]:  0x0000000000000000
+; CHECK-NEXT:                [DW_RLE_offset_pair  ]
+; CHECK-NEXT:                [DW_RLE_end_of_list  ]
+
+; CHECK-NEXT: [[F5_RANGE]]: [DW_RLE_base_addressx]:  0x0000000000000000
+; CHECK-NEXT:               [DW_RLE_offset_pair  ]
+; CHECK-NEXT:               [DW_RLE_end_of_list  ]
+
+; CHECK-NEXT: [[CU_RANGE]]: [DW_RLE_base_addressx]:  0x0000000000000000
+; CHECK-NEXT:               [DW_RLE_offset_pair  ]
+; CHECK-NEXT:               [DW_RLE_offset_pair  ]
+; CHECK-NEXT:               [DW_RLE_startx_length]:  0x0000000000000001
+; CHECK-NEXT:               [DW_RLE_end_of_list  ]
+
+; Function Attrs: noinline optnone uwtable mustprogress
+define dso_local void @_Z2f3v() #0 !dbg !7 {
+entry:
+  call void @_Z2f1v(), !dbg !10
+  call void @_Z2f1v(), !dbg !11
+  ret void, !dbg !14
+}
+
+declare dso_local void @_Z2f1v() #1
+
+; Function Attrs: noinline nounwind optnone uwtable mustprogress
+define dso_local void @_Z2f4v() #2 {
+entry:
+  ret void
+}
+
+; Function Attrs: noinline nounwind optnone uwtable mustprogress
+define dso_local void @_Z2f5v() #2 !dbg !15 {
+entry:
+  ret void, !dbg !16
+}
+
+; Function Attrs: noinline nounwind optnone uwtable mustprogress
+define dso_local void @_Z2f6v() #2 section ".other" !dbg !17 {
+entry:
+  ret void, !dbg !18
+}
+
+attributes #0 = { noinline optnone uwtable mustprogress "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { noinline nounwind optnone uwtable mustprogress "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 12.0.0 (git at github.com:llvm/llvm-project.git 79afdd7d36b814942ec7f2f577d0443f6aecc939)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "ranges_always.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch", checksumkind: CSK_MD5, checksum: "25fb47763043609a0aac0ab69baa803d")
+!2 = !{}
+!3 = !{i32 7, !"Dwarf Version", i32 5}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 12.0.0 (git at github.com:llvm/llvm-project.git 79afdd7d36b814942ec7f2f577d0443f6aecc939)"}
+!7 = distinct !DISubprogram(name: "f3", linkageName: "_Z2f3v", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !9)
+!9 = !{null}
+!10 = !DILocation(line: 6, column: 3, scope: !7)
+!11 = !DILocation(line: 3, column: 3, scope: !12, inlinedAt: !13)
+!12 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!13 = distinct !DILocation(line: 7, column: 3, scope: !7)
+!14 = !DILocation(line: 8, column: 1, scope: !7)
+!15 = distinct !DISubprogram(name: "f5", linkageName: "_Z2f5v", scope: !1, file: !1, line: 11, type: !8, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!16 = !DILocation(line: 12, column: 1, scope: !15)
+!17 = distinct !DISubprogram(name: "f6", linkageName: "_Z2f6v", scope: !1, file: !1, line: 13, type: !8, scopeLine: 13, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!18 = !DILocation(line: 14, column: 1, scope: !17)


        


More information about the llvm-branch-commits mailing list