This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Preserve branch prediction over try_split
- To: gcc-patches at gcc dot gnu dot org, rth at cygnus dot com, patches at x86-64 dot org
- Subject: Preserve branch prediction over try_split
- From: Jan Hubicka <jh at suse dot cz>
- Date: Tue, 17 Jul 2001 17:14:41 +0200
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));