aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2012-03-05 21:17:44 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2012-03-05 21:17:44 +0100
commit1e3c1d950e3723c46ef467306bcaea3a4f1a85f2 (patch)
tree0a203dfd5709e8e57936d2ab25e4fc15b3529a67 /gcc
parent8993fde43241743b76372651364048d45ce2309e (diff)
downloadgcc-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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/dwarf2out.c54
-rw-r--r--gcc/function.c72
-rw-r--r--gcc/tree.h3
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;
+ }
}
}
diff --git a/gcc/tree.h b/gcc/tree.h
index 140f23e..0a2d619 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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. */