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]

Re: [tree-ssa] switch_expr lowering, part 1


> On Thu, Oct 30, 2003 at 10:16:38PM +0100, Jan Hubicka wrote:
> > > (1) Lots of Wswitch failures.  This stuff shouldn't have been in the
> > >     tree->rtl converter in the first place.  Will be moved to the front
> > >     ends where it belongs.
> > > 
> > > (2) tree-ssa/20030814-2.c fails.  I thought I took care of this with
> > >     the tree-ssa-dom.c part of the patch; havn't looked at why that 
> > >     didn't work yet.
> > > 
> > > (3) Two new Java bytecode failures.  I presume I have to change 
> > >     something in the bytecode emission path.
> > > 
> > > Future work includes
> > > 
> > > (4) Jump threading should adjust case target labels.
> > > 
> > > (5) Qsort SWITCH_LABELS vector so that we can bsearch for value
> > >     edges during simplification and, 
> > > 
> > > (6) Case targets should be coelesed into ranges.  This is done by
> > >     the tree->rtl converter, but should be easier with already sorted
> > >     labels.  Also, the tree->rtl coelesing is (effectively) disabled
> > >     until jump threading is done, so that all cases that go to the 
> > >     same block reference the same label.  See #if 0 in same_case_target_p.
> > > 
> > > (7) Enormous simplifications in the tree->rtl path.
> [...]
> > How much of this have you been working on already?
> 
> I've finished (2) and (3), though (2) isn't committed yet.  I'm
> still trying to work out how to approach (1).
> 
> > I have some code to map CFG manipulation routines to trees (so we can
> > redirect edges and split blocks)
> 
> This is clearly the Correct Way to attack (4), as well as cleaning
> up code in tree-cfg.c.  Doing this properly isn't as easy as it ought
> to be yet.  I hope to have this done by next Wednesday at the latest.

Hi,
this implements theeasy part of edge redirection code (basically
updating Zdenek's thread_jump to match redirect_edge_and_branch
interface).  I extended the RTL interface to return edges as needed by
tree code updating SSA form and massaged around the tree code to avoid
producing duplicated edges and unnecesary jumps like we do for RTL.

I would like to proceed by BB splittling and merging so we can fire up
loop datastructures properly now.

OK?

Honza

	* cfghooks.h (redirect_edge_and_branch hook): Make it return edge.
	* cfgrtl.c (cfg_layout_redirect_edge_and_branch,
	rtl_redirect_edge_and_branch, try_redirect_by_replacing_jump):
	Update to new interface.
	* tree-cfg.c (tree_cfg_hooks): Move to end of file; set
	redirect_edge_and_branch and redirect_edge_and_branch_force.
	(thread_jumps): Use redirect_edge_and_branch.
	(tree_block_label): new; break out of thread_edge.
	(tree_try_redirect_by_replacing_jump): New.
	(thread_edge): Rename to tree_redirect_edge_and_branch; deal sanely
	with unusual edges; preserve profile.
	(tree_redirect_edge_and_branch_force): New.
	* tree-flow.h (ssa_redirect_edge): Declare.
	* tree-ssa.dom.c (tree_ssa_dominator_optimize): Use redirect_edge_and_branch.
	* tree-ssa.c (ssa_redirect_edge): New.
diff -c3p old/gcc/cfghooks.h gcc/cfghooks.h
*** old/gcc/cfghooks.h	Tue Oct 14 19:31:31 2003
--- gcc/cfghooks.h	Sat Nov  1 10:59:43 2003
*************** struct cfg_hooks
*** 35,43 ****
    basic_block (*create_basic_block) (void *head, void *end, basic_block after);
  
    /* Redirect edge E to the given basic block B and update underlying program
!      representation.  Returns false when edge is not easily redirectable for
!      whatever reason.  */
!   bool (*redirect_edge_and_branch) (edge e, basic_block b);
  
    /* Same as the above but allows redirecting of fallthru edges.  In that case
       newly created forwarder basic block is returned.  It aborts when called
--- 35,44 ----
    basic_block (*create_basic_block) (void *head, void *end, basic_block after);
  
    /* Redirect edge E to the given basic block B and update underlying program
!      representation.  Returns edge representing redirected branch (that may not
!      be equivalent to E in the case of duplicate edges being removed) or NULL
!      if edge is not easily redirectable for whatever reason.  */
!   edge (*redirect_edge_and_branch) (edge e, basic_block b);
  
    /* Same as the above but allows redirecting of fallthru edges.  In that case
       newly created forwarder basic block is returned.  It aborts when called
diff -c3p old/gcc/cfgrtl.c gcc/cfgrtl.c
*** old/gcc/cfgrtl.c	Tue Oct 14 19:31:31 2003
--- gcc/cfgrtl.c	Sat Nov  1 11:09:55 2003
*************** basic_block force_nonfallthru_and_redire
*** 78,89 ****
  static basic_block rtl_split_edge (edge);
  static int rtl_verify_flow_info (void);
  static edge cfg_layout_split_block (basic_block, void *);
! static bool cfg_layout_redirect_edge_and_branch (edge, basic_block);
  static basic_block cfg_layout_redirect_edge_and_branch_force (edge, basic_block);
  static void cfg_layout_delete_block (basic_block);
  static void rtl_delete_block (basic_block);
  static basic_block rtl_redirect_edge_and_branch_force (edge, basic_block);
! static bool rtl_redirect_edge_and_branch (edge, basic_block);
  static edge rtl_split_block (basic_block, void *);
  static void rtl_dump_bb (basic_block, FILE *, int);
  static int rtl_verify_flow_info_1 (void);
--- 78,89 ----
  static basic_block rtl_split_edge (edge);
  static int rtl_verify_flow_info (void);
  static edge cfg_layout_split_block (basic_block, void *);
! static edge cfg_layout_redirect_edge_and_branch (edge, basic_block);
  static basic_block cfg_layout_redirect_edge_and_branch_force (edge, basic_block);
  static void cfg_layout_delete_block (basic_block);
  static void rtl_delete_block (basic_block);
  static basic_block rtl_redirect_edge_and_branch_force (edge, basic_block);
! static edge rtl_redirect_edge_and_branch (edge, basic_block);
  static edge rtl_split_block (basic_block, void *);
  static void rtl_dump_bb (basic_block, FILE *, int);
  static int rtl_verify_flow_info_1 (void);
*************** block_label (basic_block block)
*** 681,687 ****
     apply only if all edges now point to the same block.  The parameters and
     return values are equivalent to redirect_edge_and_branch.  */
  
! static bool
  try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
  {
    basic_block src = e->src;
--- 681,687 ----
     apply only if all edges now point to the same block.  The parameters and
     return values are equivalent to redirect_edge_and_branch.  */
  
! static edge
  try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
  {
    basic_block src = e->src;
*************** try_redirect_by_replacing_jump (edge e, 
*** 696,709 ****
        break;
  
    if (tmp || !onlyjump_p (insn))
!     return false;
    if ((!optimize || flow2_completed) && tablejump_p (insn, NULL, NULL))
!     return false;
  
    /* Avoid removing branch with side effects.  */
    set = single_set (insn);
    if (!set || side_effects_p (set))
!     return false;
  
    /* In case we zap a conditional jump, we'll need to kill
       the cc0 setter too.  */
--- 696,709 ----
        break;
  
    if (tmp || !onlyjump_p (insn))
!     return NULL;
    if ((!optimize || flow2_completed) && tablejump_p (insn, NULL, NULL))
!     return NULL;
  
    /* Avoid removing branch with side effects.  */
    set = single_set (insn);
    if (!set || side_effects_p (set))
!     return NULL;
  
    /* In case we zap a conditional jump, we'll need to kill
       the cc0 setter too.  */
*************** try_redirect_by_replacing_jump (edge e, 
*** 752,772 ****
    else if (simplejump_p (insn))
      {
        if (e->dest == target)
! 	return false;
        if (rtl_dump_file)
  	fprintf (rtl_dump_file, "Redirecting jump %i from %i to %i.\n",
  		 INSN_UID (insn), e->dest->index, target->index);
        if (!redirect_jump (insn, block_label (target), 0))
  	{
  	  if (target == EXIT_BLOCK_PTR)
! 	    return false;
  	  abort ();
  	}
      }
  
    /* Cannot do anything for target exit block.  */
    else if (target == EXIT_BLOCK_PTR)
!     return false;
  
    /* Or replace possibly complicated jump insn by simple jump insn.  */
    else
--- 752,772 ----
    else if (simplejump_p (insn))
      {
        if (e->dest == target)
! 	return NULL;
        if (rtl_dump_file)
  	fprintf (rtl_dump_file, "Redirecting jump %i from %i to %i.\n",
  		 INSN_UID (insn), e->dest->index, target->index);
        if (!redirect_jump (insn, block_label (target), 0))
  	{
  	  if (target == EXIT_BLOCK_PTR)
! 	    return NULL;
  	  abort ();
  	}
      }
  
    /* Cannot do anything for target exit block.  */
    else if (target == EXIT_BLOCK_PTR)
!     return NULL;
  
    /* Or replace possibly complicated jump insn by simple jump insn.  */
    else
*************** try_redirect_by_replacing_jump (edge e, 
*** 816,822 ****
    if (e->dest != target)
      redirect_edge_succ (e, target);
  
!   return true;
  }
  
  /* Return last loop_beg note appearing after INSN, before start of next
--- 816,822 ----
    if (e->dest != target)
      redirect_edge_succ (e, target);
  
!   return e;
  }
  
  /* Return last loop_beg note appearing after INSN, before start of next
*************** last_loop_beg_note (rtx insn)
*** 841,848 ****
    return last;
  }
  
! /* Redirect edge representing branch of (un)conditional jump or tablejump.  */
! static bool
  redirect_branch_edge (edge e, basic_block target)
  {
    rtx tmp;
--- 841,849 ----
    return last;
  }
  
! /* Redirect edge representing branch of (un)conditional jump or tablejump,
!    NULL on failure  */
! static edge
  redirect_branch_edge (edge e, basic_block target)
  {
    rtx tmp;
*************** redirect_branch_edge (edge e, basic_bloc
*** 852,860 ****
  
    /* We can only redirect non-fallthru edges of jump insn.  */
    if (e->flags & EDGE_FALLTHRU)
!     return false;
    else if (GET_CODE (insn) != JUMP_INSN)
!     return false;
  
    /* Recognize a tablejump and adjust all matching cases.  */
    if (tablejump_p (insn, NULL, &tmp))
--- 853,861 ----
  
    /* We can only redirect non-fallthru edges of jump insn.  */
    if (e->flags & EDGE_FALLTHRU)
!     return NULL;
    else if (GET_CODE (insn) != JUMP_INSN)
!     return NULL;
  
    /* Recognize a tablejump and adjust all matching cases.  */
    if (tablejump_p (insn, NULL, &tmp))
*************** redirect_branch_edge (edge e, basic_bloc
*** 864,870 ****
        rtx new_label = block_label (target);
  
        if (target == EXIT_BLOCK_PTR)
! 	return false;
        if (GET_CODE (PATTERN (tmp)) == ADDR_VEC)
  	vec = XVEC (PATTERN (tmp), 0);
        else
--- 865,871 ----
        rtx new_label = block_label (target);
  
        if (target == EXIT_BLOCK_PTR)
! 	return NULL;
        if (GET_CODE (PATTERN (tmp)) == ADDR_VEC)
  	vec = XVEC (PATTERN (tmp), 0);
        else
*************** redirect_branch_edge (edge e, basic_bloc
*** 899,905 ****
        if (computed_jump_p (insn)
  	  /* A return instruction can't be redirected.  */
  	  || returnjump_p (insn))
! 	return false;
  
        /* If the insn doesn't go where we think, we're confused.  */
        if (JUMP_LABEL (insn) != old_label)
--- 900,906 ----
        if (computed_jump_p (insn)
  	  /* A return instruction can't be redirected.  */
  	  || returnjump_p (insn))
! 	return NULL;
  
        /* If the insn doesn't go where we think, we're confused.  */
        if (JUMP_LABEL (insn) != old_label)
*************** redirect_branch_edge (edge e, basic_bloc
*** 911,917 ****
        if (!redirect_jump (insn, block_label (target), 0))
  	{
  	  if (target == EXIT_BLOCK_PTR)
! 	    return false;
  	  abort ();
  	}
      }
--- 912,918 ----
        if (!redirect_jump (insn, block_label (target), 0))
  	{
  	  if (target == EXIT_BLOCK_PTR)
! 	    return NULL;
  	  abort ();
  	}
      }
*************** redirect_branch_edge (edge e, basic_bloc
*** 921,928 ****
  	     e->src->index, e->dest->index, target->index);
  
    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
--- 922,929 ----
  	     e->src->index, e->dest->index, target->index);
  
    if (e->dest != target)
!     e = redirect_edge_succ_nodup (e, target);
!   return e;
  }
  
  /* Attempt to change code to redirect edge E to TARGET.  Don't do that on
*************** redirect_branch_edge (edge e, basic_bloc
*** 931,958 ****
     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 (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;
  }
  
  /* Like force_nonfallthru below, but additionally performs redirection
--- 932,959 ----
     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 edge representing the branch if transformation succeeded.  Return NULL
!    on failure.
!    We still return NULL in case E already destinated TARGET and we didn't
!    managed to simplify instruction stream.  */
  
! static edge
  rtl_redirect_edge_and_branch (edge e, basic_block target)
  {
+   edge ret;
    if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
!     return NULL;
  
!   if ((ret = try_redirect_by_replacing_jump (e, target, false)) != NULL)
!     return ret;
  
    /* 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 NULL;
  
!   return redirect_branch_edge (e, target);
  }
  
  /* Like force_nonfallthru below, but additionally performs redirection
*************** cfg_layout_split_block (basic_block bb, 
*** 2405,2425 ****
  
  
  /* Redirect Edge to DEST.  */
! static bool
  cfg_layout_redirect_edge_and_branch (edge e, 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))
--- 2406,2426 ----
  
  
  /* Redirect Edge to DEST.  */
! static edge
  cfg_layout_redirect_edge_and_branch (edge e, basic_block dest)
  {
    basic_block src = e->src;
!   edge ret;
  
    if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
!     return NULL;
  
    if (e->src != ENTRY_BLOCK_PTR
!       && (ret = try_redirect_by_replacing_jump (e, dest, true)))
!     return ret;
  
    if (e->dest == dest)
!     return NULL;
  
    if (e->src == ENTRY_BLOCK_PTR
        && (e->flags & EDGE_FALLTHRU) && !(e->flags & EDGE_COMPLEX))
*************** cfg_layout_redirect_edge_and_branch (edg
*** 2429,2435 ****
  		 e->src->index, dest->index);
  
        redirect_edge_succ (e, dest);
!       return true;
      }
  
    /* Redirect_edge_and_branch may decide to turn branch into fallthru edge
--- 2430,2436 ----
  		 e->src->index, dest->index);
  
        redirect_edge_succ (e, dest);
!       return e;
      }
  
    /* Redirect_edge_and_branch may decide to turn branch into fallthru edge
*************** cfg_layout_redirect_edge_and_branch (edg
*** 2456,2467 ****
  	      && onlyjump_p (src->end))
  	    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);
--- 2457,2466 ----
  	      && onlyjump_p (src->end))
  	    delete_insn (src->end);
  	}
!       ret = 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);
      }
    else
      ret = redirect_branch_edge (e, dest);
diff -c3p old/gcc/tree-cfg.c gcc/tree-cfg.c
*** old/gcc/tree-cfg.c	Fri Oct 31 19:42:01 2003
--- gcc/tree-cfg.c	Sat Nov  1 14:16:17 2003
*************** static tree_stmt_iterator bsi_link_after
*** 188,211 ****
    at line 6, it sets NEXT_BLOCK_LINK (s3) to 's4'.  */
  #define NEXT_BLOCK_LINK(STMT)	TREE_CHAIN (STMT)
  
- /* FIXME These need to be filled in with appropriate pointers.  But this
-    implies an ABI change in some functions.  */
- struct cfg_hooks tree_cfg_hooks = {
-   tree_verify_flow_info,
-   tree_dump_bb,			/* dump_bb  */
-   NULL,				/* create_basic_block  */
-   NULL,				/* redirect_edge_and_branch  */
-   NULL,				/* redirect_edge_and_branch_force  */
-   NULL,				/* delete_basic_block  */
-   NULL,				/* split_block  */
-   NULL,				/* can_merge_blocks_p  */
-   NULL,				/* merge_blocks  */
-   tree_split_edge,		/* cfgh_split_edge  */
-   tree_make_forwarder_block,	/* cfgh_make_forward_block  */
-   tree_loop_optimizer_init,     /* cfgh_loop_optimizer_init  */
-   tree_loop_optimizer_finalize  /* cfgh_loop_optimizer_finalize  */
- };
- 
  /*---------------------------------------------------------------------------
  			      Create basic blocks
  ---------------------------------------------------------------------------*/
--- 188,193 ----
*************** thread_jumps (void)
*** 4496,4502 ****
  
  	  /* Perform the redirection.  */
  	  retval = true;
! 	  e = thread_edge (e, dest);
  	  if (!old)
  	    {
  	      /* Update phi nodes.   We know that the new argument should
--- 4478,4484 ----
  
  	  /* Perform the redirection.  */
  	  retval = true;
! 	  e = redirect_edge_and_branch (e, dest);
  	  if (!old)
  	    {
  	      /* Update phi nodes.   We know that the new argument should
*************** thread_jumps (void)
*** 4519,4545 ****
    return retval;
  }
  
! /* Redirects edge E to basic block DEST.  Returns the new edge to DEST.  */
! edge
! thread_edge (edge e, basic_block dest)
! {
!   tree dest_stmt = first_stmt (dest);
!   tree label, stmt;
!   basic_block bb = e->src, new_bb;
!   int flags;
  
    /* We need a label at our final destination.  If it does not already exist,
       create it.  */
!   if (!dest_stmt || TREE_CODE (dest_stmt) != LABEL_EXPR)
      {
!       block_stmt_iterator dest_iterator = bsi_start (dest);
        label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
        DECL_CONTEXT (label) = current_function_decl;
!       dest_stmt = build1 (LABEL_EXPR, void_type_node, label);
!       bsi_insert_before (&dest_iterator, dest_stmt, BSI_SAME_STMT);
      }
    else
!     label = LABEL_EXPR_LABEL (dest_stmt);
  
    /* If our block does not end with a GOTO, then create one.
       Otherwise redirect the existing GOTO_EXPR to LABEL.  */
--- 4502,4601 ----
    return retval;
  }
  
! /* Return the label in the head of basic block BLOCK.  Create one if it doesn't
!    exist.  */
  
+ static tree
+ tree_block_label (basic_block bb)
+ {
+   tree stmt = first_stmt (bb);
    /* We need a label at our final destination.  If it does not already exist,
       create it.  */
!   if (!stmt || TREE_CODE (stmt) != LABEL_EXPR)
      {
!       block_stmt_iterator iterator = bsi_start (bb);
!       tree label;
! 
        label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
        DECL_CONTEXT (label) = current_function_decl;
!       stmt = build1 (LABEL_EXPR, void_type_node, label);
!       bsi_insert_before (&iterator, stmt, BSI_SAME_STMT);
!       return label;
      }
    else
!     return LABEL_EXPR_LABEL (stmt);
! }
! 
! /* Attempt to perform edge redirection by replacing possibly complex jump
!    instruction by goto or removing jump completely.  This can apply only
!    if all edges now point to the same block.  The parameters and
!    return values are equivalent to redirect_edge_and_branch.  */
! 
! static edge
! tree_try_redirect_by_replacing_jump (edge e, basic_block target)
! {
!   basic_block src = e->src;
!   edge tmp;
!   block_stmt_iterator b;
!   tree stmt;
!   int flags;
! 
!   /* Verify that all targets will be TARGET.  */
!   for (tmp = src->succ; tmp; tmp = tmp->succ_next)
!     if (tmp->dest != target && tmp != e)
!       break;
! 
!   if (tmp)
!     return NULL;
! 
!   b = bsi_last (src);
!   if (bsi_end_p (b))
!     return NULL;
!   stmt = bsi_stmt (b);
! 
!   if (TREE_CODE (stmt) == COND_EXPR || TREE_CODE (stmt) == SWITCH_EXPR
!       || (TREE_CODE (stmt) == GOTO_EXPR && target == successor_block (src)))
!     {
!       if (target == successor_block (src))
! 	{
! 	  flags = EDGE_FALLTHRU;
!           bsi_remove (&b);
! 	}
!       else
! 	{
! 	  flags = 0;
!           stmt = build1 (GOTO_EXPR, void_type_node, tree_block_label (target));
!           bsi_replace (b, stmt);
! 	}
!       e = ssa_redirect_edge (e, target);
!       e->flags = flags;
!       return e;
!     }
!   return NULL;
! }
! 
! /* Redirect E to DEST.  Return NULL on failure, edge representing redirected
!    branch otherwise  */
! 
! static edge
! tree_redirect_edge_and_branch (edge e, basic_block dest)
! {
!   edge ret;
!   tree label, stmt;
!   basic_block bb = e->src, new_bb;
!   int flags;
! 
!   if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
!     return NULL;
! 
!   if (e->src != ENTRY_BLOCK_PTR 
!       && (ret = tree_try_redirect_by_replacing_jump (e, dest)))
!     return ret;
! 
!   if (e->dest == dest)
!     return NULL;
! 
!   label = tree_block_label (dest);
  
    /* If our block does not end with a GOTO, then create one.
       Otherwise redirect the existing GOTO_EXPR to LABEL.  */
*************** thread_edge (edge e, basic_block dest)
*** 4578,4597 ****
      default:
        stmt = build1 (GOTO_EXPR, void_type_node, label);
        bsi_insert_on_edge_immediate (e, stmt, NULL, &new_bb);
        break;
      }
  
    /* Update/insert PHI nodes as necessary.  */
  
    /* Now update the edges in the CFG.  */
!   if (new_bb)
!     {
!       ssa_remove_edge (new_bb->succ);
!       return make_edge (new_bb, dest, 0);
!     }
!   else
!     {
!       ssa_remove_edge (e);
!       return make_edge (bb, dest, flags);
!     }
  }
--- 4634,4681 ----
      default:
        stmt = build1 (GOTO_EXPR, void_type_node, label);
        bsi_insert_on_edge_immediate (e, stmt, NULL, &new_bb);
+       /* ??? In RTL equivalent we never create new basic blocks here.
+ 	 Hopefully this will be just a temporary side case before we switch
+ 	 to cfg_layout style mode with no explicit GOTO statements.  */
+       if (new_bb)
+ 	e = new_bb->succ;
+       e->flags &= ~EDGE_FALLTHRU;
        break;
      }
  
    /* Update/insert PHI nodes as necessary.  */
  
    /* Now update the edges in the CFG.  */
!   e = ssa_redirect_edge (e, dest);
!   e->flags |= flags;
!   return e;
  }
+ 
+ /* Simple wrapper as we always can redirect fallthru edges.  */
+ static basic_block
+ tree_redirect_edge_and_branch_force (edge e, basic_block dest)
+ {
+   basic_block old = e->src;
+   e = tree_redirect_edge_and_branch (e, dest);
+   if (!e)
+     abort ();
+   return e->src == old ? NULL : old;
+ }
+ 
+ /* FIXME These need to be filled in with appropriate pointers.  But this
+    implies an ABI change in some functions.  */
+ struct cfg_hooks tree_cfg_hooks = {
+   tree_verify_flow_info,
+   tree_dump_bb,			/* dump_bb  */
+   NULL,				/* create_basic_block  */
+   tree_redirect_edge_and_branch,/* redirect_edge_and_branch  */
+   tree_redirect_edge_and_branch_force,/* redirect_edge_and_branch_force  */
+   NULL,				/* delete_basic_block  */
+   NULL,				/* split_block  */
+   NULL,				/* can_merge_blocks_p  */
+   NULL,				/* merge_blocks  */
+   tree_split_edge,		/* cfgh_split_edge  */
+   tree_make_forwarder_block,	/* cfgh_make_forward_block  */
+   tree_loop_optimizer_init,     /* cfgh_loop_optimizer_init  */
+   tree_loop_optimizer_finalize  /* cfgh_loop_optimizer_finalize  */
+ };
diff -c3p old/gcc/tree-flow.h gcc/tree-flow.h
*** old/gcc/tree-flow.h	Fri Oct 31 19:42:01 2003
--- gcc/tree-flow.h	Sat Nov  1 13:20:19 2003
*************** extern void debug_def_blocks (void);
*** 504,509 ****
--- 504,510 ----
  extern void dump_tree_ssa_stats (FILE *);
  extern void debug_tree_ssa_stats (void);
  extern void ssa_remove_edge (edge);
+ extern edge ssa_redirect_edge (edge, basic_block);
  extern void set_is_used (tree);
  extern bool tree_ssa_useless_type_conversion (tree);
  extern void build_dominator_tree (dominance_info);
diff -c3p old/gcc/tree-ssa-dom.c gcc/tree-ssa-dom.c
*** old/gcc/tree-ssa-dom.c	Fri Oct 31 19:42:01 2003
--- gcc/tree-ssa-dom.c	Sat Nov  1 11:40:51 2003
*************** tree_ssa_dominator_optimize_1 (tree fnde
*** 421,427 ****
  	      for (phi = phi_nodes (e->dest); phi; phi = TREE_CHAIN (phi))
  		SET_BIT (vars_to_rename, var_ann (SSA_NAME_VAR (PHI_RESULT (phi)))->uid);
  
! 	      e = thread_edge (e, tgt);
  	      
  	      if ((dump_file && (dump_flags & TDF_DETAILS))
      		  && e->src != src)
--- 421,427 ----
  	      for (phi = phi_nodes (e->dest); phi; phi = TREE_CHAIN (phi))
  		SET_BIT (vars_to_rename, var_ann (SSA_NAME_VAR (PHI_RESULT (phi)))->uid);
  
! 	      e = redirect_edge_and_branch (e, tgt);
  	      
  	      if ((dump_file && (dump_flags & TDF_DETAILS))
      		  && e->src != src)
diff -c3p old/gcc/tree-ssa.c gcc/tree-ssa.c
*** old/gcc/tree-ssa.c	Fri Oct 31 19:42:02 2003
--- gcc/tree-ssa.c	Sat Nov  1 13:22:47 2003
*************** rewrite_out_of_ssa (tree fndecl, enum tr
*** 1869,1876 ****
  
  
  /* Remove edge E and remove the corresponding arguments from the PHI nodes
!    in E's destination block.  Return a TREE_LIST node with all the removed
!    PHI arguments.  */
  
  void
  ssa_remove_edge (edge e)
--- 1869,1875 ----
  
  
  /* Remove edge E and remove the corresponding arguments from the PHI nodes
!    in E's destination block.  */
  
  void
  ssa_remove_edge (edge e)
*************** ssa_remove_edge (edge e)
*** 1884,1889 ****
--- 1883,1904 ----
    remove_edge (e);
  }
  
+ /* Remove remove the corresponding arguments from the PHI nodes
+    in E's destination block and redirect it to DEST.  Return redirected edge.
+    It is up to caller to update phi nodes on the destination.  */
+ 
+ edge
+ ssa_redirect_edge (edge e, basic_block dest)
+ {
+   tree phi;
+ 
+   /* Remove the appropriate PHI arguments in E's destination block.  */
+   for (phi = phi_nodes (e->dest); phi; phi = TREE_CHAIN (phi))
+     remove_phi_arg (phi, e->src);
+ 
+   return redirect_edge_succ_nodup (e, dest);
+ }
+ 
  /*---------------------------------------------------------------------------
  			       Debugging support
  ---------------------------------------------------------------------------*/


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