From a686dbf86a80b697e84a8ea9a8fa94b281796557 Mon Sep 17 00:00:00 2001
From: Jan Hubicka <jh@suse.cz>
Date: Sat, 24 Feb 2001 03:32:33 +0100
Subject: [PATCH] flow.c (find_sub_basic_blocks): New function.

	* 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 |   9 ++++
 gcc/flow.c    | 126 ++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 130 insertions(+), 5 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e0359670eb3e..d3f1da5600ff 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/flow.c b/gcc/flow.c
index 10c1bd2d3f84..82e90174063a 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -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));
 
 /* 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.  */
-- 
GitLab