Commit 10f13594 by Richard Henderson Committed by Richard Henderson

loop.c (canonicalize_condition): Add WANT_REG argument.

        * loop.c (canonicalize_condition): Add WANT_REG argument.
        Stop the search if we match it.
        * expr.h (canonicalize_condition): Update decl.
        * predict.c (expected_value_to_br_prob): Use it.  Track last
        expected value note.
        (find_expected_value): Remove.

        * reorg.c (mostly_true_jump): Always use BR_PROB if present.

From-SVN: r33214
parent a7384840
2000-04-17 Richard Henderson <rth@cygnus.com>
* loop.c (canonicalize_condition): Add WANT_REG argument.
Stop the search if we match it.
* expr.h (canonicalize_condition): Update decl.
* predict.c (expected_value_to_br_prob): Use it. Track last
expected value note.
(find_expected_value): Remove.
* reorg.c (mostly_true_jump): Always use BR_PROB if present.
2000-04-17 Zack Weinberg <zack@wolery.cumb.org> 2000-04-17 Zack Weinberg <zack@wolery.cumb.org>
* aclocal.m4 (AM_GNU_GETTEXT): Don't AC_REQUIRE([AC_FUNC_MMAP]). * aclocal.m4 (AM_GNU_GETTEXT): Don't AC_REQUIRE([AC_FUNC_MMAP]).
......
...@@ -894,7 +894,7 @@ extern rtx emit_store_flag_force PARAMS ((rtx, enum rtx_code, rtx, rtx, ...@@ -894,7 +894,7 @@ extern rtx emit_store_flag_force PARAMS ((rtx, enum rtx_code, rtx, rtx,
/* Given an insn and condition, return a canonical description of /* Given an insn and condition, return a canonical description of
the test being made. */ the test being made. */
extern rtx canonicalize_condition PARAMS ((rtx, rtx, int, rtx *)); extern rtx canonicalize_condition PARAMS ((rtx, rtx, int, rtx *, rtx));
/* Given a JUMP_INSN, return a canonical description of the test /* Given a JUMP_INSN, return a canonical description of the test
being made. */ being made. */
......
...@@ -9013,14 +9013,19 @@ update_reg_last_use (x, insn) ...@@ -9013,14 +9013,19 @@ update_reg_last_use (x, insn)
If EARLIEST is non-zero, it is a pointer to a place where the earliest If EARLIEST is non-zero, it is a pointer to a place where the earliest
insn used in locating the condition was found. If a replacement test insn used in locating the condition was found. If a replacement test
of the condition is desired, it should be placed in front of that of the condition is desired, it should be placed in front of that
insn and we will be sure that the inputs are still valid. */ insn and we will be sure that the inputs are still valid.
If WANT_REG is non-zero, we wish the condition to be relative to that
register, if possible. Therefore, do not canonicalize the condition
further. */
rtx rtx
canonicalize_condition (insn, cond, reverse, earliest) canonicalize_condition (insn, cond, reverse, earliest, want_reg)
rtx insn; rtx insn;
rtx cond; rtx cond;
int reverse; int reverse;
rtx *earliest; rtx *earliest;
rtx want_reg;
{ {
enum rtx_code code; enum rtx_code code;
rtx prev = insn; rtx prev = insn;
...@@ -9050,7 +9055,9 @@ canonicalize_condition (insn, cond, reverse, earliest) ...@@ -9050,7 +9055,9 @@ canonicalize_condition (insn, cond, reverse, earliest)
the same tests as a function of STORE_FLAG_VALUE as find_comparison_args the same tests as a function of STORE_FLAG_VALUE as find_comparison_args
in cse.c */ in cse.c */
while (GET_RTX_CLASS (code) == '<' && op1 == CONST0_RTX (GET_MODE (op0))) while (GET_RTX_CLASS (code) == '<'
&& op1 == CONST0_RTX (GET_MODE (op0))
&& op0 != want_reg)
{ {
/* Set non-zero when we find something of interest. */ /* Set non-zero when we find something of interest. */
rtx x = 0; rtx x = 0;
...@@ -9291,7 +9298,7 @@ get_condition (jump, earliest) ...@@ -9291,7 +9298,7 @@ get_condition (jump, earliest)
= GET_CODE (XEXP (SET_SRC (PATTERN (jump)), 2)) == LABEL_REF = GET_CODE (XEXP (SET_SRC (PATTERN (jump)), 2)) == LABEL_REF
&& XEXP (XEXP (SET_SRC (PATTERN (jump)), 2), 0) == JUMP_LABEL (jump); && XEXP (XEXP (SET_SRC (PATTERN (jump)), 2), 0) == JUMP_LABEL (jump);
return canonicalize_condition (jump, cond, reverse, earliest); return canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX);
} }
/* Similar to above routine, except that we also put an invariant last /* Similar to above routine, except that we also put an invariant last
......
...@@ -190,29 +190,46 @@ static rtx find_expected_value PARAMS ((rtx, rtx)); ...@@ -190,29 +190,46 @@ static rtx find_expected_value PARAMS ((rtx, rtx));
void void
expected_value_to_br_prob () expected_value_to_br_prob ()
{ {
rtx insn, cond, earliest, ev; rtx insn, cond, ev = NULL_RTX, ev_reg;
for (insn = get_insns (); insn ; insn = NEXT_INSN (insn)) for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
{ {
/* Look for simple conditional branches. */ switch (GET_CODE (insn))
if (GET_CODE (insn) != JUMP_INSN) {
case NOTE:
/* Look for expected value notes. */
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EXPECTED_VALUE)
{
ev = NOTE_EXPECTED_VALUE (insn);
ev_reg = XEXP (ev, 0);
}
continue;
case CODE_LABEL:
/* Never propagate across labels. */
ev = NULL_RTX;
continue;
default:
/* Look for insns that clobber the EV register. */
if (ev && reg_set_p (ev_reg, insn))
ev = NULL_RTX;
continue;
case JUMP_INSN:
/* Look for simple conditional branches. If we havn't got an
expected value yet, no point going further. */
if (GET_CODE (insn) != JUMP_INSN || ev == NULL_RTX)
continue; continue;
if (! condjump_p (insn) || simplejump_p (insn)) if (! condjump_p (insn) || simplejump_p (insn))
continue; continue;
break;
}
/* Collect the branch condition. Some machines can branch on /* Collect the branch condition, hopefully relative to EV_REG. */
user values directly, others need a compare instruction. If
the branch condition involves a MODE_INT register, try that
expression first. Otherwise use get_condition. */
cond = XEXP (SET_SRC (PATTERN (insn)), 0); cond = XEXP (SET_SRC (PATTERN (insn)), 0);
if (GET_RTX_CLASS (GET_CODE (cond)) != '<') cond = canonicalize_condition (insn, cond, 0, NULL, ev_reg);
abort (); if (! cond || XEXP (cond, 0) != ev_reg)
if (GET_CODE (XEXP (cond, 0)) == REG
&& GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_INT
&& (ev = find_expected_value (cond, insn)) != NULL_RTX)
;
else if ((cond = get_condition (insn, &earliest)) == NULL_RTX
|| (ev = find_expected_value (cond, earliest)) == NULL_RTX)
continue; continue;
/* Substitute and simplify. Given that the expression we're /* Substitute and simplify. Given that the expression we're
...@@ -223,48 +240,10 @@ expected_value_to_br_prob () ...@@ -223,48 +240,10 @@ expected_value_to_br_prob ()
cond = simplify_rtx (cond); cond = simplify_rtx (cond);
/* Turn the condition into a scaled branch probability. */ /* Turn the condition into a scaled branch probability. */
if (cond == const0_rtx) if (cond == const1_rtx)
cond = const1_rtx; cond = GEN_INT (REG_BR_PROB_BASE);
else if (cond == const1_rtx) else if (cond != const0_rtx)
cond = GEN_INT (REG_BR_PROB_BASE - 1);
else
abort (); abort ();
REG_NOTES (insn) = alloc_EXPR_LIST (REG_BR_PROB, cond, REG_NOTES (insn)); REG_NOTES (insn) = alloc_EXPR_LIST (REG_BR_PROB, cond, REG_NOTES (insn));
} }
} }
/* Search backwards for a NOTE_INSN_EXPECTED_VALUE note with a register
that matches the condition. */
static rtx
find_expected_value (cond, earliest)
rtx cond, earliest;
{
rtx insn, reg = XEXP (cond, 0);
int timeout;
/* The condition should be (op (reg) (const_int)), otherwise we
won't be able to intuit anything about it. */
if (GET_CODE (reg) != REG
|| GET_CODE (XEXP (cond, 1)) != CONST_INT
|| GET_MODE_CLASS (GET_MODE (reg)) != MODE_INT)
return NULL_RTX;
/* Assuming the user wrote something like `if (__builtin_expect(...))',
we shouldn't have to search too far. Also stop if we reach a code
label or if REG is modified. */
for (insn = earliest, timeout = 10;
insn && timeout > 0;
insn = PREV_INSN (insn), --timeout)
{
if (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_EXPECTED_VALUE
&& XEXP (NOTE_EXPECTED_VALUE (insn), 0) == reg)
return NOTE_EXPECTED_VALUE (insn);
if (GET_CODE (insn) == CODE_LABEL || reg_set_p (reg, insn))
break;
}
return NULL_RTX;
}
...@@ -900,18 +900,16 @@ mostly_true_jump (jump_insn, condition) ...@@ -900,18 +900,16 @@ mostly_true_jump (jump_insn, condition)
rtx jump_insn, condition; rtx jump_insn, condition;
{ {
rtx target_label = JUMP_LABEL (jump_insn); rtx target_label = JUMP_LABEL (jump_insn);
rtx insn; rtx insn, note;
int rare_dest = rare_destination (target_label); int rare_dest = rare_destination (target_label);
int rare_fallthrough = rare_destination (NEXT_INSN (jump_insn)); int rare_fallthrough = rare_destination (NEXT_INSN (jump_insn));
/* If branch probabilities are available, then use that number since it /* If branch probabilities are available, then use that number since it
always gives a correct answer. */ always gives a correct answer. */
if (flag_branch_probabilities) note = find_reg_note (jump_insn, REG_BR_PROB, 0);
{
rtx note = find_reg_note (jump_insn, REG_BR_PROB, 0);
if (note) if (note)
{ {
int prob = XINT (note, 0); int prob = INTVAL (XEXP (note, 0));
if (prob >= REG_BR_PROB_BASE * 9 / 10) if (prob >= REG_BR_PROB_BASE * 9 / 10)
return 2; return 2;
...@@ -922,7 +920,8 @@ mostly_true_jump (jump_insn, condition) ...@@ -922,7 +920,8 @@ mostly_true_jump (jump_insn, condition)
else else
return -1; return -1;
} }
}
/* ??? Ought to use estimate_probability instead. */
/* If this is a branch outside a loop, it is highly unlikely. */ /* If this is a branch outside a loop, it is highly unlikely. */
if (GET_CODE (PATTERN (jump_insn)) == SET if (GET_CODE (PATTERN (jump_insn)) == SET
......
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