Commit 4db384c9 by Jan Hubicka Committed by Jan Hubicka

predict.def: New file.

	* predict.def: New file.
	* predict.h: New file.
	* predict.c: Include predict.h.
	(predictor_info): New structure and array.
	(predict_edge, predict_insn): Rewrite; make global.
	(predict_edge_def, predict_insn_def): New global functions.
	(dump_prediction, combine_predictions_for_insns): New
	static functions.
	(estimate_probability): Change calls to predict_edge
	to predict_edge_def and calls to predict_insn to predict_insn_def;
	combine probabilities.
	(expected_value_to_br_prob): Behave as predictor.
	* rtl.h (REG_BR_PRED): Update coment.
	(invert_br_probabilities): New.
	* jump.c: Include predict.h
	(duplicate_loop_exit_test): Drop branch prediction notes.
	(invert_jump): Use invert_br_probabilities.
	* Makefile.in: Add dependancy on predict.h for jump and predict pass.
	* ifcvt.c (dead_or_predicable): Use invert_br_probabilities.
	* combine.c (distribute_notes): Handle BR_PRED.

From-SVN: r43115
parent 5bb8dd28
Sun Jun 10 00:35:37 CEST 2001 Jan Hubicka <jh@suse.cz>
* predict.def: New file.
* predict.h: New file.
* predict.c: Include predict.h.
(predictor_info): New structure and array.
(predict_edge, predict_insn): Rewrite; make global.
(predict_edge_def, predict_insn_def): New global functions.
(dump_prediction, combine_predictions_for_insns): New
static functions.
(estimate_probability): Change calls to predict_edge
to predict_edge_def and calls to predict_insn to predict_insn_def;
combine probabilities.
(expected_value_to_br_prob): Behave as predictor.
* rtl.h (REG_BR_PRED): Update coment.
(invert_br_probabilities): New.
* jump.c: Include predict.h
(duplicate_loop_exit_test): Drop branch prediction notes.
(invert_jump): Use invert_br_probabilities.
* Makefile.in: Add dependancy on predict.h for jump and predict pass.
* ifcvt.c (dead_or_predicable): Use invert_br_probabilities.
* combine.c (distribute_notes): Handle BR_PRED.
Sat Jun 9 23:29:41 CEST 2001 Jan Hubicka <jh@suse.cz>
* predict.c (predict_insn, predict_edge): New static functions.
......
......@@ -572,6 +572,7 @@ INSN_ATTR_H = insn-attr.h $(srcdir)/insn-addr.h $(srcdir)/varray.h
C_COMMON_H = c-common.h $(SPLAY_TREE_H)
C_TREE_H = c-tree.h $(C_COMMON_H)
SYSTEM_H = system.h hwint.h $(srcdir)/../include/libiberty.h
PREDICT_H = predict.h predict.def
# sed inserts variable overrides after the following line.
####target overrides
......@@ -1403,7 +1404,7 @@ integrate.o : integrate.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
params.h $(TM_P_H)
jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h hard-reg-set.h $(REGS_H) \
insn-config.h $(RECOG_H) $(EXPR_H) real.h except.h function.h \
toplev.h $(INSN_ATTR_H) $(TM_P_H) reload.h
toplev.h $(INSN_ATTR_H) $(TM_P_H) reload.h $(PREDICT_H)
simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) \
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
......@@ -1509,7 +1510,7 @@ reg-stack.o : reg-stack.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) $(RECOG_H)
varray.h function.h $(TM_P_H)
predict.o: predict.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h \
$(RECOG_H) function.h except.h $(EXPR_H) $(TM_P_H)
$(RECOG_H) function.h except.h $(EXPR_H) $(TM_P_H) $(PREDICT_H)
lists.o: lists.c $(CONFIG_H) $(SYSTEM_H) toplev.h $(RTL_H) $(GGC_H)
bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h \
......
......@@ -11952,6 +11952,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
switch (REG_NOTE_KIND (note))
{
case REG_BR_PROB:
case REG_BR_PRED:
case REG_EXEC_COUNT:
/* Doesn't matter much where we put this, as long as it's somewhere.
It is preferable to keep these notes on branches, which is most
......
......@@ -2410,11 +2410,7 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
JUMP_LABEL (jump) = new_dest;
if (reversep)
{
rtx note = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
if (note)
XEXP (note, 0) = GEN_INT (REG_BR_PROB_BASE - INTVAL (XEXP (note, 0)));
}
invert_br_probabilities (jump);
/* Move the insns out of MERGE_BB to before the branch. */
if (head != NULL)
......
......@@ -67,6 +67,7 @@ Boston, MA 02111-1307, USA. */
#include "except.h"
#include "toplev.h"
#include "reload.h"
#include "predict.h"
/* ??? Eventually must record somehow the labels used by jumps
from nested functions. */
......@@ -1248,6 +1249,23 @@ duplicate_loop_exit_test (loop_start)
replace_regs (REG_NOTES (copy), reg_map, max_reg, 1);
}
/* Predict conditional jump that do make loop looping as taken.
Other jumps are probably exit conditions, so predict
them as untaken. */
if (any_condjump_p (copy))
{
rtx label = JUMP_LABEL (copy);
if (label)
{
if (PREV_INSN (label)
&& GET_CODE (PREV_INSN (label)) == NOTE
&& (NOTE_LINE_NUMBER (PREV_INSN (label))
== NOTE_INSN_LOOP_CONT))
predict_insn_def (copy, PRED_LOOP_HEADER, TAKEN);
else
predict_insn_def (copy, PRED_LOOP_HEADER, NOT_TAKEN);
}
}
/* If this is a simple jump, add it to the jump chain. */
if (INSN_UID (copy) < max_jump_chain && JUMP_LABEL (copy)
......@@ -3351,13 +3369,7 @@ invert_jump (jump, nlabel, delete_unused)
if (redirect_jump (jump, nlabel, delete_unused))
{
/* An inverted jump means that a probability taken becomes a
probability not taken. Subtract the branch probability from the
probability base to convert it back to a taken probability. */
rtx note = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
if (note)
XEXP (note, 0) = GEN_INT (REG_BR_PROB_BASE - INTVAL (XEXP (note, 0)));
invert_br_probabilities (jump);
return 1;
}
......
......@@ -46,7 +46,7 @@
#include "toplev.h"
#include "recog.h"
#include "expr.h"
#include "predict.h"
/* Random guesstimation given names. */
#define PROB_NEVER (0)
......@@ -57,34 +57,63 @@
#define PROB_VERY_LIKELY (REG_BR_PROB_BASE - PROB_VERY_UNLIKELY)
#define PROB_ALWAYS (REG_BR_PROB_BASE)
static void predict_insn PARAMS ((rtx, int));
static void predict_edge PARAMS ((edge, int));
static void combine_predictions_for_insn PARAMS ((rtx, basic_block));
static void dump_prediction PARAMS ((enum br_predictor, int,
basic_block));
static void
predict_insn (insn, probability)
rtx insn;
int probability;
/* Information we hold about each branch predictor.
Filled using information from predict.def. */
struct predictor_info
{
rtx note = find_reg_note (insn, REG_BR_PROB, 0);
const char *name; /* Name used in the debugging dumps. */
int hitrate; /* Expected hitrate used by
predict_insn_def call. */
};
/* Implement "first match" heruistics. In case we already predicted
insn somehow, keep it predicted that way. In future we would like
to rather store all predictions and then combine them. */
if (note)
return;
#define DEF_PREDICTOR(ENUM, NAME, HITRATE) {NAME, HITRATE},
struct predictor_info predictor_info[] = {
#include "predict.def"
/* Upper bound on non-language-specific builtins. */
{NULL, 0}
};
#undef DEF_PREDICTOR
void
predict_insn (insn, predictor, probability)
rtx insn;
int probability;
enum br_predictor predictor;
{
if (!any_condjump_p (insn))
abort ();
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_BR_PROB,
GEN_INT (probability), REG_NOTES (insn));
= gen_rtx_EXPR_LIST (REG_BR_PRED,
gen_rtx_CONCAT (VOIDmode,
GEN_INT ((int) predictor),
GEN_INT ((int) probability)),
REG_NOTES (insn));
}
/* Predict insn by given predictor. */
void
predict_insn_def (insn, predictor, taken)
rtx insn;
enum br_predictor predictor;
enum prediction taken;
{
int probability = predictor_info[(int) predictor].hitrate;
if (taken != TAKEN)
probability = REG_BR_PROB_BASE - probability;
predict_insn (insn, predictor, probability);
}
/* Predict edge E with given probability if possible. */
static void
predict_edge (e, probability)
void
predict_edge (e, predictor, probability)
edge e;
int probability;
enum br_predictor predictor;
{
rtx last_insn;
last_insn = e->src->end;
......@@ -98,7 +127,107 @@ predict_edge (e, probability)
if (e->flags & EDGE_FALLTHRU)
probability = REG_BR_PROB_BASE - probability;
predict_insn (last_insn, probability);
predict_insn (last_insn, predictor, probability);
}
/* Predict edge E by given predictor if possible. */
void
predict_edge_def (e, predictor, taken)
edge e;
enum br_predictor predictor;
enum prediction taken;
{
int probability = predictor_info[(int) predictor].hitrate;
if (taken != TAKEN)
probability = REG_BR_PROB_BASE - probability;
predict_edge (e, predictor, probability);
}
/* Invert all branch predictions or probability notes in the INSN. This needs
to be done each time we invert the condition used by the jump. */
void
invert_br_probabilities (insn)
rtx insn;
{
rtx note = REG_NOTES (insn);
while (note)
{
if (REG_NOTE_KIND (note) == REG_BR_PROB)
XEXP (note, 0) = GEN_INT (REG_BR_PROB_BASE - INTVAL (XEXP (note, 0)));
else if (REG_NOTE_KIND (note) == REG_BR_PRED)
XEXP (XEXP (note, 0), 1)
= GEN_INT (REG_BR_PROB_BASE - INTVAL (XEXP (XEXP (note, 0), 1)));
note = XEXP (note, 1);
}
}
/* Dump information about the branch prediction to the output file. */
static void
dump_prediction (predictor, probability, bb)
enum br_predictor predictor;
int probability;
basic_block bb;
{
edge e = bb->succ;
if (!rtl_dump_file)
return;
while (e->flags & EDGE_FALLTHRU)
e = e->succ_next;
fprintf (rtl_dump_file, " %s heuristics: %.1f%%",
predictor_info[predictor].name,
probability * 100.0 / REG_BR_PROB_BASE);
if (bb->count)
fprintf (rtl_dump_file, " exec %i hit %i (%.1f%%)",
bb->count, e->count, e->count * 100.0 / bb->count);
fprintf (rtl_dump_file, "\n");
}
/* Combine all REG_BR_PRED notes into single probability and attach REG_BR_PROB
note if not already present. Remove now useless REG_BR_PRED notes. */
static void
combine_predictions_for_insn (insn, bb)
rtx insn;
basic_block bb;
{
rtx prob_note = find_reg_note (insn, REG_BR_PROB, 0);
rtx *pnote = &REG_NOTES (insn);
int best_probability = PROB_EVEN;
int best_predictor = END_PREDICTORS;
if (rtl_dump_file)
fprintf (rtl_dump_file, "Predictions for insn %i\n", INSN_UID (insn));
/* We implement "first match" heuristics and use probability guessed
by predictor with smallest index. In future we will use better
probability combination techniques. */
while (*pnote)
{
rtx *next_pnote = &XEXP (*pnote, 1);
if (REG_NOTE_KIND (*pnote) == REG_BR_PRED)
{
int predictor = INTVAL (XEXP (XEXP (*pnote, 0), 0));
int probability = INTVAL (XEXP (XEXP (*pnote, 0), 1));
dump_prediction (predictor, probability, bb);
if (best_predictor > predictor)
best_probability = probability, best_predictor = predictor;
*pnote = XEXP (*pnote, 1);
}
pnote = next_pnote;
}
dump_prediction (PRED_FIRST_MATCH, best_probability, bb);
if (!prob_note)
{
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_BR_PROB,
GEN_INT (best_probability), REG_NOTES (insn));
}
}
/* Statically estimate the probability that a branch will be taken.
......@@ -134,7 +263,7 @@ estimate_probability (loops_info)
if (e->dest == loops_info->array[i].header)
{
header_found = 1;
predict_edge (e, PROB_VERY_LIKELY);
predict_edge_def (e, PRED_LOOP_BRANCH, TAKEN);
}
/* Loop exit heruistics - predict as not taken an edge exiting
the loop if the conditinal has no loop header successors */
......@@ -142,7 +271,7 @@ estimate_probability (loops_info)
for (e = BASIC_BLOCK(j)->succ; e; e = e->succ_next)
if (e->dest->index <= 0
|| !TEST_BIT (loops_info->array[i].nodes, e->dest->index))
predict_edge (e, PROB_UNLIKELY);
predict_edge_def (e, PRED_LOOP_EXIT, NOT_TAKEN);
}
}
}
......@@ -169,7 +298,7 @@ estimate_probability (loops_info)
/* ??? Ought to do the same for any subgraph with no exit. */
for (e = BASIC_BLOCK (i)->succ; e; e = e->succ_next)
if (e->dest->succ == NULL)
predict_edge (e, PROB_NEVER);
predict_edge_def (e, PRED_NORETURN, NOT_TAKEN);
cond = get_condition (last_insn, &earliest);
if (! cond)
......@@ -187,7 +316,7 @@ estimate_probability (loops_info)
|| (GET_CODE (XEXP (cond, 1)) == REG
&& REG_POINTER (XEXP (cond, 1)))))
predict_insn (last_insn, PROB_UNLIKELY);
predict_insn_def (last_insn, PRED_POINTER, NOT_TAKEN);
break;
case NE:
if (GET_CODE (XEXP (cond, 0)) == REG
......@@ -195,7 +324,7 @@ estimate_probability (loops_info)
&& (XEXP (cond, 1) == const0_rtx
|| (GET_CODE (XEXP (cond, 1)) == REG
&& REG_POINTER (XEXP (cond, 1)))))
predict_insn (last_insn, PROB_LIKELY);
predict_insn_def (last_insn, PRED_POINTER, TAKEN);
break;
default:
......@@ -210,41 +339,52 @@ estimate_probability (loops_info)
{
case CONST_INT:
/* Unconditional branch. */
predict_insn (last_insn,
cond == const0_rtx ? PROB_NEVER : PROB_ALWAYS);
predict_insn_def (last_insn, PRED_UNCONDITIONAL,
cond == const0_rtx ? NOT_TAKEN : TAKEN);
break;
case EQ:
case UNEQ:
predict_insn (last_insn, PROB_UNLIKELY);
predict_insn_def (last_insn, PRED_OPCODE, NOT_TAKEN);
break;
case NE:
case LTGT:
predict_insn (last_insn, PROB_LIKELY);
predict_insn_def (last_insn, PRED_OPCODE, TAKEN);
break;
case ORDERED:
predict_insn (last_insn, PROB_LIKELY);
predict_insn_def (last_insn, PRED_OPCODE, TAKEN);
break;
case UNORDERED:
predict_insn (last_insn, PROB_UNLIKELY);
predict_insn_def (last_insn, PRED_OPCODE, NOT_TAKEN);
break;
case LE:
case LT:
if (XEXP (cond, 1) == const0_rtx)
predict_insn (last_insn, PROB_UNLIKELY);
predict_insn_def (last_insn, PRED_OPCODE, NOT_TAKEN);
break;
case GE:
case GT:
if (XEXP (cond, 1) == const0_rtx
|| (GET_CODE (XEXP (cond, 1)) == CONST_INT
&& INTVAL (XEXP (cond, 1)) == -1))
predict_insn (last_insn, PROB_LIKELY);
predict_insn_def (last_insn, PRED_OPCODE, TAKEN);
break;
default:
break;
}
}
/* Attach the combined probability to each conditional jump. */
for (i = 0; i < n_basic_blocks - 1; i++)
{
rtx last_insn = BLOCK_END (i);
if (GET_CODE (last_insn) != JUMP_INSN
|| ! any_condjump_p (last_insn))
continue;
combine_predictions_for_insn (last_insn, BASIC_BLOCK (i));
}
}
/* __builtin_expect dropped tokens into the insn stream describing
......@@ -285,7 +425,7 @@ expected_value_to_br_prob ()
expected value yet, no point going further. */
if (GET_CODE (insn) != JUMP_INSN || ev == NULL_RTX)
continue;
if (! condjump_p (insn) || simplejump_p (insn))
if (! any_condjump_p (insn))
continue;
break;
}
......@@ -316,7 +456,7 @@ expected_value_to_br_prob ()
/* Turn the condition into a scaled branch probability. */
if (cond != const1_rtx && cond != const0_rtx)
abort ();
predict_insn (insn,
cond == const1_rtx ? PROB_VERY_LIKELY : PROB_VERY_UNLIKELY);
predict_insn_def (insn, PRED_BUILTIN_EXPECT,
cond == const1_rtx ? TAKEN : NOT_TAKEN);
}
}
/* This file contains the definitions and documentation for the
builtins used in the GNU compiler.
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Before including this file, you should define a macro:
DEF_PREDICTOR (ENUM, NAME, HITRATE)
This macro will be called once for each predictor. The ENUM will
be of type `enum predictor', and will enumerate all supported
predictors. The order of DEF_PREDICTOR calls is important, as
in the first match combining heuristics, the predictor appearing
first in this file will win.
NAME is used in the debugging output to determine predictor type.
HITRATE is the probability that edge predicted by predictor as taken
will be really taken (so it should be always above
REG_BR_PROB_BASE / 2). */
DEF_PREDICTOR (PRED_FIRST_MATCH, "first match", PROB_ALWAYS)
DEF_PREDICTOR (PRED_UNCONDITIONAL, "unconditional jump", PROB_ALWAYS)
DEF_PREDICTOR (PRED_BUILTIN_EXPECT, "__builtin_expect", PROB_VERY_LIKELY)
DEF_PREDICTOR (PRED_NORETURN, "noreturn call", PROB_ALWAYS)
DEF_PREDICTOR (PRED_LOOP_BRANCH, "loop branch", PROB_VERY_LIKELY)
DEF_PREDICTOR (PRED_LOOP_EXIT, "loop exit", PROB_LIKELY)
DEF_PREDICTOR (PRED_LOOP_HEADER, "loop header", PROB_LIKELY)
DEF_PREDICTOR (PRED_POINTER, "pointer", PROB_LIKELY)
DEF_PREDICTOR (PRED_OPCODE, "opcode", PROB_LIKELY)
/* This file contains the definitions and documentation for the
builtins used in the GNU compiler.
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define DEF_PREDICTOR(ENUM, NAME, HITRATE) ENUM,
enum br_predictor
{
#include "predict.def"
/* Upper bound on non-language-specific builtins. */
END_PREDICTORS
};
#undef DEF_PREDICTOR
enum prediction
{
NOT_TAKEN,
TAKEN
};
extern void predict_insn_def PARAMS ((rtx, enum br_predictor,
enum prediction));
extern void predict_insn PARAMS ((rtx, enum br_predictor, int));
/* Avoid unneeded dependancy on basic_block.h */
#ifdef BASIC_BLOCK
extern void predict_edge PARAMS ((edge, enum br_predictor, int));
extern void predict_edge_def PARAMS ((edge, enum br_predictor,
enum prediction));
#endif
......@@ -497,10 +497,10 @@ enum reg_note
flow, are represented by a 0 reg note kind. */
REG_DEP_ANTI, REG_DEP_OUTPUT,
/* REG_BR_PROB is attached to JUMP_INSNs and CALL_INSNs when the flag
-fbranch-probabilities is given. It has an integer value. For jumps,
it is the probability that this is a taken branch. For calls, it is
the probability that this call won't return. */
/* REG_BR_PROB is attached to JUMP_INSNs and CALL_INSNs.
It has an integer value. For jumps, it is the probability that this is a
taken branch. For calls, it is the probability that this call won't
return. */
REG_BR_PROB,
/* REG_EXEC_COUNT is attached to the first insn of each basic block, and
......@@ -516,8 +516,10 @@ enum reg_note
where SETJMP_VIA_SAVE_AREA is true. */
REG_SAVE_AREA,
/* Attached to JUMP_INSNs only, it holds the branch prediction flags
computed by get_jump_flags() after dbr scheduling is complete. */
/* REG_BR_PRED is attached to JUMP_INSNs and CALL_INSNSs. It contains
CONCAT of two integer value. First specifies the branch predictor
that added the note, second specifies the predicted hitrate of branch
in the same format as REG_BR_PROB note uses. */
REG_BR_PRED,
/* Attached to insns that are RTX_FRAME_RELATED_P, but are too complex
......@@ -2020,7 +2022,9 @@ extern rtx stack_limit_rtx;
/* In regrename.c */
extern void regrename_optimize PARAMS ((void));
/* In condexec.c */
/* In ifcvt.c */
extern void if_convert PARAMS ((int));
/* In predict.c */
extern void invert_br_probabilities PARAMS ((rtx));
#endif /* ! GCC_RTL_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment