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]
Other format: [Raw text]

cfg_layout mode CFG manipulation functions


Hi,
this patch implements basic RTL manipulation API in the cfglayout mode.  I
tested it by turning cfgcleanup and loop discovery into cfglayout mode and it
appears to work well (except the fact that it complettely messes up loop notes
but hopefully these won't be there forever :)

Several things are easier than in the normal mode so I hope it won't
have too many dead ends.

Regtested/bootstrapped on i386, OK?

Tue Jun 17 23:12:11 CEST 2003  Jan Hubicka  <jh@suse.cz>
	* cfgrtl.c: Update comments.
	(try_redirect_by_replacing_jump): New argument.
	(redirect_branch_edge): Break out from ...
	(rtl_redirect_edge_and_branch): ... this one.
	(update_cfg_after_block_merging): Break out from ...
	(rtl_merge_blocks): ... this one.
	(cfg_layout_split_edge): New.
	(cfg_layout_merge_blocks): New.
	(cfg_layout_can_merge_blocks_p): New.
	(cfg_layout_redirect_edge_and_branch): Reorganize.
	(cfg_layout_rtl_cfg_hooks): Fill in.
	(cfg_layout_delete_block): Kill barriers.
	* cfganal.c (can_fallthru): Deal with exit blocks
	* cfglayout.c (cfg_layout_function_header): New function
	(record_effective_endpoints): Record function header.
	(fixup_reorder_chain): Fixup dead jumptables; place header
*** cfgrtl.c.old3	Tue Jun 17 17:56:51 2003
--- cfgrtl.c	Tue Jun 17 23:10:15 2003
*************** Software Foundation, 59 Temple Place - S
*** 23,42 ****
     that are aware of the RTL intermediate language.
  
     Available functionality:
       - CFG-aware instruction chain manipulation
  	 delete_insn, delete_insn_chain
!      - Basic block manipulation
! 	 rtl_create_basic_block, rtl_delete_block,rtl_split_block,
! 	 rtl_merge_block
       - Infrastructure to determine quickly basic block for insn
  	 compute_bb_for_insn, update_bb_for_insn, set_block_for_insn,
       - Edge redirection with updating and optimizing of insn chain
! 	 block_label, rtl_redirect_edge_and_branch,
! 	 rtl_redirect_edge_and_branch_force, tidy_fallthru_edge, force_nonfallthru
!      - Edge splitting and committing to edges
! 	 rtl_split_edge, insert_insn_on_edge, commit_edge_insertions
!      - CFG updating after constant propagation
! 	 purge_dead_edges, purge_all_dead_edges   */
  
  #include "config.h"
  #include "system.h"
--- 23,41 ----
     that are aware of the RTL intermediate language.
  
     Available functionality:
+      - Basic CFG/RTL manipulation API documented in cfghooks.h
       - CFG-aware instruction chain manipulation
  	 delete_insn, delete_insn_chain
!      - Edge splitting and committing to edges
! 	 insert_insn_on_edge, commit_edge_insertions
!      - CFG updating after insn simplification
! 	 purge_dead_edges, purge_all_dead_edges
! 
!    Functions not supposed for generic use:
       - Infrastructure to determine quickly basic block for insn
  	 compute_bb_for_insn, update_bb_for_insn, set_block_for_insn,
       - Edge redirection with updating and optimizing of insn chain
! 	 block_label, tidy_fallthru_edge, force_nonfallthru  */
  
  #include "config.h"
  #include "system.h"
*************** rtx tail_recursion_label_list;
*** 72,82 ****
  static int can_delete_note_p		PARAMS ((rtx));
  static int can_delete_label_p		PARAMS ((rtx));
  static void commit_one_edge_insertion	PARAMS ((edge, int));
! static bool try_redirect_by_replacing_jump PARAMS ((edge, basic_block));
  static rtx last_loop_beg_note		PARAMS ((rtx));
  static bool back_edge_of_syntactic_loop_p PARAMS ((basic_block, basic_block));
  basic_block force_nonfallthru_and_redirect PARAMS ((edge, basic_block));
  static basic_block rtl_split_edge	PARAMS ((edge));
  static int rtl_verify_flow_info		PARAMS ((void));
  static edge cfg_layout_split_block	PARAMS ((basic_block, void *));
  static bool cfg_layout_redirect_edge_and_branch	PARAMS ((edge, basic_block));
--- 71,83 ----
  static int can_delete_note_p		PARAMS ((rtx));
  static int can_delete_label_p		PARAMS ((rtx));
  static void commit_one_edge_insertion	PARAMS ((edge, int));
! static bool try_redirect_by_replacing_jump PARAMS ((edge, basic_block, int));
! static bool redirect_branch_edge	PARAMS ((edge, basic_block));
  static rtx last_loop_beg_note		PARAMS ((rtx));
  static bool back_edge_of_syntactic_loop_p PARAMS ((basic_block, basic_block));
  basic_block force_nonfallthru_and_redirect PARAMS ((edge, basic_block));
  static basic_block rtl_split_edge	PARAMS ((edge));
+ static basic_block cfg_layout_split_edge PARAMS ((edge));
  static int rtl_verify_flow_info		PARAMS ((void));
  static edge cfg_layout_split_block	PARAMS ((basic_block, void *));
  static bool cfg_layout_redirect_edge_and_branch	PARAMS ((edge, basic_block));
*************** static basic_block rtl_create_basic_bloc
*** 92,97 ****
--- 93,101 ----
  static basic_block cfg_layout_create_basic_block PARAMS ((void *, void *, basic_block));
  static void rtl_merge_blocks		PARAMS ((basic_block, basic_block));
  static bool rtl_can_merge_blocks	PARAMS ((basic_block, basic_block));
+ static void update_cfg_after_block_merging PARAMS ((basic_block, basic_block));
+ static void cfg_layout_merge_blocks	PARAMS ((basic_block, basic_block));
+ static bool cfg_layout_can_merge_blocks_p	PARAMS ((basic_block, basic_block));
  
  /* Return true if NOTE is not one of the ones that must be kept paired,
     so that we may simply delete it.  */
*************** rtl_split_block (bb, insnp)
*** 545,550 ****
--- 549,582 ----
    return new_edge;
  }
  
+ /* Assume that the code of basic block B has been merged into A.
+    Do corresponding CFG updates:  redirect edges accordingly etc.  */
+ static void
+ update_cfg_after_block_merging (a, b)
+      basic_block a, b;
+ {
+   edge e;
+ 
+   /* Normally there should only be one successor of A and that is B, but
+      partway though the merge of blocks for conditional_execution we'll
+      be merging a TEST block with THEN and ELSE successors.  Free the
+      whole lot of them and hope the caller knows what they're doing.  */
+   while (a->succ)
+     remove_edge (a->succ);
+ 
+   /* Adjust the edges out of B for the new owner.  */
+   for (e = b->succ; e; e = e->succ_next)
+     e->src = a;
+   a->succ = b->succ;
+   a->flags |= b->flags;
+ 
+   /* B hasn't quite yet ceased to exist.  Attempt to prevent mishap.  */
+   b->pred = b->succ = NULL;
+   a->global_live_at_end = b->global_live_at_end;
+ 
+   expunge_block (b);
+ }
+ 
  /* Blocks A and B are to be merged into a single block A.  The insns
     are already contiguous, hence `nomove'.  */
  
*************** rtl_merge_blocks (a, b)
*** 621,644 ****
    else if (GET_CODE (NEXT_INSN (a_end)) == BARRIER)
      del_first = NEXT_INSN (a_end);
  
!   /* Normally there should only be one successor of A and that is B, but
!      partway though the merge of blocks for conditional_execution we'll
!      be merging a TEST block with THEN and ELSE successors.  Free the
!      whole lot of them and hope the caller knows what they're doing.  */
!   while (a->succ)
!     remove_edge (a->succ);
! 
!   /* Adjust the edges out of B for the new owner.  */
!   for (e = b->succ; e; e = e->succ_next)
!     e->src = a;
!   a->succ = b->succ;
!   a->flags |= b->flags;
! 
!   /* B hasn't quite yet ceased to exist.  Attempt to prevent mishap.  */
!   b->pred = b->succ = NULL;
!   a->global_live_at_end = b->global_live_at_end;
! 
!   expunge_block (b);
  
    /* Delete everything marked above as well as crap that might be
       hanging out between the two blocks.  */
--- 645,651 ----
    else if (GET_CODE (NEXT_INSN (a_end)) == BARRIER)
      del_first = NEXT_INSN (a_end);
  
!   update_cfg_after_block_merging (a, b);
  
    /* Delete everything marked above as well as crap that might be
       hanging out between the two blocks.  */
*************** block_label (block)
*** 703,711 ****
     return values are equivalent to redirect_edge_and_branch.  */
  
  static bool
! try_redirect_by_replacing_jump (e, target)
       edge e;
       basic_block target;
  {
    basic_block src = e->src;
    rtx insn = src->end, kill_from;
--- 710,719 ----
     return values are equivalent to redirect_edge_and_branch.  */
  
  static bool
! try_redirect_by_replacing_jump (e, target, in_cfglayout)
       edge e;
       basic_block target;
+      int in_cfglayout;
  {
    basic_block src = e->src;
    rtx insn = src->end, kill_from;
*************** try_redirect_by_replacing_jump (e, targe
*** 737,750 ****
  #endif
  
    /* See if we can create the fallthru edge.  */
!   if (can_fallthru (src, target))
      {
        if (rtl_dump_file)
  	fprintf (rtl_dump_file, "Removing jump %i.\n", INSN_UID (insn));
        fallthru = 1;
  
        /* Selectively unlink whole insn chain.  */
!       delete_insn_chain (kill_from, PREV_INSN (target->head));
      }
  
    /* If this already is simplejump, redirect it.  */
--- 745,782 ----
  #endif
  
    /* See if we can create the fallthru edge.  */
!   if (in_cfglayout || can_fallthru (src, target))
      {
        if (rtl_dump_file)
  	fprintf (rtl_dump_file, "Removing jump %i.\n", INSN_UID (insn));
        fallthru = 1;
  
        /* Selectively unlink whole insn chain.  */
!       if (in_cfglayout)
! 	{
! 	  rtx insn = src->rbi->footer;
! 
!           delete_insn_chain (kill_from, src->end);
! 
! 	  /* Remove barriers but keep jumptables.  */
! 	  while (insn)
! 	    {
! 	      if (GET_CODE (insn) == BARRIER)
! 		{
! 		  if (PREV_INSN (insn))
! 		    NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
! 		  else
! 		    src->rbi->footer = NEXT_INSN (insn);
! 		  if (NEXT_INSN (insn))
! 		    PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
! 		}
! 	      if (GET_CODE (insn) == CODE_LABEL)
! 		break;
! 	      insn = NEXT_INSN (insn);
! 	    }
! 	}
!       else
!         delete_insn_chain (kill_from, PREV_INSN (target->head));
      }
  
    /* If this already is simplejump, redirect it.  */
*************** last_loop_beg_note (insn)
*** 841,858 ****
    return last;
  }
  
! /* Attempt to change code to redirect edge E to TARGET.  Don't do that on
!    expense of adding new instructions or reordering basic blocks.
! 
!    Function can be also called with edge destination equivalent to the TARGET.
!    Then it should try the simplifications and do nothing if none is possible.
! 
!    Return true if transformation succeeded.  We still return false in case E
!    already destinated TARGET and we didn't managed to simplify instruction
!    stream.  */
! 
  static bool
! rtl_redirect_edge_and_branch (e, target)
       edge e;
       basic_block target;
  {
--- 873,881 ----
    return last;
  }
  
! /* Redirect edge representing branch of (un)conditional jump or tablejump.  */
  static bool
! redirect_branch_edge (e, target)
       edge e;
       basic_block target;
  {
*************** rtl_redirect_edge_and_branch (e, target)
*** 861,878 ****
    basic_block src = e->src;
    rtx insn = src->end;
  
-   if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
-     return false;
- 
-   if (try_redirect_by_replacing_jump (e, target))
-     return true;
- 
-   /* Do this fast path late, as we want above code to simplify for cases
-      where called on single edge leaving basic block containing nontrivial
-      jump insn.  */
-   else if (e->dest == target)
-     return false;
- 
    /* We can only redirect non-fallthru edges of jump insn.  */
    if (e->flags & EDGE_FALLTHRU)
      return false;
--- 884,889 ----
*************** rtl_redirect_edge_and_branch (e, target)
*** 945,950 ****
--- 956,992 ----
  
    if (e->dest != target)
      redirect_edge_succ_nodup (e, target);
+   return true;
+ }
+ 
+ /* Attempt to change code to redirect edge E to TARGET.  Don't do that on
+    expense of adding new instructions or reordering basic blocks.
+ 
+    Function can be also called with edge destination equivalent to the TARGET.
+    Then it should try the simplifications and do nothing if none is possible.
+ 
+    Return true if transformation succeeded.  We still return false in case E
+    already destinated TARGET and we didn't managed to simplify instruction
+    stream.  */
+ 
+ static bool
+ rtl_redirect_edge_and_branch (e, target)
+      edge e;
+      basic_block target;
+ {
+   if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
+     return false;
+ 
+   if (try_redirect_by_replacing_jump (e, target, false))
+     return true;
+ 
+   /* Do this fast path late, as we want above code to simplify for cases
+      where called on single edge leaving basic block containing nontrivial
+      jump insn.  */
+   else if (e->dest == target)
+     return false;
+   else if (!redirect_branch_edge (e, target))
+     return false;
  
    return true;
  }
*************** cfg_layout_redirect_edge_and_branch (e, 
*** 2324,2337 ****
       basic_block dest;
  {
    basic_block src = e->src;
-   basic_block old_next_bb = src->next_bb;
    bool ret;
  
    /* Redirect_edge_and_branch may decide to turn branch into fallthru edge
       in the case the basic block appears to be in sequence.  Avoid this
       transformation.  */
  
-   src->next_bb = NULL;
    if (e->flags & EDGE_FALLTHRU)
      {
        /* Redirect any branch edges unified with the fallthru one.  */
--- 2366,2398 ----
       basic_block dest;
  {
    basic_block src = e->src;
    bool ret;
  
+   if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
+     return false;
+ 
+   if (e->src != ENTRY_BLOCK_PTR
+       && try_redirect_by_replacing_jump (e, dest, true))
+     return true;
+ 
+   if (e->dest == dest)
+     return true;
+ 
+   if (e->src == ENTRY_BLOCK_PTR
+       && (e->flags & EDGE_FALLTHRU) && !(e->flags & EDGE_COMPLEX))
+     {
+       if (rtl_dump_file)
+ 	fprintf (rtl_dump_file, "Redirecting entry edge from bb %i to %i\n",
+ 		 e->src->index, dest->index);
+ 
+       redirect_edge_succ (e, dest);
+       return true;
+     }
+ 
    /* Redirect_edge_and_branch may decide to turn branch into fallthru edge
       in the case the basic block appears to be in sequence.  Avoid this
       transformation.  */
  
    if (e->flags & EDGE_FALLTHRU)
      {
        /* Redirect any branch edges unified with the fallthru one.  */
*************** cfg_layout_redirect_edge_and_branch (e, 
*** 2353,2372 ****
  	    delete_insn (src->end);
  	}
        redirect_edge_succ_nodup (e, dest);
  
        ret = true;
      }
    else
!     ret = rtl_redirect_edge_and_branch (e, dest);
  
    /* We don't want simplejumps in the insn stream during cfglayout.  */
    if (simplejump_p (src->end))
!     {
!       delete_insn (src->end);
!       delete_barrier (NEXT_INSN (src->end));
!       src->succ->flags |= EDGE_FALLTHRU;
!     }
!   src->next_bb = old_next_bb;
  
    return ret;
  }
--- 2414,2431 ----
  	    delete_insn (src->end);
  	}
        redirect_edge_succ_nodup (e, dest);
+       if (rtl_dump_file)
+ 	fprintf (rtl_dump_file, "Fallthru edge %i->%i redirected to %i\n",
+ 		 e->src->index, e->dest->index, dest->index);
  
        ret = true;
      }
    else
!     ret = redirect_branch_edge (e, dest);
  
    /* We don't want simplejumps in the insn stream during cfglayout.  */
    if (simplejump_p (src->end))
!     abort ();
  
    return ret;
  }
*************** cfg_layout_delete_block (bb)
*** 2406,2421 ****
    next = NEXT_INSN (bb->end);
    if (bb->rbi->footer)
      {
!       insn = bb->end;
!       NEXT_INSN (insn) = bb->rbi->footer;
!       PREV_INSN (bb->rbi->footer) = insn;
!       while (NEXT_INSN (insn))
! 	insn = NEXT_INSN (insn);
!       NEXT_INSN (insn) = next;
!       if (next)
! 	PREV_INSN (next) = insn;
!       else
! 	set_last_insn (insn);
      }
    if (bb->next_bb != EXIT_BLOCK_PTR)
      to = &bb->next_bb->rbi->header;
--- 2465,2499 ----
    next = NEXT_INSN (bb->end);
    if (bb->rbi->footer)
      {
!       insn = bb->rbi->footer;
!       while (insn)
! 	{
! 	  if (GET_CODE (insn) == BARRIER)
! 	    {
! 	      if (PREV_INSN (insn))
! 		NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
! 	      else
! 		bb->rbi->footer = NEXT_INSN (insn);
! 	      if (NEXT_INSN (insn))
! 		PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
! 	    }
! 	  if (GET_CODE (insn) == CODE_LABEL)
! 	    break;
! 	  insn = NEXT_INSN (insn);
! 	}
!       if (bb->rbi->footer)
! 	{
! 	  insn = bb->end;
! 	  NEXT_INSN (insn) = bb->rbi->footer;
! 	  PREV_INSN (bb->rbi->footer) = insn;
! 	  while (NEXT_INSN (insn))
! 	    insn = NEXT_INSN (insn);
! 	  NEXT_INSN (insn) = next;
! 	  if (next)
! 	    PREV_INSN (next) = insn;
! 	  else
! 	    set_last_insn (insn);
! 	}
      }
    if (bb->next_bb != EXIT_BLOCK_PTR)
      to = &bb->next_bb->rbi->header;
*************** cfg_layout_delete_block (bb)
*** 2445,2450 ****
--- 2504,2638 ----
      }
  }
  
+ /* Merge block A and B, abort when it is not possible.  */
+ static void
+ cfg_layout_merge_blocks (a, b)
+      basic_block a;
+      basic_block b;
+ {
+ #ifdef ENABLE_CHECKING
+   if (!cfg_layout_can_merge_blocks_p (a, b))
+     abort ();
+ #endif
+ 
+   /* If there was a CODE_LABEL beginning B, delete it.  */
+   if (GET_CODE (b->head) == CODE_LABEL)
+     delete_insn (b->head);
+ 
+   /* We should have fallthru edge in a, or we can do dummy redirection to get
+      it cleaned up.  */
+   if (GET_CODE (a->end) == JUMP_INSN)
+     redirect_edge_and_branch (a->succ, b);
+   if (GET_CODE (a->end) == JUMP_INSN)
+     abort ();
+ 
+   /* Possible line number notes should appear in between.  */
+   if (b->rbi->header)
+     {
+       rtx first = a->end, last;
+ 
+       last = emit_insn_after (b->rbi->header, a->end);
+       delete_insn_chain (NEXT_INSN (first), last);
+       b->rbi->header = NULL;
+     }
+ 
+   /* In the case basic blocks are not adjacent, move them around.  */
+   if (NEXT_INSN (a->end) != b->head)
+     {
+       rtx first = unlink_insn_chain (b->head, b->end);
+ 
+       emit_insn_after (first, a->end);
+       /* Skip possible DELETED_LABEL insn.  */
+       if (!NOTE_INSN_BASIC_BLOCK_P (first))
+ 	first = NEXT_INSN (first);
+       if (!NOTE_INSN_BASIC_BLOCK_P (first))
+ 	abort ();
+       b->head = NULL;
+       delete_insn (first);
+     }
+   /* Otherwise just re-associate the instructions.  */
+   else
+     {
+       rtx insn;
+ 
+       for (insn = b->head; insn != NEXT_INSN (b->end); insn = NEXT_INSN (insn))
+ 	set_block_for_insn (insn, a);
+       insn = b->head;
+       /* Skip possible DELETED_LABEL insn.  */
+       if (!NOTE_INSN_BASIC_BLOCK_P (insn))
+ 	insn = NEXT_INSN (insn);
+       if (!NOTE_INSN_BASIC_BLOCK_P (insn))
+ 	abort ();
+       b->head = NULL;
+       a->end = b->end;
+       delete_insn (insn);
+     }
+ 
+   /* Possible tablejumps and barriers should appear after the block.  */
+   if (b->rbi->footer)
+     {
+       if (!a->rbi->footer)
+ 	a->rbi->footer = b->rbi->footer;
+       else
+ 	{
+ 	  rtx last = a->rbi->footer;
+ 
+ 	  while (NEXT_INSN (last))
+ 	    last = NEXT_INSN (last);
+ 	  NEXT_INSN (last) = b->rbi->footer;
+ 	  PREV_INSN (b->rbi->footer) = last;
+ 	}
+       b->rbi->footer = NULL;
+     }
+ 
+   if (rtl_dump_file)
+     fprintf (rtl_dump_file, "Merged blocks %d and %d.\n",
+ 	     a->index, b->index);
+ 
+   update_cfg_after_block_merging (a, b);
+ }
+ 
+ /* return true when blocks A and B can be safely merged.  */
+ static bool
+ cfg_layout_can_merge_blocks_p (a, b)
+      basic_block a;
+      basic_block b;
+ {
+   /* There must be exactly one edge in between the blocks.  */
+   return (a->succ && !a->succ->succ_next && a->succ->dest == b
+ 	  && !b->pred->pred_next && a != b
+ 	  /* Must be simple edge.  */
+ 	  && !(a->succ->flags & EDGE_COMPLEX)
+ 	  && a != ENTRY_BLOCK_PTR && b != EXIT_BLOCK_PTR
+ 	  /* If the jump insn has side effects,
+ 	     we can't kill the edge.  */
+ 	  && (GET_CODE (a->end) != JUMP_INSN
+ 	      || (flow2_completed
+ 		  ? simplejump_p (a->end) : onlyjump_p (a->end))));
+ }
+ 
+ /* Split edge E.  */
+ static basic_block
+ cfg_layout_split_edge (e)
+      edge e;
+ {
+   edge new_e;
+   basic_block new_bb =
+     create_basic_block (e->src != ENTRY_BLOCK_PTR
+ 			? NEXT_INSN (e->src-> end) : get_insns (),
+ 			NULL_RTX, e->src);
+ 
+   new_bb->count = e->count;
+   new_bb->frequency = EDGE_FREQUENCY (e);
+ 
+   new_e = make_edge (new_bb, e->dest, EDGE_FALLTHRU);
+   new_e->probability = REG_BR_PROB_BASE;
+   new_e->count = e->count;
+   redirect_edge_and_branch_force (e, new_bb);
+ 
+   return new_bb;
+ }
+ 
  /* Implementation of CFG manipulation for linearized RTL.  */
  struct cfg_hooks rtl_cfg_hooks = {
    rtl_verify_flow_info,
*************** struct cfg_hooks rtl_cfg_hooks = {
*** 2454,2460 ****
    rtl_redirect_edge_and_branch_force,
    rtl_delete_block,
    rtl_split_block,
!   rtl_can_merge_blocks,  /* can_merge_blocks_p */
    rtl_merge_blocks,
    rtl_split_edge
  };
--- 2642,2648 ----
    rtl_redirect_edge_and_branch_force,
    rtl_delete_block,
    rtl_split_block,
!   rtl_can_merge_blocks,
    rtl_merge_blocks,
    rtl_split_edge
  };
*************** struct cfg_hooks rtl_cfg_hooks = {
*** 2464,2477 ****
     This representation will hopefully become the default one in future
     version of the compiler.  */
  struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
!   rtl_verify_flow_info_1,   /* verify_flow_info.  */
    rtl_dump_bb,
    cfg_layout_create_basic_block,
    cfg_layout_redirect_edge_and_branch,
    cfg_layout_redirect_edge_and_branch_force,
    cfg_layout_delete_block,
    cfg_layout_split_block,
!   NULL,  /* can_merge_blocks_p */
!   NULL,  /* merge_blocks  */
!   NULL  /* split_edge.  */
  };
--- 2652,2665 ----
     This representation will hopefully become the default one in future
     version of the compiler.  */
  struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
!   rtl_verify_flow_info_1,
    rtl_dump_bb,
    cfg_layout_create_basic_block,
    cfg_layout_redirect_edge_and_branch,
    cfg_layout_redirect_edge_and_branch_force,
    cfg_layout_delete_block,
    cfg_layout_split_block,
!   cfg_layout_can_merge_blocks_p,
!   cfg_layout_merge_blocks,
!   cfg_layout_split_edge
  };
*** cfganal.c.old3	Tue Jun 17 21:35:29 2003
--- cfganal.c	Tue Jun 17 21:36:42 2003
*************** can_fallthru (src, target)
*** 110,121 ****
       basic_block src, target;
  {
    rtx insn = src->end;
!   rtx insn2 = target->head;
  
    if (src->next_bb != target)
      return 0;
  
!   if (!active_insn_p (insn2))
      insn2 = next_active_insn (insn2);
  
    /* ??? Later we may add code to move jump tables offline.  */
--- 110,121 ----
       basic_block src, target;
  {
    rtx insn = src->end;
!   rtx insn2 = target == EXIT_BLOCK_PTR ? NULL : target->head;
  
    if (src->next_bb != target)
      return 0;
  
!   if (insn2 && !active_insn_p (insn2))
      insn2 = next_active_insn (insn2);
  
    /* ??? Later we may add code to move jump tables offline.  */
*** cfglayout.c.old3	Tue Jun 17 18:12:58 2003
--- cfglayout.c	Tue Jun 17 23:21:17 2003
*************** fixup_reorder_chain ()
*** 770,775 ****
--- 769,784 ----
      }
    prev_bb->next_bb = EXIT_BLOCK_PTR;
    EXIT_BLOCK_PTR->prev_bb = prev_bb;
+ 
+   /* Anoying special case - jump around dead jumptables left in the code.  */
+   FOR_EACH_BB (bb)
+     {
+       edge e;
+       for (e = bb->succ; e && !(e->flags & EDGE_FALLTHRU); e = e->succ_next)
+ 	continue;
+       if (e && !can_fallthru (e->src, e->dest))
+ 	force_nonfallthru (e);
+     }
  }
  
  /* Perform sanity checks on the insn chain.
*** cfglayout.c.old3	Tue Jun 17 18:12:58 2003
--- cfglayout.c	Wed Jun 18 00:59:21 2003
*************** extern struct obstack flow_obstack;
*** 43,49 ****
  alloc_pool cfg_layout_pool;
  
  /* Holds the interesting trailing notes for the function.  */
! rtx cfg_layout_function_footer;
  
  static rtx skip_insns_after_block	PARAMS ((basic_block));
  static void record_effective_endpoints	PARAMS ((void));
--- 43,49 ----
  alloc_pool cfg_layout_pool;
  
  /* Holds the interesting trailing notes for the function.  */
! rtx cfg_layout_function_footer, cfg_layout_function_header;
  
  static rtx skip_insns_after_block	PARAMS ((basic_block));
  static void record_effective_endpoints	PARAMS ((void));
*************** label_for_bb (bb)
*** 196,204 ****
  static void
  record_effective_endpoints ()
  {
!   rtx next_insn = get_insns ();
    basic_block bb;
  
    FOR_EACH_BB (bb)
      {
        rtx end;
--- 195,222 ----
  static void
  record_effective_endpoints ()
  {
!   rtx next_insn;
    basic_block bb;
+   rtx insn;
+ 
+   for (insn = get_insns ();
+        NEXT_INSN (insn) && GET_CODE (insn) == NOTE;
+        insn = NEXT_INSN (insn))
+     {
+       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
+ 	{
+ 	  insn = NULL;
+ 	  break;
+ 	 }
+       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
+ 	break;
+     }
+   if (insn)
+     cfg_layout_function_header = unlink_insn_chain (get_insns (), insn);
+   else
+     cfg_layout_function_header = NULL_RTX;
  
+   next_insn = get_insns ();
    FOR_EACH_BB (bb)
      {
        rtx end;
*************** fixup_reorder_chain ()
*** 544,549 ****
--- 562,575 ----
    int index;
    rtx insn = NULL;
  
+   if (cfg_layout_function_header)
+     {
+       set_first_insn (cfg_layout_function_header);
+       insn = cfg_layout_function_header;
+       while (NEXT_INSN (insn))
+ 	insn = NEXT_INSN (insn);
+     }
+ 
    /* First do the bulk reordering -- rechain the blocks without regard to
       the needed changes to jumps and labels.  */
  
*************** fixup_reorder_chain ()
*** 770,775 ****
--- 796,811 ----
      }
    prev_bb->next_bb = EXIT_BLOCK_PTR;
    EXIT_BLOCK_PTR->prev_bb = prev_bb;
+ 
+   /* Anoying special case - jump around dead jumptables left in the code.  */
+   FOR_EACH_BB (bb)
+     {
+       edge e;
+       for (e = bb->succ; e && !(e->flags & EDGE_FALLTHRU); e = e->succ_next)
+ 	continue;
+       if (e && !can_fallthru (e->src, e->dest))
+ 	force_nonfallthru (e);
+     }
  }
  
  /* Perform sanity checks on the insn chain.


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