diff options
author | Jakub Jelinek <jakub@redhat.com> | 2012-03-05 21:17:44 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2012-03-05 21:17:44 +0100 |
commit | 1e3c1d950e3723c46ef467306bcaea3a4f1a85f2 (patch) | |
tree | 0a203dfd5709e8e57936d2ab25e4fc15b3529a67 | |
parent | 8993fde43241743b76372651364048d45ce2309e (diff) | |
download | gcc-1e3c1d950e3723c46ef467306bcaea3a4f1a85f2.zip gcc-1e3c1d950e3723c46ef467306bcaea3a4f1a85f2.tar.gz gcc-1e3c1d950e3723c46ef467306bcaea3a4f1a85f2.tar.bz2 |
re PR debug/51902 (lexical_blocks inside inlined_subroutines generate duplicate debug_ranges)
PR debug/51902
* tree.h (BLOCK_SAME_RANGE): Define.
* function.c (block_fragments_nreverse): Clear BLOCK_SAME_RANGE
if BLOCK_FRAGMENT_CHAIN is non-NULL, but has it cleared.
Also clear BLOCK_SAME_RANGE if fragment chain's supercontext fragment
isn't equal to supercontext fragment's fragment chain.
Adjust BLOCK_SUPERCONTEXT to point to supercontext fragment's
fragment origin.
(blocks_nreverse_all): Likewise.
(reorder_blocks_1): Compute BLOCK_SAME_RANGE bits. Set
BLOCK_SUPERCONTEXT to supercontext fragment instead of
supercontext fragment's fragment origin.
* dwarf2out.c (add_high_low_attributes): If stmt has the same
range as its parent (or parents thereof etc.), use the parent's
DW_AT_ranges value instead of creating a new .debug_ranges range.
From-SVN: r184958
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 54 | ||||
-rw-r--r-- | gcc/function.c | 72 | ||||
-rw-r--r-- | gcc/tree.h | 3 |
4 files changed, 138 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 936a07e..b7d7dfa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2012-03-05 Jakub Jelinek <jakub@redhat.com> + + PR debug/51902 + * tree.h (BLOCK_SAME_RANGE): Define. + * function.c (block_fragments_nreverse): Clear BLOCK_SAME_RANGE + if BLOCK_FRAGMENT_CHAIN is non-NULL, but has it cleared. + Also clear BLOCK_SAME_RANGE if fragment chain's supercontext fragment + isn't equal to supercontext fragment's fragment chain. + Adjust BLOCK_SUPERCONTEXT to point to supercontext fragment's + fragment origin. + (blocks_nreverse_all): Likewise. + (reorder_blocks_1): Compute BLOCK_SAME_RANGE bits. Set + BLOCK_SUPERCONTEXT to supercontext fragment instead of + supercontext fragment's fragment origin. + * dwarf2out.c (add_high_low_attributes): If stmt has the same + range as its parent (or parents thereof etc.), use the parent's + DW_AT_ranges value instead of creating a new .debug_ranges range. + 2012-03-05 Richard Henderson <rth@redhat.com> PR tree-opt/52242 diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 63c46c0..b5f921a 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -18134,7 +18134,9 @@ add_high_low_attributes (tree stmt, dw_die_ref die) if (BLOCK_FRAGMENT_CHAIN (stmt) && (dwarf_version >= 3 || !dwarf_strict)) { - tree chain; + tree chain, superblock = NULL_TREE; + dw_die_ref pdie; + dw_attr_ref attr = NULL; if (inlined_function_outer_scope_p (stmt)) { @@ -18143,6 +18145,56 @@ add_high_low_attributes (tree stmt, dw_die_ref die) add_AT_lbl_id (die, DW_AT_entry_pc, label); } + /* Optimize duplicate .debug_ranges lists or even tails of + lists. If this BLOCK has same ranges as its supercontext, + lookup DW_AT_ranges attribute in the supercontext (and + recursively so), verify that the ranges_table contains the + right values and use it instead of adding a new .debug_range. */ + for (chain = stmt, pdie = die; + BLOCK_SAME_RANGE (chain); + chain = BLOCK_SUPERCONTEXT (chain)) + { + dw_attr_ref new_attr; + + pdie = pdie->die_parent; + if (pdie == NULL) + break; + if (BLOCK_SUPERCONTEXT (chain) == NULL_TREE) + break; + new_attr = get_AT (pdie, DW_AT_ranges); + if (new_attr == NULL + || new_attr->dw_attr_val.val_class != dw_val_class_range_list) + break; + attr = new_attr; + superblock = BLOCK_SUPERCONTEXT (chain); + } + if (attr != NULL + && (ranges_table[attr->dw_attr_val.v.val_offset + / 2 / DWARF2_ADDR_SIZE].num + == BLOCK_NUMBER (superblock)) + && BLOCK_FRAGMENT_CHAIN (superblock)) + { + unsigned long off = attr->dw_attr_val.v.val_offset + / 2 / DWARF2_ADDR_SIZE; + unsigned long supercnt = 0, thiscnt = 0; + for (chain = BLOCK_FRAGMENT_CHAIN (superblock); + chain; chain = BLOCK_FRAGMENT_CHAIN (chain)) + { + ++supercnt; + gcc_checking_assert (ranges_table[off + supercnt].num + == BLOCK_NUMBER (chain)); + } + gcc_checking_assert (ranges_table[off + supercnt + 1].num == 0); + for (chain = BLOCK_FRAGMENT_CHAIN (stmt); + chain; chain = BLOCK_FRAGMENT_CHAIN (chain)) + ++thiscnt; + gcc_assert (supercnt >= thiscnt); + add_AT_range_list (die, DW_AT_ranges, + (off + supercnt - thiscnt) + * 2 * DWARF2_ADDR_SIZE); + return; + } + add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt)); chain = BLOCK_FRAGMENT_CHAIN (stmt); diff --git a/gcc/function.c b/gcc/function.c index 4508ae2..9add7c1 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -3998,18 +3998,35 @@ generate_setjmp_warnings (void) /* Reverse the order of elements in the fragment chain T of blocks, - and return the new head of the chain (old last element). */ + and return the new head of the chain (old last element). + In addition to that clear BLOCK_SAME_RANGE flags when needed + and adjust BLOCK_SUPERCONTEXT from the super fragment to + its super fragment origin. */ static tree block_fragments_nreverse (tree t) { - tree prev = 0, block, next; + tree prev = 0, block, next, prev_super = 0; + tree super = BLOCK_SUPERCONTEXT (t); + if (BLOCK_FRAGMENT_ORIGIN (super)) + super = BLOCK_FRAGMENT_ORIGIN (super); for (block = t; block; block = next) { next = BLOCK_FRAGMENT_CHAIN (block); BLOCK_FRAGMENT_CHAIN (block) = prev; + if ((prev && !BLOCK_SAME_RANGE (prev)) + || (BLOCK_FRAGMENT_CHAIN (BLOCK_SUPERCONTEXT (block)) + != prev_super)) + BLOCK_SAME_RANGE (block) = 0; + prev_super = BLOCK_SUPERCONTEXT (block); + BLOCK_SUPERCONTEXT (block) = super; prev = block; } + t = BLOCK_FRAGMENT_ORIGIN (t); + if (BLOCK_FRAGMENT_CHAIN (BLOCK_SUPERCONTEXT (t)) + != prev_super) + BLOCK_SAME_RANGE (t) = 0; + BLOCK_SUPERCONTEXT (t) = super; return prev; } @@ -4026,11 +4043,15 @@ blocks_nreverse_all (tree t) { next = BLOCK_CHAIN (block); BLOCK_CHAIN (block) = prev; - BLOCK_SUBBLOCKS (block) = blocks_nreverse_all (BLOCK_SUBBLOCKS (block)); if (BLOCK_FRAGMENT_CHAIN (block) && BLOCK_FRAGMENT_ORIGIN (block) == NULL_TREE) - BLOCK_FRAGMENT_CHAIN (block) - = block_fragments_nreverse (BLOCK_FRAGMENT_CHAIN (block)); + { + BLOCK_FRAGMENT_CHAIN (block) + = block_fragments_nreverse (BLOCK_FRAGMENT_CHAIN (block)); + if (!BLOCK_SAME_RANGE (BLOCK_FRAGMENT_CHAIN (block))) + BLOCK_SAME_RANGE (block) = 0; + } + BLOCK_SUBBLOCKS (block) = blocks_nreverse_all (BLOCK_SUBBLOCKS (block)); prev = block; } return prev; @@ -4085,6 +4106,7 @@ static void reorder_blocks_1 (rtx insns, tree current_block, VEC(tree,heap) **p_block_stack) { rtx insn; + tree prev_beg = NULL_TREE, prev_end = NULL_TREE; for (insn = insns; insn; insn = NEXT_INSN (insn)) { @@ -4098,12 +4120,17 @@ reorder_blocks_1 (rtx insns, tree current_block, VEC(tree,heap) **p_block_stack) gcc_assert (BLOCK_FRAGMENT_ORIGIN (block) == NULL_TREE); origin = block; + if (prev_end) + BLOCK_SAME_RANGE (prev_end) = 0; + prev_end = NULL_TREE; + /* If we have seen this block before, that means it now spans multiple address regions. Create a new fragment. */ if (TREE_ASM_WRITTEN (block)) { tree new_block = copy_node (block); + BLOCK_SAME_RANGE (new_block) = 0; BLOCK_FRAGMENT_ORIGIN (new_block) = origin; BLOCK_FRAGMENT_CHAIN (new_block) = BLOCK_FRAGMENT_CHAIN (origin); @@ -4113,6 +4140,11 @@ reorder_blocks_1 (rtx insns, tree current_block, VEC(tree,heap) **p_block_stack) block = new_block; } + if (prev_beg == current_block && prev_beg) + BLOCK_SAME_RANGE (block) = 1; + + prev_beg = origin; + BLOCK_SUBBLOCKS (block) = 0; TREE_ASM_WRITTEN (block) = 1; /* When there's only one block for the entire function, @@ -4120,10 +4152,22 @@ reorder_blocks_1 (rtx insns, tree current_block, VEC(tree,heap) **p_block_stack) will cause infinite recursion. */ if (block != current_block) { + tree super; if (block != origin) - gcc_assert (BLOCK_SUPERCONTEXT (origin) == current_block); - - BLOCK_SUPERCONTEXT (block) = current_block; + gcc_assert (BLOCK_SUPERCONTEXT (origin) == current_block + || BLOCK_FRAGMENT_ORIGIN (BLOCK_SUPERCONTEXT + (origin)) + == current_block); + if (VEC_empty (tree, *p_block_stack)) + super = current_block; + else + { + super = VEC_last (tree, *p_block_stack); + gcc_assert (super == current_block + || BLOCK_FRAGMENT_ORIGIN (super) + == current_block); + } + BLOCK_SUPERCONTEXT (block) = super; BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block); BLOCK_SUBBLOCKS (current_block) = block; current_block = origin; @@ -4134,8 +4178,20 @@ reorder_blocks_1 (rtx insns, tree current_block, VEC(tree,heap) **p_block_stack) { NOTE_BLOCK (insn) = VEC_pop (tree, *p_block_stack); current_block = BLOCK_SUPERCONTEXT (current_block); + if (BLOCK_FRAGMENT_ORIGIN (current_block)) + current_block = BLOCK_FRAGMENT_ORIGIN (current_block); + prev_beg = NULL_TREE; + prev_end = BLOCK_SAME_RANGE (NOTE_BLOCK (insn)) + ? NOTE_BLOCK (insn) : NULL_TREE; } } + else + { + prev_beg = NULL_TREE; + if (prev_end) + BLOCK_SAME_RANGE (prev_end) = 0; + prev_end = NULL_TREE; + } } } @@ -2088,6 +2088,9 @@ struct GTY(()) tree_omp_clause { #define BLOCK_ABSTRACT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.abstract_origin) #define BLOCK_ABSTRACT(NODE) (BLOCK_CHECK (NODE)->block.abstract_flag) +/* True if BLOCK has the same ranges as its BLOCK_SUPERCONTEXT. */ +#define BLOCK_SAME_RANGE(NODE) (BLOCK_CHECK (NODE)->base.nameless_flag) + /* An index number for this block. These values are not guaranteed to be unique across functions -- whether or not they are depends on the debugging output format in use. */ |