diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index e9295f0e21dd3..7036c408c2e32 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -464,6 +464,18 @@ void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta, Label, PointerSize); return; } + + // If the two labels are within the same fragment, then the address-offset is + // already a fixed constant and is not relaxable. Emit the advance-line-addr + // data immediately to save time and memory. + if (auto OptAddrDelta = absoluteSymbolDiff(Label, LastLabel)) { + SmallString<16> Tmp; + MCDwarfLineAddr::encode(getContext(), Assembler->getDWARFLinetableParams(), + LineDelta, *OptAddrDelta, Tmp); + emitBytes(Tmp); + return; + } + const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel, SMLoc()); insert(getContext().allocFragment(LineDelta, *AddrDelta)); diff --git a/llvm/test/DebugInfo/RISCV/dwarf-riscv-relocs.ll b/llvm/test/DebugInfo/RISCV/dwarf-riscv-relocs.ll index 548cf2daa9d8d..d609a3fa889c0 100644 --- a/llvm/test/DebugInfo/RISCV/dwarf-riscv-relocs.ll +++ b/llvm/test/DebugInfo/RISCV/dwarf-riscv-relocs.ll @@ -38,7 +38,7 @@ ; LINE-DUMP: .debug_line contents: ; LINE-DUMP-NEXT: debug_line[0x00000000] ; LINE-DUMP-NEXT: Line table prologue: -; LINE-DUMP-NEXT: total_length: 0x00000067 +; LINE-DUMP-NEXT: total_length: 0x00000061 ; LINE-DUMP-NEXT: format: DWARF32 ; LINE-DUMP-NEXT: version: 5 ; LINE-DUMP-NEXT: address_size: 4 @@ -83,12 +83,10 @@ ; LINE-DUMP-NEXT: 0x000000000000001c 3 5 0 0 0 0 is_stmt prologue_end ; LINE-DUMP-NEXT:0x0000005d: 06 DW_LNS_negate_stmt ; LINE-DUMP-NEXT:0x0000005e: 0b DW_LNS_set_epilogue_begin -; LINE-DUMP-NEXT:0x0000005f: 03 DW_LNS_advance_line (3) -; LINE-DUMP-NEXT:0x00000061: 09 DW_LNS_fixed_advance_pc (addr += 0x0004, op-index = 0) -; LINE-DUMP-NEXT:0x00000064: 01 DW_LNS_copy +; LINE-DUMP-NEXT:0x0000005f: 4a address += 4, line += 0, op-index += 0 ; LINE-DUMP-NEXT: 0x0000000000000020 3 5 0 0 0 0 epilogue_begin -; LINE-DUMP-NEXT:0x00000065: 09 DW_LNS_fixed_advance_pc (addr += 0x0010, op-index = 0) -; LINE-DUMP-NEXT:0x00000068: 00 DW_LNE_end_sequence +; LINE-DUMP-NEXT:0x00000060: 02 DW_LNS_advance_pc (addr += 16, op-index += 0) +; LINE-DUMP-NEXT:0x00000062: 00 DW_LNE_end_sequence ; LINE-DUMP-NEXT: 0x0000000000000030 3 5 0 0 0 0 end_sequence ; ModuleID = 'dwarf-riscv-relocs.c' diff --git a/llvm/test/DebugInfo/X86/debug-line-in-one-fragment.ll b/llvm/test/DebugInfo/X86/debug-line-in-one-fragment.ll new file mode 100644 index 0000000000000..16c9e12accbc0 --- /dev/null +++ b/llvm/test/DebugInfo/X86/debug-line-in-one-fragment.ll @@ -0,0 +1,96 @@ +; RUN: llc %s -o %t.o -filetype=obj +; RUN: llvm-dwarfdump --debug-line %t.o | FileCheck %s --check-prefix=LINES +; RUN: llc %s -o %t.o -filetype=obj -debug-only=mc-dump 2>&1 | FileCheck %s --check-prefix=FRAGMENTS +; +; REQUIRES: asserts + +;; Test (using mc-dump debug output) that .debug_line can be arranged in memory +;; using a single data fragment for a simple function, instead of using multiple +;; MCDwarfFragment fragments in un-necessary cirucmstances. Some targets want +;; multiple fragments so that they can linker-relax the linetable, but x86 +;; doesn't. +;; +;; First, sanity check that the linetable output is as expected, + +; LINES: Address Line Column File ISA Discriminator OpIndex Flags +; LINES-NEXT: ------------------ ------ ------ ------ --- ------------- ------- ------------- +; LINES-NEXT: 0x0000000000000000 3 5 0 0 0 0 is_stmt prologue_end +; LINES-NEXT: 0x0000000000000003 4 12 0 0 0 0 is_stmt +; LINES-NEXT: 0x0000000000000007 4 3 0 0 0 0 +; LINES-NEXT: 0x0000000000000008 4 3 0 0 0 0 end_sequence + +;; Here's a typical example of .debug_line in a suboptimal arrangement: for each +;; address-delta there's an MCDwarfFragment computing the delta during +;; relaxation. +;; +;; +;; AddrDelta:- LineDelta:1>, +;; +;; Contents:[05,03,06] (3 bytes)>, +;; +;; AddrDelta:- LineDelta:0>, +;; +;; AddrDelta:- LineDelta:9223372036854775807>, +;; +;; Contents:[] (0 bytes)>]>, +;; +;; The function in question is made of a single data fragment where the address +;; deltas are known at assembly time. We can (and should) emit .debug_line as a +;; single data fragment. (Check that we see one data fragment, then no more +;; fragments until the next section). +; +; FRAGMENTS: