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]

split_edge cleanup



Hi,
the patch breaks out the jump redirection logic from split_edge to
separate functions.  Now I only need to base on it flow jump optimization :)

Honza

Wed Jun 27 12:29:57 CEST 2001  Jan Hubicka  <jh@suse.cz>
	* flow.c (block_label, redirect_edge_and_branch): Split out from ....
	(split_edge) .... here;

Index: flow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flow.c,v
retrieving revision 1.406
diff -c -3 -p -r1.406 flow.c
*** flow.c	2001/06/23 08:22:52	1.406
--- flow.c	2001/06/27 10:29:47
*************** static int flow_loop_level_compute	PARAM
*** 471,476 ****
--- 471,478 ----
  static int flow_loops_level_compute	PARAMS ((struct loops *));
  static void allocate_bb_life_data	PARAMS ((void));
  static void find_sub_basic_blocks	PARAMS ((basic_block));
+ static int redirect_edge_and_branch 	PARAMS ((edge, basic_block));
+ static rtx block_label			PARAMS ((basic_block));
  
  /* Find basic blocks of the current function.
     F is the first insn of the function and NREGS the number of register
*************** split_block (bb, insn)
*** 1574,1579 ****
--- 1576,1669 ----
    return new_edge;
  }
  
+ /* Return label in the head of basic block.  Create one if it doesn't exist.  */
+ static rtx
+ block_label (block)
+      basic_block block;
+ {
+   if (GET_CODE (block->head) != CODE_LABEL)
+     block->head = emit_label_before (gen_label_rtx (), block->head);
+   return block->head;
+ }
+ 
+ /* Attempt to change code to redirect edge E to destinate in TARGET.
+    Don't do that on expense of adding new instructions or reordering
+    basic blocks.  */
+ static int
+ redirect_edge_and_branch (e, target)
+      edge e;
+      basic_block target;
+ {
+   if (!(e->flags & EDGE_FALLTHRU))
+     {
+       rtx insn = e->src->end;
+       rtx tmp;
+       rtx old_label = e->dest->head;
+ 
+       if (GET_CODE (insn) != JUMP_INSN)
+ 	abort ();
+ 
+       /* Recognize a tablejump and adjust all matching cases.  */
+       if ((tmp = JUMP_LABEL (insn)) != NULL_RTX
+ 	  && (tmp = NEXT_INSN (tmp)) != NULL_RTX
+ 	  && GET_CODE (tmp) == JUMP_INSN
+ 	  && (GET_CODE (PATTERN (tmp)) == ADDR_VEC
+ 	      || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC))
+ 	{
+ 	  rtvec vec;
+ 	  int j;
+ 	  rtx new_label = block_label (target);
+ 
+ 	  if (GET_CODE (PATTERN (tmp)) == ADDR_VEC)
+ 	    vec = XVEC (PATTERN (tmp), 0);
+ 	  else
+ 	    vec = XVEC (PATTERN (tmp), 1);
+ 
+ 	  for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
+ 	    if (XEXP (RTVEC_ELT (vec, j), 0) == old_label)
+ 	      {
+ 		RTVEC_ELT (vec, j) = gen_rtx_LABEL_REF (VOIDmode, new_label);
+ 		--LABEL_NUSES (old_label);
+ 		++LABEL_NUSES (new_label);
+ 	      }
+ 
+ 	  /* Handle casesi dispatch insns */
+ 	  if ((tmp = single_set (insn)) != NULL
+ 	      && SET_DEST (tmp) == pc_rtx
+ 	      && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
+ 	      && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF
+ 	      && XEXP (XEXP (SET_SRC (tmp), 2), 0) == old_label)
+ 	    {
+ 	      XEXP (SET_SRC (tmp), 2) = gen_rtx_LABEL_REF (VOIDmode,
+ 							   new_label);
+ 	      --LABEL_NUSES (old_label);
+ 	      ++LABEL_NUSES (new_label);
+ 	    }
+ 	}
+       else
+ 	{
+ 	  /* ?? We may play the games with moving the named labels from
+ 	     one basic block to the other in case only one computed_jump is
+ 	     available.  */
+ 	  if (computed_jump_p (insn))
+ 	    return 0;
+ 
+ 	  /* A return instruction can't be redirected.  */
+ 	  if (returnjump_p (insn))
+ 	    return 0;
+ 
+ 	  /* If the insn doesn't go where we think, we're confused.  */
+ 	  if (JUMP_LABEL (insn) != old_label)
+ 	    abort ();
+ 	  redirect_jump (insn, block_label (target), 0);
+ 	}
+     }
+   else
+     return 0;
+   redirect_edge_succ (e, target);
+   return 1;
+ }
+ 
  
  /* Split a (typically critical) edge.  Return the new block.
     Abort on abnormal edges.
*************** split_edge (edge_in)
*** 1598,1612 ****
    old_pred = edge_in->src;
    old_succ = edge_in->dest;
  
-   /* Remove the existing edge from the destination's pred list.  */
-   {
-     edge *pp;
-     for (pp = &old_succ->pred; *pp != edge_in; pp = &(*pp)->pred_next)
-       continue;
-     *pp = edge_in->pred_next;
-     edge_in->pred_next = NULL;
-   }
- 
    /* Create the new structures.  */
    bb = (basic_block) obstack_alloc (&flow_obstack, sizeof (*bb));
    edge_out = (edge) xcalloc (1, sizeof (*edge_out));
--- 1688,1693 ----
*************** split_edge (edge_in)
*** 1624,1636 ****
      }
  
    /* Wire them up.  */
-   bb->pred = edge_in;
    bb->succ = edge_out;
    bb->count = edge_in->count;
    bb->frequency = (edge_in->probability * edge_in->src->frequency
  		   / REG_BR_PROB_BASE);
  
-   edge_in->dest = bb;
    edge_in->flags &= ~EDGE_CRITICAL;
  
    edge_out->pred_next = old_succ->pred;
--- 1705,1715 ----
*************** split_edge (edge_in)
*** 1743,1815 ****
    NOTE_BASIC_BLOCK (bb_note) = bb;
    bb->head = bb->end = bb_note;
  
!   /* Not quite simple -- for non-fallthru edges, we must adjust the
!      predecessor's jump instruction to target our new block.  */
    if ((edge_in->flags & EDGE_FALLTHRU) == 0)
!     {
!       rtx tmp, insn = old_pred->end;
!       rtx old_label = old_succ->head;
!       rtx new_label = gen_label_rtx ();
! 
!       if (GET_CODE (insn) != JUMP_INSN)
! 	abort ();
! 
!       /* ??? Recognize a tablejump and adjust all matching cases.  */
!       if ((tmp = JUMP_LABEL (insn)) != NULL_RTX
! 	  && (tmp = NEXT_INSN (tmp)) != NULL_RTX
! 	  && GET_CODE (tmp) == JUMP_INSN
! 	  && (GET_CODE (PATTERN (tmp)) == ADDR_VEC
! 	      || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC))
! 	{
! 	  rtvec vec;
! 	  int j;
! 
! 	  if (GET_CODE (PATTERN (tmp)) == ADDR_VEC)
! 	    vec = XVEC (PATTERN (tmp), 0);
! 	  else
! 	    vec = XVEC (PATTERN (tmp), 1);
! 
! 	  for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
! 	    if (XEXP (RTVEC_ELT (vec, j), 0) == old_label)
! 	      {
! 		RTVEC_ELT (vec, j) = gen_rtx_LABEL_REF (VOIDmode, new_label);
! 		--LABEL_NUSES (old_label);
! 		++LABEL_NUSES (new_label);
! 	      }
! 
! 	  /* Handle casesi dispatch insns */
! 	  if ((tmp = single_set (insn)) != NULL
! 	      && SET_DEST (tmp) == pc_rtx
! 	      && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
! 	      && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF
! 	      && XEXP (XEXP (SET_SRC (tmp), 2), 0) == old_label)
! 	    {
! 	      XEXP (SET_SRC (tmp), 2) = gen_rtx_LABEL_REF (VOIDmode,
! 							   new_label);
! 	      --LABEL_NUSES (old_label);
! 	      ++LABEL_NUSES (new_label);
! 	    }
! 	}
!       else
! 	{
! 	  /* This would have indicated an abnormal edge.  */
! 	  if (computed_jump_p (insn))
! 	    abort ();
! 
! 	  /* A return instruction can't be redirected.  */
! 	  if (returnjump_p (insn))
! 	    abort ();
! 
! 	  /* If the insn doesn't go where we think, we're confused.  */
! 	  if (JUMP_LABEL (insn) != old_label)
! 	    abort ();
! 
! 	  redirect_jump (insn, new_label, 0);
! 	}
! 
!       emit_label_before (new_label, bb_note);
!       bb->head = new_label;
!     }
  
    return bb;
  }
--- 1822,1833 ----
    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)
!     redirect_edge_and_branch (edge_in, bb);
!   else
!     redirect_edge_succ (edge_in, bb);
  
    return bb;
  }


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