basic_block.h (struct basic_block_def): Added prev_bb and next_bb fields.
authorZdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
Sun, 19 May 2002 22:25:49 +0000 (00:25 +0200)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Sun, 19 May 2002 22:25:49 +0000 (22:25 +0000)
* basic_block.h (struct basic_block_def): Added prev_bb and next_bb
fields.
(FOR_BB_BETWEEN, FOR_ALL_BB, FOR_ALL_BB_REVERSE): New macros for
traversing basic block chain.
(create_basic_block_structure, create_basic_block): Declaration changed.
(link_block, unlink_block): Declare.
* cfg.c (entry_exit_blocks): Initialize new fields.
(link_block, unlink_block): New.
(expunge_block_nocompact): Unlink basic block.
(dump_flow_info): Print prev_bb/next_bb fields.
* cfgbuild.c (find_basic_blocks_1, find_basic_blocks): Modified.
* cfgcleanup.c (merge_blocks_move_predecessor_nojumps): Modified.
* cfglayout.c (fixup_reorder_chain, cfg_layout_duplicate_bb): Modified.
* cfgrtl.c (create_basic_block_structure, create_basic_block,
split_block, force_nonfallthru_and_redirect, split_edge): Modified.
(verify_flow_info): Check that list agrees with numbering.

From-SVN: r53642

gcc/ChangeLog
gcc/basic-block.h
gcc/cfg.c
gcc/cfgbuild.c
gcc/cfgcleanup.c
gcc/cfglayout.c
gcc/cfgrtl.c

index 1f6f6f4fe58e56f12b2ed5eabe0ec131030535bf..0aedfaae3c4e37ad67d04ee8d864cb8be2c6a57e 100644 (file)
@@ -1,3 +1,22 @@
+2002-05-20  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
+
+       * basic_block.h (struct basic_block_def): Added prev_bb and next_bb
+       fields.
+       (FOR_BB_BETWEEN, FOR_ALL_BB, FOR_ALL_BB_REVERSE): New macros for
+       traversing basic block chain.
+       (create_basic_block_structure, create_basic_block): Declaration changed.
+       (link_block, unlink_block): Declare.
+       * cfg.c (entry_exit_blocks): Initialize new fields.
+       (link_block, unlink_block): New.
+       (expunge_block_nocompact): Unlink basic block.
+       (dump_flow_info): Print prev_bb/next_bb fields.
+       * cfgbuild.c (find_basic_blocks_1, find_basic_blocks): Modified.
+       * cfgcleanup.c (merge_blocks_move_predecessor_nojumps): Modified.
+       * cfglayout.c (fixup_reorder_chain, cfg_layout_duplicate_bb): Modified.
+       * cfgrtl.c (create_basic_block_structure, create_basic_block,
+       split_block, force_nonfallthru_and_redirect, split_edge): Modified.
+       (verify_flow_info): Check that list agrees with numbering.
+
 2002-05-19  Neil Booth  <neil@daikokuya.demon.co.uk>
 
        * c-common.c (preprocessing_asm): New macro.
index 5615b145f020d375c6a93be5d7c2a163dec5786b..cf0d13ad2d527e3fc6d7f99bce8072b31b4a3e05 100644 (file)
@@ -206,6 +206,9 @@ typedef struct basic_block_def {
   /* The index of this block.  */
   int index;
 
+  /* Previous and next blocks in the chain.  */
+  struct basic_block_def *prev_bb, *next_bb;
+
   /* The loop depth of this block.  */
   int loop_depth;
 
@@ -240,6 +243,16 @@ extern varray_type basic_block_info;
 
 #define BASIC_BLOCK(N)  (VARRAY_BB (basic_block_info, (N)))
 
+/* For iterating over basic blocks.  */
+#define FOR_BB_BETWEEN(BB, FROM, TO, DIR) \
+  for (BB = FROM; BB != TO; BB = BB->DIR)
+
+#define FOR_EACH_BB(BB) \
+  FOR_BB_BETWEEN (BB, ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR, next_bb)
+
+#define FOR_EACH_BB_REVERSE(BB) \
+  FOR_BB_BETWEEN (BB, EXIT_BLOCK_PTR->prev_bb, ENTRY_BLOCK_PTR, prev_bb)
+
 /* What registers are live at the setjmp call.  */
 
 extern regset regs_live_at_setjmp;
@@ -314,8 +327,8 @@ extern void remove_edge                     PARAMS ((edge));
 extern void redirect_edge_succ         PARAMS ((edge, basic_block));
 extern edge redirect_edge_succ_nodup   PARAMS ((edge, basic_block));
 extern void redirect_edge_pred         PARAMS ((edge, basic_block));
-extern basic_block create_basic_block_structure PARAMS ((int, rtx, rtx, rtx));
-extern basic_block create_basic_block  PARAMS ((int, rtx, rtx));
+extern basic_block create_basic_block_structure PARAMS ((int, rtx, rtx, rtx, basic_block));
+extern basic_block create_basic_block  PARAMS ((rtx, rtx, basic_block));
 extern int flow_delete_block           PARAMS ((basic_block));
 extern int flow_delete_block_noexpunge PARAMS ((basic_block));
 extern void clear_bb_flags             PARAMS ((void));
@@ -644,6 +657,8 @@ extern void debug_regset            PARAMS ((regset));
 extern void allocate_reg_life_data      PARAMS ((void));
 extern void allocate_bb_life_data      PARAMS ((void));
 extern void expunge_block              PARAMS ((basic_block));
+extern void link_block                 PARAMS ((basic_block, basic_block));
+extern void unlink_block               PARAMS ((basic_block));
 extern void expunge_block_nocompact    PARAMS ((basic_block));
 extern basic_block alloc_block         PARAMS ((void));
 extern void find_unreachable_blocks    PARAMS ((void));
index 47dfb238ea593ac18b5ff43857534b8c8e028917..d1045331e2b2cb89484c9389aeb23a71fc3265cb 100644 (file)
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -93,6 +93,8 @@ struct basic_block_def entry_exit_blocks[2]
     NULL,                      /* global_live_at_end */
     NULL,                      /* aux */
     ENTRY_BLOCK,               /* index */
+    NULL,                      /* prev_bb */
+    EXIT_BLOCK_PTR,            /* next_bb */
     0,                         /* loop_depth */
     0,                         /* count */
     0,                         /* frequency */
@@ -111,6 +113,8 @@ struct basic_block_def entry_exit_blocks[2]
     NULL,                      /* global_live_at_end */
     NULL,                      /* aux */
     EXIT_BLOCK,                        /* index */
+    ENTRY_BLOCK_PTR,           /* prev_bb */
+    NULL,                      /* next_bb */
     0,                         /* loop_depth */
     0,                         /* count */
     0,                         /* frequency */
@@ -220,12 +224,35 @@ alloc_block ()
   return bb;
 }
 
+/* Link block B to chain after AFTER.  */
+void
+link_block (b, after)
+     basic_block b, after;
+{
+  b->next_bb = after->next_bb;
+  b->prev_bb = after;
+  after->next_bb = b;
+  b->next_bb->prev_bb = b;
+}
+  
+/* Unlink block B from chain.  */
+void
+unlink_block (b)
+     basic_block b;
+{
+  b->next_bb->prev_bb = b->prev_bb;
+  b->prev_bb->next_bb = b->next_bb;
+}
+  
+
 /* Remove block B from the basic block array and compact behind it.  */
 
 void
 expunge_block_nocompact (b)
      basic_block b;
 {
+  unlink_block (b);
+
   /* Invalidate data to make bughunting easier.  */
   memset (b, 0, sizeof *b);
   b->index = -3;
@@ -521,6 +548,8 @@ dump_flow_info (file)
 
       fprintf (file, "\nBasic block %d: first insn %d, last %d, ",
               i, INSN_UID (bb->head), INSN_UID (bb->end));
+      fprintf (file, "prev %d, next %d, ",
+              bb->prev_bb->index, bb->next_bb->index);
       fprintf (file, "loop_depth %d, count ", bb->loop_depth);
       fprintf (file, HOST_WIDEST_INT_PRINT_DEC, bb->count);
       fprintf (file, ", freq %i.\n", bb->frequency);
index 5ce9d40f3b076d25bfce3abaada19e418317159d..767b0dee0bc634b9a35f5c070dd430e8bbf1fa54 100644 (file)
@@ -476,6 +476,7 @@ find_basic_blocks_1 (f)
   rtx trll = NULL_RTX;
   rtx head = NULL_RTX;
   rtx end = NULL_RTX;
+  basic_block prev = ENTRY_BLOCK_PTR;
 
   /* We process the instructions in a slightly different way than we did
      previously.  This is so that we see a NOTE_BASIC_BLOCK after we have
@@ -492,7 +493,7 @@ find_basic_blocks_1 (f)
       if ((GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == BARRIER)
          && head)
        {
-         create_basic_block_structure (i++, head, end, bb_note);
+         prev = create_basic_block_structure (i++, head, end, bb_note, prev);
          head = end = NULL_RTX;
          bb_note = NULL_RTX;
        }
@@ -506,7 +507,7 @@ find_basic_blocks_1 (f)
 
       if (head && control_flow_insn_p (insn))
        {
-         create_basic_block_structure (i++, head, end, bb_note);
+         prev = create_basic_block_structure (i++, head, end, bb_note, prev);
          head = end = NULL_RTX;
          bb_note = NULL_RTX;
        }
@@ -588,7 +589,7 @@ find_basic_blocks_1 (f)
     }
 
   if (head != NULL_RTX)
-    create_basic_block_structure (i++, head, end, bb_note);
+    create_basic_block_structure (i++, head, end, bb_note, prev);
   else if (bb_note)
     delete_insn (bb_note);
 
@@ -633,6 +634,8 @@ find_basic_blocks (f, nregs, file)
     }
 
   n_basic_blocks = count_basic_blocks (f);
+  ENTRY_BLOCK_PTR->next_bb = EXIT_BLOCK_PTR;
+  EXIT_BLOCK_PTR->prev_bb = ENTRY_BLOCK_PTR;
 
   /* Size the basic block table.  The actual structures will be allocated
      by find_basic_blocks_1, since we want to keep the structure pointers
index fcf6944d4bb8ce117aa1f4bb03b03f0989c4c7ea..15dbec1f28b7b18f6bc292edd1f339d0f36b9df2 100644 (file)
@@ -723,6 +723,9 @@ merge_blocks_move_predecessor_nojumps (a, b)
   a->index = b->index;
   b->index = index;
 
+  unlink_block (a);
+  link_block (a, b->prev_bb);
+
   /* Now blocks A and B are contiguous.  Merge them.  */
   merge_blocks_nomove (a, b);
 }
index 2820f0d5d9697e1c16b509184f9290d677641b8f..b3cdf84b66a6ecd858ea749fd04a3015026e2046 100644 (file)
@@ -357,7 +357,7 @@ scope_to_insns_finalize ()
 static void
 fixup_reorder_chain ()
 {
-  basic_block bb;
+  basic_block bb, prev_bb;
   int index;
   rtx insn = NULL;
 
@@ -541,11 +541,20 @@ fixup_reorder_chain ()
        }
     }
 
-  for (bb = BASIC_BLOCK (0), index = 0; bb; bb = RBI (bb)->next, index ++)
+  prev_bb = ENTRY_BLOCK_PTR;
+  bb = BASIC_BLOCK (0);
+  index = 0;
+
+  for (; bb; prev_bb = bb, bb = RBI (bb)->next, index ++)
     {
       bb->index = index;
       BASIC_BLOCK (index) = bb;
+
+      bb->prev_bb = prev_bb;
+      prev_bb->next_bb = bb;
     }
+  prev_bb->next_bb = EXIT_BLOCK_PTR;
+  EXIT_BLOCK_PTR->prev_bb = prev_bb;
 }
 \f
 /* Perform sanity checks on the insn chain.
@@ -871,8 +880,9 @@ cfg_layout_duplicate_bb (bb, e)
 #endif
 
   insn = duplicate_insn_chain (bb->head, bb->end);
-  new_bb = create_basic_block (n_basic_blocks, insn,
-                              insn ? get_last_insn () : NULL);
+  new_bb = create_basic_block (insn,
+                              insn ? get_last_insn () : NULL,
+                              EXIT_BLOCK_PTR->prev_bb);
   alloc_aux_for_block (new_bb, sizeof (struct reorder_block_def));
 
   if (RBI (bb)->header)
index 844f5df70f51c4cc60b9c479058be44580b96a92..1ce15ba8c6832cf7280d322dae8a09f8dee7c728 100644 (file)
@@ -248,12 +248,14 @@ delete_insn_chain_and_edges (first, last)
    the note and basic block struct in BB_NOTE, if any and do not grow
    BASIC_BLOCK chain and should be used directly only by CFG construction code.
    END can be NULL in to create new empty basic block before HEAD.  Both END
-   and HEAD can be NULL to create basic block at the end of INSN chain.  */
+   and HEAD can be NULL to create basic block at the end of INSN chain.
+   AFTER is the basic block we should be put after.  */
 
 basic_block
-create_basic_block_structure (index, head, end, bb_note)
+create_basic_block_structure (index, head, end, bb_note, after)
      int index;
      rtx head, end, bb_note;
+     basic_block after;
 {
   basic_block bb;
 
@@ -311,6 +313,7 @@ create_basic_block_structure (index, head, end, bb_note)
   bb->end = end;
   bb->index = index;
   bb->flags = BB_NEW;
+  link_block (bb, after);
   BASIC_BLOCK (index) = bb;
   if (basic_block_for_insn)
     update_bb_for_insn (bb);
@@ -323,17 +326,18 @@ create_basic_block_structure (index, head, end, bb_note)
 }
 
 /* Create new basic block consisting of instructions in between HEAD and END
-   and place it to the BB chain at position INDEX.  END can be NULL in to
+   and place it to the BB chain after block AFTER.  END can be NULL in to
    create new empty basic block before HEAD.  Both END and HEAD can be NULL to
    create basic block at the end of INSN chain.  */
 
 basic_block
-create_basic_block (index, head, end)
-     int index;
+create_basic_block (head, end, after)
      rtx head, end;
+     basic_block after;
 {
   basic_block bb;
   int i;
+  int index = after->index + 1;
 
   /* Place the new block just after the block being split.  */
   VARRAY_GROW (basic_block_info, ++n_basic_blocks);
@@ -349,7 +353,7 @@ create_basic_block (index, head, end)
       tmp->index = i;
     }
 
-  bb = create_basic_block_structure (index, head, end, NULL);
+  bb = create_basic_block_structure (index, head, end, NULL, after);
   bb->aux = NULL;
   return bb;
 }
@@ -537,7 +541,7 @@ split_block (bb, insn)
     return 0;
 
   /* Create the new basic block.  */
-  new_bb = create_basic_block (bb->index + 1, NEXT_INSN (insn), bb->end);
+  new_bb = create_basic_block (NEXT_INSN (insn), bb->end, bb);
   new_bb->count = bb->count;
   new_bb->frequency = bb->frequency;
   new_bb->loop_depth = bb->loop_depth;
@@ -998,7 +1002,7 @@ force_nonfallthru_and_redirect (e, target)
       /* We can't redirect the entry block.  Create an empty block at the
          start of the function which we use to add the new jump.  */
       edge *pe1;
-      basic_block bb = create_basic_block (0, e->dest->head, NULL);
+      basic_block bb = create_basic_block (e->dest->head, NULL, ENTRY_BLOCK_PTR);
 
       /* Change the existing edge's source to be the new block, and add
         a new edge from the entry block to the new block.  */
@@ -1019,7 +1023,7 @@ force_nonfallthru_and_redirect (e, target)
       /* Create the new structures.  */
       note = last_loop_beg_note (e->src->end);
       jump_block
-       = create_basic_block (e->src->index + 1, NEXT_INSN (note), NULL);
+       = create_basic_block (NEXT_INSN (note), NULL, e->src);
       jump_block->count = e->count;
       jump_block->frequency = EDGE_FREQUENCY (e);
       jump_block->loop_depth = target->loop_depth;
@@ -1286,8 +1290,7 @@ split_edge (edge_in)
   else
     before = NULL_RTX;
 
-  bb = create_basic_block (edge_in->dest == EXIT_BLOCK_PTR ? n_basic_blocks
-                          : edge_in->dest->index, before, NULL);
+  bb = create_basic_block (before, NULL, edge_in->dest->prev_bb);
   bb->count = edge_in->count;
   bb->frequency = EDGE_FREQUENCY (edge_in);
 
@@ -1719,12 +1722,49 @@ verify_flow_info ()
   size_t *edge_checksum;
   rtx x;
   int i, last_bb_num_seen, num_bb_notes, err = 0;
+  basic_block bb, last_bb_seen;
 
   bb_info = (basic_block *) xcalloc (max_uid, sizeof (basic_block));
   last_visited = (basic_block *) xcalloc (n_basic_blocks + 2,
                                          sizeof (basic_block));
   edge_checksum = (size_t *) xcalloc (n_basic_blocks + 2, sizeof (size_t));
 
+  /* Check bb chain & numbers.  */
+  last_bb_seen = ENTRY_BLOCK_PTR;
+  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb, NULL, next_bb)
+    {
+      if (bb != EXIT_BLOCK_PTR
+         && bb != BASIC_BLOCK (bb->index))
+       {
+         error ("bb %d on wrong place", bb->index);
+         err = 1;
+       }
+
+      if (bb->prev_bb != last_bb_seen)
+       {
+         error ("prev_bb of %d should be %d, not %d",
+                bb->index, last_bb_seen->index, bb->prev_bb->index);
+         err = 1;
+       }
+
+      /* For now, also check that we didn't change the order.  */
+      if (bb != EXIT_BLOCK_PTR && bb->index != last_bb_seen->index + 1)
+       {
+         error ("Wrong order of blocks %d and %d",
+                last_bb_seen->index, bb->index);
+         err = 1;
+       }
+
+      if (bb == EXIT_BLOCK_PTR && last_bb_seen->index != n_basic_blocks - 1)
+       {
+         error ("Only %d of %d blocks in chain",
+                last_bb_seen->index + 1, n_basic_blocks);
+         err = 1;
+       }
+
+      last_bb_seen = bb;
+    }
+
   for (i = n_basic_blocks - 1; i >= 0; i--)
     {
       basic_block bb = BASIC_BLOCK (i);