This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

make commit_edge_insertion ready to commit multiple entry prologues


Hi
This patch makes commit_edge_insertion ready to accept code with control
flow constructs inside.
This is currently used in my tree to commit the prologues with multiple
entry points, but may be usefull in other cases.
I've implemented it by adding function find_sub_basic_blocks that scans
basic block and split it when reach control flow instructions.

Thu Feb 22 16:21: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.

Index: flow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flow.c,v
retrieving revision 1.380
diff -c -3 -p -r1.380 flow.c
*** flow.c	2001/02/21 16:52:40	1.380
--- flow.c	2001/02/22 15:19:47
*************** find_label_refs (f, lvl)
*** 697,702 ****
--- 697,802 ----
    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
*************** split_block (bb, insn)
*** 1589,1599 ****
    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;
  
    update_bb_for_insn (new_bb);
  
--- 1693,1713 ----
    BASIC_BLOCK (i) = new_bb;
    new_bb->index = i;
  
!   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);
  
*************** commit_one_edge_insertion (e)
*** 1995,2000 ****
--- 2109,2115 ----
      }
    else if (GET_CODE (last) == JUMP_INSN)
      abort ();
+   find_sub_basic_blocks (bb);
  }
  
  /* Update the CFG for all queued instructions.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]