PR debug/51902
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 5 Mar 2012 20:17:44 +0000 (20:17 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 5 Mar 2012 20:17:44 +0000 (20:17 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@184958 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/dwarf2out.c
gcc/function.c
gcc/tree.h

index 936a07e..b7d7dfa 100644 (file)
@@ -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
index 63c46c0..b5f921a 100644 (file)
@@ -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);
index 4508ae2..9add7c1 100644 (file)
@@ -3998,18 +3998,35 @@ generate_setjmp_warnings (void)
 
 \f
 /* 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;
+       }
     }
 }
 
index 140f23e..0a2d619 100644 (file)
@@ -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.  */