flow.c (find_sub_basic_blocks): New function.
authorJan Hubicka <jh@suse.cz>
Sat, 24 Feb 2001 02:32:33 +0000 (03:32 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sat, 24 Feb 2001 02:32:33 +0000 (02:32 +0000)
* flow.c (find_sub_basic_blocks): New function.
(split_block): Be ready for basic block introduced by CODE_LABEL.
(commit_one_edge_insertion): Call find_sub_basic_block.

* flow.c (make_edges): Add edge from entry for blocks starting with
label having ALTERNATE_NAME

From-SVN: r40021

gcc/ChangeLog
gcc/flow.c

index e0359670eb3e81905e271f7615621fa6bebbfa80..d3f1da5600ff2e8a3fcfe37e0e730196e2ea127f 100644 (file)
@@ -1,3 +1,12 @@
+Sat Feb 24 03:30:38 CET 2001  Jan Hubicka  <jh@suse.cz>
+
+       * flow.c (find_sub_basic_blocks): New function.
+       (split_block): Be ready for basic block introduced by CODE_LABEL.
+       (commit_one_edge_insertion): Call find_sub_basic_block.
+
+       * flow.c (make_edges): Add edge from entry for blocks starting with
+       label having ALTERNATE_NAME
+
 Sat Feb 24 03:19:42 CET 2001  Jan Hubicka  <jh@suse.cz>
 
        * function.c (epilogue_done): Be ready for first basic block not
index 10c1bd2d3f8479cb20de0aec06ec586fd9ff2d14..82e90174063ae6d4ab8239e875e23e2411c8e208 100644 (file)
@@ -473,6 +473,7 @@ static void flow_loops_tree_build   PARAMS ((struct loops *));
 static int flow_loop_level_compute     PARAMS ((struct loop *, int));
 static int flow_loops_level_compute    PARAMS ((struct loops *));
 static void allocate_bb_life_data      PARAMS ((void));
+static void find_sub_basic_blocks      PARAMS ((basic_block));
 \f
 /* Find basic blocks of the current function.
    F is the first insn of the function and NREGS the number of register
@@ -697,6 +698,106 @@ find_label_refs (f, lvl)
   return lvl;
 }
 
+/* Assume that someone emitted code with control flow instructions to the
+   basic block.  Update the data structure.  */
+static void
+find_sub_basic_blocks (bb)
+     basic_block bb;
+{
+  rtx first_insn = bb->head, insn;
+  rtx end = bb->end;
+  edge succ_list = bb->succ;
+  rtx jump_insn = NULL_RTX;
+  int created = 0;
+  int barrier = 0;
+  edge falltru = 0;
+  basic_block first_bb = bb, last_bb;
+  int i;
+
+  if (GET_CODE (first_insn) == LABEL_REF)
+    first_insn = NEXT_INSN (first_insn);
+  first_insn = NEXT_INSN (first_insn);
+  bb->succ = NULL;
+
+  insn = first_insn;
+  /* Scan insn chain and try to find new basic block boundaries.  */
+  while (insn != end)
+    {
+      enum rtx_code code = GET_CODE (insn);
+      switch (code)
+       {
+       case JUMP_INSN:
+         /* We need some special care for those expressions.  */
+         if (GET_CODE (PATTERN (insn)) == ADDR_VEC
+             || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
+           abort();
+         jump_insn = insn;
+         break;
+       case BARRIER:
+         if (!jump_insn)
+           abort ();
+         barrier = 1;
+         break;
+       /* On code label, split current basic block.  */
+       case CODE_LABEL:
+         falltru = split_block (bb, PREV_INSN (insn));
+         if (jump_insn)
+           bb->end = jump_insn;
+         bb = falltru->dest;
+         if (barrier)
+           remove_edge (falltru);
+         barrier = 0;
+         jump_insn = 0;
+         created = 1;
+         if (LABEL_ALTERNATE_NAME (insn))
+           make_edge (NULL, ENTRY_BLOCK_PTR, bb, 0);
+         break;
+       case INSN:
+         /* In case we've previously split insn on the JUMP_INSN, move the
+            block header to proper place.  */
+         if (jump_insn)
+           {
+             falltru = split_block (bb, PREV_INSN (insn));
+             bb->end = jump_insn;
+             bb = falltru->dest;
+             if (barrier)
+               abort ();
+             jump_insn = 0;
+           }
+       default:
+         break;
+       }
+      insn = NEXT_INSN (insn);
+    }
+  /* Last basic block must end in the original BB end.  */
+  if (jump_insn)
+    abort ();
+
+  /* Wire in the original edges for last basic block.  */
+  if (created)
+    {
+      bb->succ = succ_list;
+      while (succ_list)
+       succ_list->src = bb, succ_list = succ_list->succ_next;
+    }
+  else
+    bb->succ = succ_list;
+
+  /* Now re-scan and wire in all edges.  This expect simple (conditional)
+     jumps at the end of each new basic blocks.  */
+  last_bb = bb;
+  for (i = first_bb->index; i < last_bb->index; i++)
+    {
+      bb = BASIC_BLOCK (i);
+      if (GET_CODE (bb->end) == JUMP_INSN)
+       {
+         mark_jump_label (PATTERN (bb->end), bb->end, 0, 0);
+         make_label_edge (NULL, bb, JUMP_LABEL (bb->end), 0);
+       }
+      insn = NEXT_INSN (insn);
+    }
+}
+
 /* Find all basic blocks of the function whose first insn is F.
 
    Collect and return a list of labels whose addresses are taken.  This
@@ -1121,6 +1222,10 @@ make_edges (label_value_list)
       enum rtx_code code;
       int force_fallthru = 0;
 
+      if (GET_CODE (bb->head) == CODE_LABEL
+         && LABEL_ALTERNATE_NAME (bb->head))
+       make_edge (NULL, ENTRY_BLOCK_PTR, bb, 0);
+
       /* Examine the last instruction of the block, and discover the
         ways we can leave the block.  */
 
@@ -1589,11 +1694,21 @@ split_block (bb, insn)
   BASIC_BLOCK (i) = new_bb;
   new_bb->index = i;
 
-  /* Create the basic block note.  */
-  bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK,
-                             new_bb->head);
-  NOTE_BASIC_BLOCK (bb_note) = new_bb;
-  new_bb->head = bb_note;
+  if (GET_CODE (new_bb->head) == CODE_LABEL)
+    {
+      /* Create the basic block note.  */
+      bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK,
+                                new_bb->head);
+      NOTE_BASIC_BLOCK (bb_note) = new_bb;
+    }
+  else
+    {
+      /* Create the basic block note.  */
+      bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK,
+                                 new_bb->head);
+      NOTE_BASIC_BLOCK (bb_note) = new_bb;
+      new_bb->head = bb_note;
+    }
 
   update_bb_for_insn (new_bb);
 
@@ -1995,6 +2110,7 @@ commit_one_edge_insertion (e)
     }
   else if (GET_CODE (last) == JUMP_INSN)
     abort ();
+  find_sub_basic_blocks (bb);
 }
 
 /* Update the CFG for all queued instructions.  */