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]

BB creation cleanup


Hi,
This is another cleanup patch, now for BB creation, I was thinking about for a while.
Now all BBs are created via create_basic_block call (so we can use similar allocation
scheme as we do now for edges) and I've added new function "force_nonfallthru" that
breaks fallthru edge by creating jump (possibly in new basic block).

I've made create_basic_block to handle renumbering of basic blocks and thus CFG
building code now uses create_basic_block_structure that avoids this
functionality.

This functionality is common to redirect_edge_and_branch_force, split_edge and
fixup_reorder_chain.  merge_blocks can be made cleaner using it avoiding
the dirty trick with cralling redirect_edge_and_branch_force.
Especially the split_edge and merge_blocks looks IMO much more readable now.

Bootstrapped/regtested i586.

Honza

Tue Sep 11 14:40:52 CEST 2001  Jan Hubicka  <jh@suse.cz>

	* basic-block.h (create_basic_block_structure): New.
	(create_basic_block): Update prototype.
	(force_nonfallthru): New.
	* bb-reorder.c (fixup_reorder_chain): Fixup use force_nonfallthru.
	* cfg.c (create_basic_block_structure): Rename from create_basic_block;
	handle updating of block_for_insn, creating of empty BBs and BBs at
	the end of INSN chain.
	(create_basic_block): New function.
	(split_block): Use create_basic_block.
	(force_nonfallthru_and_redirect): Break out from ...; cleanup
	(redirect_edge_and_branch_force): ... here.
	(force_nonfallthru): New.
	(split_edge): Rewrite to use force_nonfallthru and create_block.
	* cfgbuild.c (find_basic_blocks_1): Use create_basic_block_structure.
	(find_basic_blocks): Free basic_block_for_insn.
	* cfgcleanup.c (merge_blocks): Use force_nonfallthru.

Index: basic-block.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/basic-block.h,v
retrieving revision 1.117
diff -c -3 -p -r1.117 basic-block.h
*** basic-block.h	2001/09/11 09:39:10	1.117
--- basic-block.h	2001/09/11 12:33:49
*************** extern void remove_edge			PARAMS ((edge)
*** 315,321 ****
  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 void create_basic_block		PARAMS ((int, rtx, rtx, rtx));
  extern int flow_delete_block		PARAMS ((basic_block));
  extern void merge_blocks_nomove		PARAMS ((basic_block, basic_block));
  extern void tidy_fallthru_edge		PARAMS ((edge, basic_block,
--- 315,322 ----
  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 int flow_delete_block		PARAMS ((basic_block));
  extern void merge_blocks_nomove		PARAMS ((basic_block, basic_block));
  extern void tidy_fallthru_edge		PARAMS ((edge, basic_block,
*************** extern void allocate_bb_life_data	PARAMS
*** 629,634 ****
--- 630,636 ----
  extern void find_unreachable_blocks	PARAMS ((void));
  extern void delete_noop_moves		PARAMS ((rtx));
  extern basic_block redirect_edge_and_branch_force PARAMS ((edge, basic_block));
+ extern basic_block force_nonfallthru	PARAMS ((edge));
  extern bool redirect_edge_and_branch	PARAMS ((edge, basic_block));
  extern rtx block_label			PARAMS ((basic_block));
  extern bool forwarder_block_p		PARAMS ((basic_block));
Index: bb-reorder.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/bb-reorder.c,v
retrieving revision 1.36
diff -c -3 -p -r1.36 bb-reorder.c
*** bb-reorder.c	2001/09/11 09:39:11	1.36
--- bb-reorder.c	2001/09/11 12:33:50
*************** fixup_reorder_chain ()
*** 610,616 ****
    for (bb = BASIC_BLOCK (0); bb ; bb = RBI (bb)->next)
      {
        edge e_fall, e_taken, e;
!       rtx jump_insn, barrier_insn, bb_end_insn;
        basic_block nb;
  
        if (bb->succ == NULL)
--- 610,616 ----
    for (bb = BASIC_BLOCK (0); bb ; bb = RBI (bb)->next)
      {
        edge e_fall, e_taken, e;
!       rtx bb_end_insn;
        basic_block nb;
  
        if (bb->succ == NULL)
*************** fixup_reorder_chain ()
*** 694,747 ****
  	  /* If the fallthru block is still next, nothing to do.  */
  	  if (RBI (bb)->next == e_fall->dest)
  	    continue;
- 
- 	  /* We need a new jump insn.  If the block has only one outgoing
- 	     edge, then we can stuff the new jump insn in directly.  */
- 	  if (bb->succ->succ_next == NULL)
- 	    {
- 	      e_fall->flags &= ~EDGE_FALLTHRU;
- 
- 	      jump_insn = emit_jump_to_block_after (e_fall->dest, bb_end_insn);
- 	      bb->end = jump_insn;
- 	      barrier_insn = emit_barrier_after (jump_insn);
- 	      RBI (bb)->eff_end = barrier_insn;
- 	      continue;
- 	    }
  	}
  
!       /* We got here if we need to add a new jump insn in a new block
! 	 across the edge e_fall.  */
  
!       jump_insn = emit_jump_to_block_after (e_fall->dest, bb_end_insn);
!       barrier_insn = emit_barrier_after (jump_insn);
  
!       VARRAY_GROW (basic_block_info, ++n_basic_blocks);
!       create_basic_block (n_basic_blocks - 1, jump_insn, jump_insn, NULL);
! 
!       nb = BASIC_BLOCK (n_basic_blocks - 1);
!       nb->local_set = 0;
!       nb->count = e_fall->count;
!       nb->frequency = EDGE_FREQUENCY (e_fall);
! 
!       nb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
!       nb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
!       COPY_REG_SET (nb->global_live_at_start, bb->global_live_at_start);
!       COPY_REG_SET (nb->global_live_at_end, bb->global_live_at_start);
! 
!       nb->aux = xmalloc (sizeof (struct reorder_block_def));
!       RBI (nb)->eff_head = nb->head;
!       RBI (nb)->eff_end = barrier_insn;
!       RBI (nb)->scope = RBI (bb)->scope;
!       RBI (nb)->visited = 1;
!       RBI (nb)->next = RBI (bb)->next;
!       RBI (bb)->next = nb;
! 
!       /* Link to new block.  */
!       make_single_succ_edge (nb, e_fall->dest, 0);
!       redirect_edge_succ (e_fall, nb);
! 
!       /* Don't process this new block.  */
!       bb = nb;
      }
  
    /* Put basic_block_info in the new order.  */
--- 694,717 ----
  	  /* If the fallthru block is still next, nothing to do.  */
  	  if (RBI (bb)->next == e_fall->dest)
  	    continue;
  	}
  
!       /* We got here if we need to add a new jump insn.  */
  
!       nb = force_nonfallthru (e_fall);
  
!       if (nb)
! 	{
! 	  nb->aux = xmalloc (sizeof (struct reorder_block_def));
! 	  RBI (nb)->eff_head = nb->head;
! 	  RBI (nb)->eff_end = NEXT_INSN (nb->end);
! 	  RBI (nb)->scope = RBI (bb)->scope;
! 	  RBI (nb)->visited = 1;
! 	  RBI (nb)->next = RBI (bb)->next;
! 	  RBI (bb)->next = nb;
! 	  /* Don't process this new block.  */
! 	  bb = nb;
! 	}
      }
  
    /* Put basic_block_info in the new order.  */
Index: cfg.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cfg.c,v
retrieving revision 1.2
diff -c -3 -p -r1.2 cfg.c
*** cfg.c	2001/09/11 09:39:11	1.2
--- cfg.c	2001/09/11 12:33:50
*************** Software Foundation, 59 Temple Place - S
*** 40,46 ****
  	 - High level edge redirection (with updating and optimizing instruction
  	   chain)
  	     block_label, redirect_edge_and_branch,
! 	     redirect_edge_and_branch_force, tidy_fallthru_edge
        - Edge splitting and commiting to edges
  	  split_edge, insert_insn_on_edge, commit_edge_insertions
        - Dumpipng and debugging
--- 40,46 ----
  	 - High level edge redirection (with updating and optimizing instruction
  	   chain)
  	     block_label, redirect_edge_and_branch,
! 	     redirect_edge_and_branch_force, tidy_fallthru_edge, force_nonfallthru
        - Edge splitting and commiting to edges
  	  split_edge, insert_insn_on_edge, commit_edge_insertions
        - Dumpipng and debugging
*************** static bool try_redirect_by_replacing_ju
*** 147,152 ****
--- 147,153 ----
  static void expunge_block		PARAMS ((basic_block));
  static rtx last_loop_beg_note		PARAMS ((rtx));
  static bool back_edge_of_syntactic_loop_p PARAMS ((basic_block, basic_block));
+ static basic_block force_nonfallthru_and_redirect PARAMS ((edge, basic_block));
  
  /* Called once at intialization time.  */
  
*************** flow_delete_insn_chain (start, finish)
*** 320,330 ****
  }
  
  /* Create a new basic block consisting of the instructions between
!    HEAD and END inclusive.  Reuses the note and basic block struct
!    in BB_NOTE, if any.  */
  
! void
! create_basic_block (index, head, end, bb_note)
       int index;
       rtx head, end, bb_note;
  {
--- 321,336 ----
  }
  
  /* Create a new basic block consisting of the instructions between
!    HEAD and END inclusive.  This function is designed to allow fast
!    BB construction - reuses 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.  */
  
! basic_block
! create_basic_block_structure (index, head, end, bb_note)
       int index;
       rtx head, end, bb_note;
  {
*************** create_basic_block (index, head, end, bb
*** 360,371 ****
        bb = (basic_block) obstack_alloc (&flow_obstack, sizeof (*bb));
        memset (bb, 0, sizeof (*bb));
  
!       if (GET_CODE (head) == CODE_LABEL)
! 	bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, head);
        else
  	{
  	  bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK, head);
  	  head = bb_note;
  	}
        NOTE_BASIC_BLOCK (bb_note) = bb;
      }
--- 366,388 ----
        bb = (basic_block) obstack_alloc (&flow_obstack, sizeof (*bb));
        memset (bb, 0, sizeof (*bb));
  
!       if (!head && !end)
! 	{
! 	  head = end = bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK,
! 						  get_last_insn ());
! 	}
!       else if (GET_CODE (head) == CODE_LABEL && end)
! 	{
! 	  bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, head);
! 	  if (head == end)
! 	    end = bb_note;
! 	}
        else
  	{
  	  bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK, head);
  	  head = bb_note;
+ 	  if (!end)
+ 	    end = head;
  	}
        NOTE_BASIC_BLOCK (bb_note) = bb;
      }
*************** create_basic_block (index, head, end, bb
*** 378,387 ****
--- 395,440 ----
    bb->end = end;
    bb->index = index;
    BASIC_BLOCK (index) = bb;
+   if (basic_block_for_insn)
+     update_bb_for_insn (bb);
  
    /* Tag the block so that we know it has been used when considering
       other basic block notes.  */
    bb->aux = bb;
+ 
+   return bb;
+ }
+ 
+ /* Create new basic block consisting of instructions in between HEAD and
+    END and place it to the BB chain at possition INDEX.
+    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;
+      rtx head, end;
+ {
+   basic_block bb;
+   int i;
+ 
+   /* Place the new block just after the block being split.  */
+   VARRAY_GROW (basic_block_info, ++n_basic_blocks);
+ 
+   /* Some parts of the compiler expect blocks to be number in
+      sequential order so insert the new block immediately after the
+      block being split..  */
+   for (i = n_basic_blocks - 1; i > index; --i)
+     {
+       basic_block tmp = BASIC_BLOCK (i - 1);
+       BASIC_BLOCK (i) = tmp;
+       tmp->index = i;
+     }
+ 
+   bb = create_basic_block_structure (index, head, end, NULL);
+   bb->aux = NULL;
+   return bb;
  }
  
  /* Remove block B from the basic block array and compact behind it.  */
*************** split_block (bb, insn)
*** 777,851 ****
    basic_block new_bb;
    edge new_edge;
    edge e;
-   rtx bb_note;
-   int i, j;
  
    /* There is no point splitting the block after its end.  */
    if (bb->end == insn)
      return 0;
- 
-   /* Create the new structures.  */
-   new_bb = (basic_block) obstack_alloc (&flow_obstack, sizeof (*new_bb));
- 
-   memset (new_bb, 0, sizeof (*new_bb));
- 
-   new_bb->head = NEXT_INSN (insn);
-   new_bb->end = bb->end;
-   bb->end = insn;
  
!   new_bb->succ = bb->succ;
!   bb->succ = NULL;
!   new_bb->pred = NULL;
    new_bb->count = bb->count;
    new_bb->frequency = bb->frequency;
    new_bb->loop_depth = bb->loop_depth;
  
!   /* Redirect the src of the successor edges of bb to point to new_bb.  */
    for (e = new_bb->succ; e; e = e->succ_next)
      e->src = new_bb;
  
    new_edge = make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU);
  
-   /* Place the new block just after the block being split.  */
-   VARRAY_GROW (basic_block_info, ++n_basic_blocks);
- 
-   /* Some parts of the compiler expect blocks to be number in
-      sequential order so insert the new block immediately after the
-      block being split..  */
-   j = bb->index;
-   for (i = n_basic_blocks - 1; i > j + 1; --i)
-     {
-       basic_block tmp = BASIC_BLOCK (i - 1);
-       BASIC_BLOCK (i) = tmp;
-       tmp->index = i;
-     }
- 
-   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;
- 
-       /* If the only thing in this new block was the label, make sure
- 	 the block note gets included.  */
-       if (new_bb->head == new_bb->end)
- 	new_bb->end = bb_note;
-     }
-   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);
- 
    if (bb->global_live_at_start)
      {
        new_bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
--- 831,856 ----
    basic_block new_bb;
    edge new_edge;
    edge e;
  
    /* There is no point splitting the block after its end.  */
    if (bb->end == insn)
      return 0;
  
!   /* Create the new basic block.  */
!   new_bb = create_basic_block (bb->index + 1, NEXT_INSN (insn), bb->end);
    new_bb->count = bb->count;
    new_bb->frequency = bb->frequency;
    new_bb->loop_depth = bb->loop_depth;
+   bb->end = insn;
  
!   /* Redirect the outgoing edges.  */
!   new_bb->succ = bb->succ;
!   bb->succ = NULL;
    for (e = new_bb->succ; e; e = e->succ_next)
      e->src = new_bb;
  
    new_edge = make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU);
  
    if (bb->global_live_at_start)
      {
        new_bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
*************** last_loop_beg_note (insn)
*** 1110,1116 ****
  {
    rtx last = insn;
    insn = NEXT_INSN (insn);
!   while (GET_CODE (insn) == NOTE
  	 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
      {
        if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
--- 1115,1121 ----
  {
    rtx last = insn;
    insn = NEXT_INSN (insn);
!   while (insn && GET_CODE (insn) == NOTE
  	 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
      {
        if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
*************** redirect_edge_and_branch (e, target)
*** 1222,1338 ****
    return true;
  }
  
! /* Redirect edge even at the expense of creating new jump insn or
!    basic block.  Return new basic block if created, NULL otherwise.
!    Abort if converison is impossible.  */
  
! basic_block
! redirect_edge_and_branch_force (e, target)
       edge e;
       basic_block target;
  {
!   basic_block new_bb;
    edge new_edge;
    rtx label;
-   rtx bb_note;
-   int i, j;
  
-   if (redirect_edge_and_branch (e, target))
-     return NULL;
-   if (e->dest == target)
-     return NULL;
    if (e->flags & EDGE_ABNORMAL)
      abort ();
    if (!(e->flags & EDGE_FALLTHRU))
      abort ();
! 
!   e->flags &= ~EDGE_FALLTHRU;
!   label = block_label (target);
!   /* Case of the fallthru block.  */
!   if (!e->src->succ->succ_next)
      {
!       e->src->end = emit_jump_insn_after (gen_jump (label),
! 					  last_loop_beg_note (e->src->end));
!       JUMP_LABEL (e->src->end) = label;
!       LABEL_NUSES (label)++;
!       if (basic_block_for_insn)
! 	set_block_for_new_insns (e->src->end, e->src);
!       emit_barrier_after (e->src->end);
!       if (rtl_dump_file)
! 	fprintf (rtl_dump_file,
! 		 "Emitting jump insn %i to redirect edge %i->%i to %i\n",
! 		 INSN_UID (e->src->end), e->src->index, e->dest->index,
! 		 target->index);
!       redirect_edge_succ (e, target);
!       return NULL;
!     }
!   /* Redirecting fallthru edge of the conditional needs extra work.  */
! 
!   if (rtl_dump_file)
!     fprintf (rtl_dump_file,
! 	     "Emitting jump insn %i in new BB to redirect edge %i->%i to %i\n",
! 	     INSN_UID (e->src->end), e->src->index, e->dest->index,
! 	     target->index);
! 
!   /* Create the new structures.  */
!   new_bb = (basic_block) obstack_alloc (&flow_obstack, sizeof (*new_bb));
! 
!   memset (new_bb, 0, sizeof (*new_bb));
! 
!   new_bb->end = new_bb->head = last_loop_beg_note (e->src->end);
!   new_bb->succ = NULL;
!   new_bb->pred = NULL;
!   new_bb->count = e->count;
!   new_bb->frequency = EDGE_FREQUENCY (e);
!   new_bb->loop_depth = e->dest->loop_depth;
  
!   if (target->global_live_at_start)
!     {
!       new_bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
!       new_bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
!       COPY_REG_SET (new_bb->global_live_at_start,
! 		    target->global_live_at_start);
!       COPY_REG_SET (new_bb->global_live_at_end, new_bb->global_live_at_start);
      }
  
!   /* Wire edge in.  */
!   new_edge = make_edge (e->src, new_bb, EDGE_FALLTHRU);
!   new_edge->probability = e->probability;
!   new_edge->count = e->count;
! 
!   /* Redirect old edge.  */
!   redirect_edge_succ (e, target);
!   redirect_edge_pred (e, new_bb);
!   e->probability = REG_BR_PROB_BASE;
  
!   /* Place the new block just after the block being split.  */
!   VARRAY_GROW (basic_block_info, ++n_basic_blocks);
  
!   /* Some parts of the compiler expect blocks to be number in
!      sequential order so insert the new block immediately after the
!      block being split..  */
!   j = new_edge->src->index;
!   for (i = n_basic_blocks - 1; i > j + 1; --i)
!     {
!       basic_block tmp = BASIC_BLOCK (i - 1);
!       BASIC_BLOCK (i) = tmp;
!       tmp->index = i;
!     }
  
!   BASIC_BLOCK (i) = new_bb;
!   new_bb->index = i;
  
!   /* Create the basic block note.  */
!   bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, new_bb->head);
!   NOTE_BASIC_BLOCK (bb_note) = new_bb;
!   new_bb->head = bb_note;
  
!   new_bb->end = emit_jump_insn_after (gen_jump (label), new_bb->head);
!   JUMP_LABEL (new_bb->end) = label;
!   LABEL_NUSES (label)++;
!   if (basic_block_for_insn)
!     set_block_for_new_insns (new_bb->end, new_bb);
!   emit_barrier_after (new_bb->end);
    return new_bb;
  }
  
--- 1227,1325 ----
    return true;
  }
  
! /* Like force_nonfallthru bellow, but additionally performs redirection
!    Used by redirect_edge_and_branch_force.  */
  
! static basic_block
! force_nonfallthru_and_redirect (e, target)
       edge e;
       basic_block target;
  {
!   basic_block jump_block, new_bb = NULL;
!   rtx note;
    edge new_edge;
    rtx label;
  
    if (e->flags & EDGE_ABNORMAL)
      abort ();
    if (!(e->flags & EDGE_FALLTHRU))
      abort ();
!   if (e->src->succ->succ_next)
      {
!       /* 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);
!       jump_block->count = e->count;
!       jump_block->frequency = EDGE_FREQUENCY (e);
!       jump_block->loop_depth = target->loop_depth;
! 
!       if (target->global_live_at_start)
! 	{
! 	  jump_block->global_live_at_start =
! 	    OBSTACK_ALLOC_REG_SET (&flow_obstack);
! 	  jump_block->global_live_at_end =
! 	    OBSTACK_ALLOC_REG_SET (&flow_obstack);
! 	  COPY_REG_SET (jump_block->global_live_at_start,
! 			target->global_live_at_start);
! 	  COPY_REG_SET (jump_block->global_live_at_end,
! 			target->global_live_at_start);
! 	}
! 
!       /* Wire edge in.  */
!       new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU);
!       new_edge->probability = e->probability;
!       new_edge->count = e->count;
! 
!       /* Redirect old edge.  */
!       redirect_edge_pred (e, jump_block);
!       e->probability = REG_BR_PROB_BASE;
  
!       new_bb = jump_block;
      }
+   else
+     jump_block = e->src;
+   e->flags &= ~(EDGE_FALLTHRU | EDGE_CRITICAL);
+   label = block_label (target);
+   jump_block->end = emit_jump_insn_after (gen_jump (label), jump_block->end);
+   JUMP_LABEL (jump_block->end) = label;
+   LABEL_NUSES (label)++;
+   if (basic_block_for_insn)
+     set_block_for_new_insns (jump_block->end, jump_block);
+   emit_barrier_after (jump_block->end);
+   redirect_edge_succ_nodup (e, target);
  
!   return new_bb;
! }
  
! /* Edge E is assumed to be fallthru edge.  Emit needed jump instruction
!    (and possibly create new basic block) to make edge non-fallthru.
!    Return newly created BB or NULL if none.  */
! basic_block
! force_nonfallthru (e)
!      edge e;
! {
!   return force_nonfallthru_and_redirect (e, e->dest);
! }
  
! /* Redirect edge even at the expense of creating new jump insn or
!    basic block.  Return new basic block if created, NULL otherwise.
!    Abort if converison is impossible.  */
  
! basic_block
! redirect_edge_and_branch_force (e, target)
!      edge e;
!      basic_block target;
! {
!   basic_block new_bb;
  
!   if (redirect_edge_and_branch (e, target))
!     return NULL;
!   if (e->dest == target)
!     return NULL;
  
!   /* In case the edge redirection failed, try to force it to be non-fallthru
!      and redirect newly created simplejump.  */
!   new_bb = force_nonfallthru_and_redirect (e, target);
    return new_bb;
  }
  
*************** basic_block
*** 1479,1527 ****
  split_edge (edge_in)
       edge edge_in;
  {
!   basic_block old_pred, bb, old_succ;
    edge edge_out;
!   rtx bb_note;
!   int i, j;
  
    /* Abnormal edges cannot be split.  */
    if ((edge_in->flags & EDGE_ABNORMAL) != 0)
      abort ();
- 
-   old_pred = edge_in->src;
-   old_succ = edge_in->dest;
- 
-   /* Create the new structures.  */
-   bb = (basic_block) obstack_alloc (&flow_obstack, sizeof (*bb));
- 
-   memset (bb, 0, sizeof (*bb));
- 
-   /* ??? This info is likely going to be out of date very soon.  */
-   if (old_succ->global_live_at_start)
-     {
-       bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
-       bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
-       COPY_REG_SET (bb->global_live_at_start, old_succ->global_live_at_start);
-       COPY_REG_SET (bb->global_live_at_end, old_succ->global_live_at_start);
-     }
  
!   /* Wire them up.  */
!   bb->succ = NULL;
!   bb->count = edge_in->count;
!   bb->frequency = EDGE_FREQUENCY (edge_in);
! 
!   edge_in->flags &= ~EDGE_CRITICAL;
! 
!   edge_out = make_single_succ_edge (bb, old_succ, EDGE_FALLTHRU);
! 
!   /* Tricky case -- if there existed a fallthru into the successor
!      (and we're not it) we must add a new unconditional jump around
!      the new block we're actually interested in.
! 
!      Further, if that edge is critical, this means a second new basic
!      block must be created to hold it.  In order to simplify correct
!      insn placement, do this before we touch the existing basic block
!      ordering for the block we were really wanting.  */
    if ((edge_in->flags & EDGE_FALLTHRU) == 0)
      {
        edge e;
--- 1466,1481 ----
  split_edge (edge_in)
       edge edge_in;
  {
!   basic_block bb;
    edge edge_out;
!   rtx before;
  
    /* Abnormal edges cannot be split.  */
    if ((edge_in->flags & EDGE_ABNORMAL) != 0)
      abort ();
  
!   /* We are going to place the new block in front of edge destination.
!      Avoid existence of fallthru predecesors.  */
    if ((edge_in->flags & EDGE_FALLTHRU) == 0)
      {
        edge e;
*************** split_edge (edge_in)
*** 1530,1589 ****
  	  break;
  
        if (e)
! 	{
! 	  basic_block jump_block;
! 	  rtx pos;
! 
! 	  if ((e->flags & EDGE_CRITICAL) == 0
! 	      && e->src != ENTRY_BLOCK_PTR)
! 	    {
! 	      /* Non critical -- we can simply add a jump to the end
! 		 of the existing predecessor.  */
! 	      jump_block = e->src;
! 	    }
! 	  else
! 	    {
! 	      /* We need a new block to hold the jump.  The simplest
! 	         way to do the bulk of the work here is to recursively
! 	         call ourselves.  */
! 	      jump_block = split_edge (e);
! 	      e = jump_block->succ;
! 	    }
! 
! 	  /* Now add the jump insn ...  */
! 	  pos = emit_jump_insn_after (gen_jump (old_succ->head),
! 				      last_loop_beg_note (jump_block->end));
! 	  jump_block->end = pos;
! 	  if (basic_block_for_insn)
! 	    set_block_for_new_insns (pos, jump_block);
! 	  emit_barrier_after (pos);
! 
! 	  /* ... let jump know that label is in use, ...  */
! 	  JUMP_LABEL (pos) = old_succ->head;
! 	  ++LABEL_NUSES (old_succ->head);
! 
! 	  /* ... and clear fallthru on the outgoing edge.  */
! 	  e->flags &= ~EDGE_FALLTHRU;
! 
! 	  /* Continue splitting the interesting edge.  */
! 	}
      }
  
-   /* Place the new block just in front of the successor.  */
-   VARRAY_GROW (basic_block_info, ++n_basic_blocks);
-   if (old_succ == EXIT_BLOCK_PTR)
-     j = n_basic_blocks - 1;
-   else
-     j = old_succ->index;
-   for (i = n_basic_blocks - 1; i > j; --i)
-     {
-       basic_block tmp = BASIC_BLOCK (i - 1);
-       BASIC_BLOCK (i) = tmp;
-       tmp->index = i;
-     }
-   BASIC_BLOCK (i) = bb;
-   bb->index = i;
- 
    /* Create the basic block note.
  
       Where we place the note can have a noticable impact on the generated
--- 1484,1492 ----
  	  break;
  
        if (e)
! 	force_nonfallthru (e);
      }
  
    /* Create the basic block note.
  
       Where we place the note can have a noticable impact on the generated
*************** split_edge (edge_in)
*** 1601,1620 ****
        we want to ensure the instructions we insert are outside of any
        loop notes that physically sit between block 0 and block 1.  Otherwise
        we confuse the loop optimizer into thinking the loop is a phony.  */
!   if (old_succ != EXIT_BLOCK_PTR
!       && PREV_INSN (old_succ->head)
!       && GET_CODE (PREV_INSN (old_succ->head)) == NOTE
!       && NOTE_LINE_NUMBER (PREV_INSN (old_succ->head)) == NOTE_INSN_LOOP_BEG
!       && !back_edge_of_syntactic_loop_p (old_succ, old_pred))
!     bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK,
! 				PREV_INSN (old_succ->head));
!   else if (old_succ != EXIT_BLOCK_PTR)
!     bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK, old_succ->head);
    else
!     bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, get_last_insn ());
!   NOTE_BASIC_BLOCK (bb_note) = bb;
!   bb->head = bb->end = bb_note;
  
    /* For non-fallthry edges, we must adjust the predecessor's
       jump instruction to target our new block.  */
    if ((edge_in->flags & EDGE_FALLTHRU) == 0)
--- 1504,1538 ----
        we want to ensure the instructions we insert are outside of any
        loop notes that physically sit between block 0 and block 1.  Otherwise
        we confuse the loop optimizer into thinking the loop is a phony.  */
! 
!   if (edge_in->dest != EXIT_BLOCK_PTR
!       && PREV_INSN (edge_in->dest->head)
!       && GET_CODE (PREV_INSN (edge_in->dest->head)) == NOTE
!       && NOTE_LINE_NUMBER (PREV_INSN (edge_in->dest->head)) == NOTE_INSN_LOOP_BEG
!       && !back_edge_of_syntactic_loop_p (edge_in->dest, edge_in->src))
!     before = PREV_INSN (edge_in->dest->head);
!   else if (edge_in->dest != EXIT_BLOCK_PTR)
!     before = edge_in->dest->head;
    else
!     before = NULL_RTX;
  
+   bb = create_basic_block (edge_in->dest == EXIT_BLOCK_PTR ? n_basic_blocks
+ 			   : edge_in->dest->index, before, NULL);
+   bb->count = edge_in->count;
+   bb->frequency = EDGE_FREQUENCY (edge_in);
+ 
+   /* ??? This info is likely going to be out of date very soon.  */
+   if (edge_in->dest->global_live_at_start)
+     {
+       bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
+       bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
+       COPY_REG_SET (bb->global_live_at_start, edge_in->dest->global_live_at_start);
+       COPY_REG_SET (bb->global_live_at_end, edge_in->dest->global_live_at_start);
+     }
+ 
+   edge_in->flags &= ~EDGE_CRITICAL;
+   edge_out = make_single_succ_edge (bb, edge_in->dest, EDGE_FALLTHRU);
+ 
    /* For non-fallthry edges, we must adjust the predecessor's
       jump instruction to target our new block.  */
    if ((edge_in->flags & EDGE_FALLTHRU) == 0)
Index: cfgbuild.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cfgbuild.c,v
retrieving revision 1.2
diff -c -3 -p -r1.2 cfgbuild.c
*** cfgbuild.c	2001/09/11 09:39:11	1.2
--- cfgbuild.c	2001/09/11 12:33:50
*************** find_basic_blocks_1 (f)
*** 452,458 ****
  	     to a barrier or some such, no need to do it again.  */
  	  if (head != NULL_RTX)
  	    {
! 	      create_basic_block (i++, head, end, bb_note);
  	      bb_note = NULL_RTX;
  	    }
  
--- 452,458 ----
  	     to a barrier or some such, no need to do it again.  */
  	  if (head != NULL_RTX)
  	    {
! 	      create_basic_block_structure (i++, head, end, bb_note);
  	      bb_note = NULL_RTX;
  	    }
  
*************** find_basic_blocks_1 (f)
*** 523,529 ****
  		end = insn;
  
  	      new_bb_exclusive:
! 		create_basic_block (i++, head, end, bb_note);
  		head = end = NULL_RTX;
  		bb_note = NULL_RTX;
  		break;
--- 523,529 ----
  		end = insn;
  
  	      new_bb_exclusive:
! 		create_basic_block_structure (i++, head, end, bb_note);
  		head = end = NULL_RTX;
  		bb_note = NULL_RTX;
  		break;
*************** find_basic_blocks_1 (f)
*** 579,585 ****
      }
  
    if (head != NULL_RTX)
!     create_basic_block (i++, head, end, bb_note);
    else if (bb_note)
      flow_delete_insn (bb_note);
  
--- 579,585 ----
      }
  
    if (head != NULL_RTX)
!     create_basic_block_structure (i++, head, end, bb_note);
    else if (bb_note)
      flow_delete_insn (bb_note);
  
*************** find_basic_blocks (f, nregs, file)
*** 603,608 ****
--- 603,612 ----
  {
    int max_uid;
    timevar_push (TV_CFG);
+ 
+   if (basic_block_for_insn)
+     VARRAY_FREE (basic_block_for_insn);
+   basic_block_for_insn = 0;
  
    /* Flush out existing data.  */
    if (basic_block_info != NULL)
Index: cfgcleanup.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cfgcleanup.c,v
retrieving revision 1.2
diff -c -3 -p -r1.2 cfgcleanup.c
*** cfgcleanup.c	2001/09/11 09:39:11	1.2
--- cfgcleanup.c	2001/09/11 12:33:50
*************** merge_blocks (e, b, c, mode)
*** 376,384 ****
       edge recorded from the call_placeholder back to this label, as
       that would make optimize_sibling_and_tail_recursive_calls more
       complex for no gain.  */
!   if (GET_CODE (c->head) == CODE_LABEL
        && tail_recursion_label_p (c->head))
!     return 0;
  
    /* If B has a fallthru edge to C, no need to move anything.  */
    if (e->flags & EDGE_FALLTHRU)
--- 374,383 ----
       edge recorded from the call_placeholder back to this label, as
       that would make optimize_sibling_and_tail_recursive_calls more
       complex for no gain.  */
!   if (! (mode & CLEANUP_PRE_SIBCALL)
!       && GET_CODE (c->head) == CODE_LABEL
        && tail_recursion_label_p (c->head))
!     return false;
  
    /* If B has a fallthru edge to C, no need to move anything.  */
    if (e->flags & EDGE_FALLTHRU)
*************** merge_blocks (e, b, c, mode)
*** 391,412 ****
  		   b->index, c->index);
  	}
  
!       return 1;
      }
    /* Otherwise we will need to move code around.  Do that only if expensive
       transformations are allowed.  */
    else if (mode & CLEANUP_EXPENSIVE)
      {
!       edge tmp_edge, c_fallthru_edge;
!       int c_has_outgoing_fallthru;
!       int b_has_incoming_fallthru;
  
        /* Avoid overactive code motion, as the forwarder blocks should be
           eliminated by edge redirection instead.  One exception might have
  	 been if B is a forwarder block and C has no fallthru edge, but
  	 that should be cleaned up by bb-reorder instead.  */
        if (forwarder_block_p (b) || forwarder_block_p (c))
! 	return 0;
  
        /* We must make sure to not munge nesting of lexical blocks,
  	 and loop notes.  This is done by squeezing out all the notes
--- 390,411 ----
  		   b->index, c->index);
  	}
  
!       return true;
      }
    /* Otherwise we will need to move code around.  Do that only if expensive
       transformations are allowed.  */
    else if (mode & CLEANUP_EXPENSIVE)
      {
!       edge tmp_edge, b_fallthru_edge;
!       bool c_has_outgoing_fallthru;
!       bool b_has_incoming_fallthru;
  
        /* Avoid overactive code motion, as the forwarder blocks should be
           eliminated by edge redirection instead.  One exception might have
  	 been if B is a forwarder block and C has no fallthru edge, but
  	 that should be cleaned up by bb-reorder instead.  */
        if (forwarder_block_p (b) || forwarder_block_p (c))
! 	return false;
  
        /* We must make sure to not munge nesting of lexical blocks,
  	 and loop notes.  This is done by squeezing out all the notes
*************** merge_blocks (e, b, c, mode)
*** 416,474 ****
  	if (tmp_edge->flags & EDGE_FALLTHRU)
  	  break;
        c_has_outgoing_fallthru = (tmp_edge != NULL);
-       c_fallthru_edge = tmp_edge;
  
        for (tmp_edge = b->pred; tmp_edge; tmp_edge = tmp_edge->pred_next)
  	if (tmp_edge->flags & EDGE_FALLTHRU)
  	  break;
        b_has_incoming_fallthru = (tmp_edge != NULL);
! 
!       /* If B does not have an incoming fallthru, then it can be moved
! 	 immediately before C without introducing or modifying jumps.
! 	 C cannot be the first block, so we do not have to worry about
! 	 accessing a non-existent block.  */
!       if (! b_has_incoming_fallthru)
! 	return merge_blocks_move_predecessor_nojumps (b, c);
  
        /* Otherwise, we're going to try to move C after B.  If C does
  	 not have an outgoing fallthru, then it can be moved
  	 immediately after B without introducing or modifying jumps.  */
        if (! c_has_outgoing_fallthru)
! 	return merge_blocks_move_successor_nojumps (b, c);
! 
!       /* Otherwise, we'll need to insert an extra jump, and possibly
! 	 a new block to contain it.  We can't redirect to EXIT_BLOCK_PTR,
! 	 as we don't have explicit return instructions before epilogues
! 	 are generated, so give up on that case.  */
! 
!       if (c_fallthru_edge->dest != EXIT_BLOCK_PTR
! 	  && merge_blocks_move_successor_nojumps (b, c))
!         {
! 	  basic_block target = c_fallthru_edge->dest;
! 	  rtx barrier;
! 	  basic_block new;
! 
! 	  /* This is a dirty hack to avoid code duplication.
! 
! 	     Set edge to point to wrong basic block, so
! 	     redirect_edge_and_branch_force will do the trick
! 	     and rewire edge back to the original location.  */
! 	  redirect_edge_succ (c_fallthru_edge, ENTRY_BLOCK_PTR);
! 	  new = redirect_edge_and_branch_force (c_fallthru_edge, target);
! 
! 	  /* We've just created barrier, but another barrier is
! 	     already present in the stream.  Avoid the duplicate.  */
! 	  barrier = next_nonnote_insn (new ? new->end : b->end);
! 	  if (GET_CODE (barrier) != BARRIER)
! 	    abort ();
! 	  flow_delete_insn (barrier);
  
! 	  return 1;
!         }
  
!       return 0;
      }
!   return 0;
  }
  
  /* Look through the insns at the end of BB1 and BB2 and find the longest
--- 415,451 ----
  	if (tmp_edge->flags & EDGE_FALLTHRU)
  	  break;
        c_has_outgoing_fallthru = (tmp_edge != NULL);
  
        for (tmp_edge = b->pred; tmp_edge; tmp_edge = tmp_edge->pred_next)
  	if (tmp_edge->flags & EDGE_FALLTHRU)
  	  break;
        b_has_incoming_fallthru = (tmp_edge != NULL);
!       b_fallthru_edge = tmp_edge;
  
        /* Otherwise, we're going to try to move C after B.  If C does
  	 not have an outgoing fallthru, then it can be moved
  	 immediately after B without introducing or modifying jumps.  */
        if (! c_has_outgoing_fallthru)
! 	{
! 	  merge_blocks_move_successor_nojumps (b, c);
! 	  return true;
! 	}
  
!       /* If B does not have an incoming fallthru, then it can be moved
! 	 immediately before C without introducing or modifying jumps.
! 	 C cannot be the first block, so we do not have to worry about
! 	 accessing a non-existent block.  */
  
!       if (b_has_incoming_fallthru)
! 	{
! 	  if (b_fallthru_edge->src == ENTRY_BLOCK_PTR)
! 	    return false;
! 	  force_nonfallthru (b_fallthru_edge);
! 	}
!       merge_blocks_move_predecessor_nojumps (b, c);
!       return true;
      }
!   return false;
  }
  
  /* Look through the insns at the end of BB1 and BB2 and find the longest


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