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]

Preserve branch prediction over try_split



Hi,
this patch modifies try_split to make possible updating of branch probabilities
when conditional jump is spit. I've added sanity checking on case updating is
nontrivial, and I require md file to asist.  This can make gcc to crash if md
file is not updated.  I believe that this feature is used only by the i386 so
far, and I am sending the patch for that shortly.  Also I've changed the
return value to return the CODE_LABELs if they are newly clreated.

Bootstrapped/regtested i686 together with the followup patch.

Tue Jul 17 16:59:08 CEST 2001  Jan Hubicka  <jh@suse.cz>
	* emit-rtl.c (split_branch_probability): New global variable.
	(try_split): Take care to set split_branch_probability and
	create REG_BR_PROB note for new jump insns.
	* md.texi (define_split): Document new feature.

Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/emit-rtl.c,v
retrieving revision 1.193
diff -c -3 -p -r1.193 emit-rtl.c
*** emit-rtl.c	2001/07/14 22:52:48	1.193
--- emit-rtl.c	2001/07/17 14:57:08
*************** static int const_int_htab_eq            
*** 184,189 ****
--- 184,193 ----
  static int rtx_htab_mark_1              PARAMS ((void **, void *));
  static void rtx_htab_mark               PARAMS ((void *));
  
+ /* Probability of the conditional branch currently proceeded by try_split.
+    Set to -1 otherwise.  */
+ int split_branch_probability = -1;
+ 
  
  /* Returns a hash code for X (which is a really a CONST_INT).  */
  
*************** try_split (pat, trial, last)
*** 2485,2493 ****
  {
    rtx before = PREV_INSN (trial);
    rtx after = NEXT_INSN (trial);
-   rtx seq = split_insns (pat, trial);
    int has_barrier = 0;
    rtx tem;
  
    /* If we are splitting a JUMP_INSN, it might be followed by a BARRIER.
       We may need to handle this specially.  */
--- 2489,2507 ----
  {
    rtx before = PREV_INSN (trial);
    rtx after = NEXT_INSN (trial);
    int has_barrier = 0;
    rtx tem;
+   rtx note, seq;
+   int probability;
+ 
+   if (any_condjump_p (trial)
+       && (note = find_reg_note (trial, REG_BR_PROB, 0)))
+     split_branch_probability = INTVAL (XEXP (note, 0));
+   probability = split_branch_probability;
+ 
+   seq = split_insns (pat, trial);
+ 
+   split_branch_probability = -1;
  
    /* If we are splitting a JUMP_INSN, it might be followed by a BARRIER.
       We may need to handle this specially.  */
*************** try_split (pat, trial, last)
*** 2504,2510 ****
  	 it, in turn, will be split (SFmode on the 29k is an example).  */
        if (GET_CODE (seq) == SEQUENCE)
  	{
! 	  int i;
  	  rtx eh_note;
  
  	  /* Avoid infinite loop if any insn of the result matches
--- 2518,2524 ----
  	 it, in turn, will be split (SFmode on the 29k is an example).  */
        if (GET_CODE (seq) == SEQUENCE)
  	{
! 	  int i, njumps = 0;
  	  rtx eh_note;
  
  	  /* Avoid infinite loop if any insn of the result matches
*************** try_split (pat, trial, last)
*** 2517,2525 ****
  	  /* Mark labels.  */
  	  for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
  	    if (GET_CODE (XVECEXP (seq, 0, i)) == JUMP_INSN)
! 	      mark_jump_label (PATTERN (XVECEXP (seq, 0, i)),
! 			       XVECEXP (seq, 0, i), 0);
! 
  	  /* If we are splitting a CALL_INSN, look for the CALL_INSN
  	     in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it.  */
  	  if (GET_CODE (trial) == CALL_INSN)
--- 2531,2557 ----
  	  /* Mark labels.  */
  	  for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
  	    if (GET_CODE (XVECEXP (seq, 0, i)) == JUMP_INSN)
! 	      {
! 		rtx insn = XVECEXP (seq, 0, i);
! 		mark_jump_label (PATTERN (insn),
! 				 XVECEXP (seq, 0, i), 0);
! 		njumps++;
! 		if (probability != -1
! 		    && any_condjump_p (insn)
! 		    && !find_reg_note (insn, REG_BR_PROB, 0))
! 		  {
! 		    /* We can preserve the REG_BR_PROB notes only if exactly
! 		       one jump is created, otherwise the machinde description
! 		       is responsible for this step using
! 		       split_branch_probability variable.  */
! 		    if (njumps != 1)
! 		      abort ();
! 		    REG_NOTES (insn)
! 		      = gen_rtx_EXPR_LIST (REG_BR_PROB,
! 					   GEN_INT (probability),
! 					   REG_NOTES (insn));
! 		  }
! 	      }
  	  /* If we are splitting a CALL_INSN, look for the CALL_INSN
  	     in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it.  */
  	  if (GET_CODE (trial) == CALL_INSN)
*************** try_split (pat, trial, last)
*** 2576,2583 ****
        /* Return either the first or the last insn, depending on which was
  	 requested.  */
        return last
! 		? (after ? prev_active_insn (after) : last_insn)
! 		: next_active_insn (before);
      }
  
    return trial;
--- 2608,2615 ----
        /* Return either the first or the last insn, depending on which was
  	 requested.  */
        return last
! 		? (after ? PREV_INSN (after) : last_insn)
! 		: NEXT_INSN (before);
      }
  
    return trial;
! /* Identify the edges between basic blocks.
  
     NONLOCAL_LABEL_LIST is a list of non-local labels in the function.  Blocks
     that are otherwise unreachable may be reachable with a non-local goto.
--- 1152,1158 ----
    n_edges = 0;
  }
  
! /* Identify the edges between basic blocks MIN to MAX.
  
     NONLOCAL_LABEL_LIST is a list of non-local labels in the function.  Blocks
     that are otherwise unreachable may be reachable with a non-local goto.
Index: doc/md.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/doc/md.texi,v
retrieving revision 1.12
diff -c -3 -p -r1.12 md.texi
*** md.texi	2001/07/09 06:10:09	1.12
--- md.texi	2001/07/17 14:57:20
*************** insns that don't.  Instead, write two se
*** 3786,3791 ****
--- 3786,3807 ----
  definitions, one for the insns that are valid and one for the insns that
  are not valid.
  
+ The splitter is allowed to split jump instructions into sequence of
+ jumps or create new jumps in while splitting non-jump instructions.  As
+ the central flowgraph and branch prediction information needs to be updated,
+ several restriction apply. 
+ 
+ Splitting of jump instruction into sequence that over by another jump
+ instruction is always valid, as compiler expect identical behaviour of new
+ jump.  When new sequence contains multiple jump instructions or new labels,
+ more assistance is needed. Splitter is required to create only unconditional
+ jumps, or simple conditional jump instructions.  Additionally it must attach an
+ REG_BR_PROB note to each conditional jump. An global variable
+ @code{split_branch_probability} hold the probability of original branch in case
+ it was an simple conditiona jump, -1 otherwise.  To simplify recomputing of
+ edge frequencies, new sequence is required to have only forward jumps to the
+ newly created labels.
+ 
  For the common case where the pattern of a define_split exactly matches the
  pattern of a define_insn, use @code{define_insn_and_split}.  It looks like
  this:
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtl.h,v
retrieving revision 1.274
diff -c -3 -p -r1.274 rtl.h
*** rtl.h	2001/07/16 20:54:43	1.274
--- rtl.h	2001/07/17 14:57:14
*************** extern rtx *find_constant_term_loc	PARAM
*** 1301,1306 ****
--- 1301,1307 ----
  
  /* In emit-rtl.c  */
  extern rtx try_split			PARAMS ((rtx, rtx, int));
+ extern int split_branch_probability;
  
  /* In unknown file  */
  extern rtx split_insns			PARAMS ((rtx, rtx));


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