Hi, I noticed that when you generate dwarf for an inlined function it often comes with duplicate range lists for both the DW_TAG_inlined_subroutine and the child DW_TAG_lexical_block DIE. For example:
static int k; static int foo (int i) { int j = i + 42; return k + (j > 14 ? j : i); } int main (int argc, char **argv) { int c = argc; k = 2 * c; c = foo (c); return c; } Generates with -O2 -gdwarf-4: DWARF section [27] '.debug_info' at offset 0x895: [Offset] Compilation unit at offset 0: Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4 [...] [ a8] inlined_subroutine abstract_origin (ref4) [ 31] entry_pc (addr) 0x0000000000400360 <main> ranges (data4) range list [ 0] call_file (data1) 1 call_line (data1) 13 [ bb] formal_parameter abstract_origin (ref4) [ 42] location (block1) [ 0] reg5 [ c2] lexical_block ranges (data4) range list [ 40] [ c7] variable abstract_origin (ref4) [ 4b] location (data4) location list [ 23] [...] DWARF section [32] '.debug_ranges' at offset 0xb4e: [ 0] 0x0000000000400360 <main>..0x0000000000400363 <main+0x3> 0x0000000000400366 <main+0x6>..0x0000000000400369 <main+0x9> 0x000000000040036f <main+0xf>..0x0000000000400374 <main+0x14> [ 40] 0x0000000000400360 <main>..0x0000000000400363 <main+0x3> 0x0000000000400366 <main+0x6>..0x0000000000400369 <main+0x9> 0x000000000040036f <main+0xf>..0x0000000000400374 <main+0x14> [ 80] 0x0000000000400360 <main>..0x0000000000400375 So range list 0 for the inlined_subroutine DIE a8 is the same as range list 40 for the lexical_block DIE c2. I had hoped I could detect and then reduce the duplication of the range lists in this case with the attached patch where I just check that the basic block numbers for the ranges are the same as the ranges of its context DIE. But that doesn't actually work since by looking at the generated assembly the basic block asm labels are in the same place, the block numbers are actually different (and so there are actually two differently named/numbered labels generated at the same place). e.g: .LVL0: .LBB4: .LBB5: .loc 1 5 0 leal 42(%rdi), %eax .LBE5: .LBE4: .loc 1 12 0 leal (%rdi,%rdi), %edx .LBB8: .LBB6: .loc 1 6 0 cmpl $14, %eax .LBE6: .LBE8: .loc 1 12 0 movl %edx, k(%rip) .LVL1: .LBB9: .LBB7: .loc 1 6 0 cmovle %edi, %eax .LVL2: addl %edx, %eax .LBE7: .LBE9: .loc 1 15 0 ret .cfi_endproc [...] .section .debug_ranges,"",@progbits .Ldebug_ranges0: .quad .LBB4 .quad .LBE4 .quad .LBB8 .quad .LBE8 .quad .LBB9 .quad .LBE9 .quad 0 .quad 0 .quad .LBB5 .quad .LBE5 .quad .LBB6 .quad .LBE6 .quad .LBB7 .quad .LBE7 .quad 0 .quad 0 .quad .LFB1 .quad .LFE1 .quad 0 .quad 0 Is there a way to detect that basic blocks have the same range even though they have different block numbers? Or am I not looking/thinking about this issue correctly? Thanks, Mark
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index f9f4295..53776f7 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -3291,6 +3291,7 @@ static int same_dw_val_p (const dw_val_node *, const dw_val_node *, int *); static int same_attr_p (dw_attr_ref, dw_attr_ref, int *); static int same_die_p (dw_die_ref, dw_die_ref, int *); static int same_die_p_wrap (dw_die_ref, dw_die_ref); +static int same_range_p (tree, dw_die_ref, unsigned int *); static void compute_section_prefix (dw_die_ref); static int is_type_die (dw_die_ref); static int is_comdat_die (dw_die_ref); @@ -6586,6 +6587,47 @@ same_die_p_wrap (dw_die_ref die1, dw_die_ref die2) return ret; } +/* Is the range of the tree the same as that of the (context) die? */ + +static int +same_range_p (tree stmt, dw_die_ref die, unsigned int *off) +{ + dw_attr_ref attr; + unsigned i; + int num; + tree chain; + + attr = get_AT (die, DW_AT_ranges); + if (! attr) + return 0; + + *off = attr->dw_attr_val.v.val_offset; + + i = ((*off) / 2) / DWARF2_ADDR_SIZE; + num = ranges_table[i].num; + + if (num != BLOCK_NUMBER (stmt)) + return 0; + + chain = BLOCK_FRAGMENT_CHAIN (stmt); + do + { + i++; + num = ranges_table[i].num; + if (num != BLOCK_NUMBER (chain)) + return 0; + chain = BLOCK_FRAGMENT_CHAIN (chain); + } + while (chain); + + i++; + num = ranges_table[i].num; + if (num != 0) + return 0; + + return 1; +} + /* The prefix to attach to symbols on DIEs in the current comdat debug info section. */ static char *comdat_symbol_id; @@ -18062,10 +18104,12 @@ add_call_src_coords_attributes (tree stmt, dw_die_ref die) /* A helper function for gen_lexical_block_die and gen_inlined_subroutine_die. - Add low_pc and high_pc attributes to the DIE for a block STMT. */ + Add low_pc and high_pc attributes to the DIE for a block STMT. + If a range is added then the context DIE is checked to see if it has + the same range already. */ static inline void -add_high_low_attributes (tree stmt, dw_die_ref die) +add_high_low_attributes (tree stmt, dw_die_ref die, dw_die_ref context_die) { char label[MAX_ARTIFICIAL_LABEL_BYTES]; @@ -18073,6 +18117,7 @@ add_high_low_attributes (tree stmt, dw_die_ref die) && (dwarf_version >= 3 || !dwarf_strict)) { tree chain; + unsigned int range_off; if (inlined_function_outer_scope_p (stmt)) { @@ -18081,16 +18126,23 @@ add_high_low_attributes (tree stmt, dw_die_ref die) add_AT_lbl_id (die, DW_AT_entry_pc, label); } - add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt)); - - chain = BLOCK_FRAGMENT_CHAIN (stmt); - do + if (same_range_p (stmt, context_die, &range_off)) { - add_ranges (chain); - chain = BLOCK_FRAGMENT_CHAIN (chain); + add_AT_range_list (die, DW_AT_ranges, range_off); + } + else + { + add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt)); + + chain = BLOCK_FRAGMENT_CHAIN (stmt); + do + { + add_ranges (chain); + chain = BLOCK_FRAGMENT_CHAIN (chain); + } + while (chain); + add_ranges (NULL); } - while (chain); - add_ranges (NULL); } else { @@ -18119,7 +18171,7 @@ gen_lexical_block_die (tree stmt, dw_die_ref context_die, int depth) } if (! BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt)) - add_high_low_attributes (stmt, stmt_die); + add_high_low_attributes (stmt, stmt_die, context_die); decls_for_scope (stmt, stmt_die, depth); } @@ -18157,7 +18209,7 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die, int depth) } add_abstract_origin_attribute (subr_die, decl); if (TREE_ASM_WRITTEN (stmt)) - add_high_low_attributes (stmt, subr_die); + add_high_low_attributes (stmt, subr_die, context_die); add_call_src_coords_attributes (stmt, subr_die); decls_for_scope (stmt, subr_die, depth);