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>
* 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,
/* Given an insn and condition, return a canonical description of
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
being made. */
......
......@@ -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
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
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
canonicalize_condition (insn, cond, reverse, earliest)
canonicalize_condition (insn, cond, reverse, earliest, want_reg)
rtx insn;
rtx cond;
int reverse;
rtx *earliest;
rtx want_reg;
{
enum rtx_code code;
rtx prev = insn;
......@@ -9050,7 +9055,9 @@ canonicalize_condition (insn, cond, reverse, earliest)
the same tests as a function of STORE_FLAG_VALUE as find_comparison_args
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. */
rtx x = 0;
......@@ -9291,7 +9298,7 @@ get_condition (jump, earliest)
= GET_CODE (XEXP (SET_SRC (PATTERN (jump)), 2)) == LABEL_REF
&& 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
......
......@@ -190,29 +190,46 @@ static rtx find_expected_value PARAMS ((rtx, rtx));
void
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))
{
/* Look for simple conditional branches. */
if (GET_CODE (insn) != JUMP_INSN)
continue;
if (! condjump_p (insn) || simplejump_p (insn))
continue;
switch (GET_CODE (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;
/* Collect the branch condition. Some machines can branch on
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. */
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;
if (! condjump_p (insn) || simplejump_p (insn))
continue;
break;
}
/* Collect the branch condition, hopefully relative to EV_REG. */
cond = XEXP (SET_SRC (PATTERN (insn)), 0);
if (GET_RTX_CLASS (GET_CODE (cond)) != '<')
abort ();
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)
cond = canonicalize_condition (insn, cond, 0, NULL, ev_reg);
if (! cond || XEXP (cond, 0) != ev_reg)
continue;
/* Substitute and simplify. Given that the expression we're
......@@ -223,48 +240,10 @@ expected_value_to_br_prob ()
cond = simplify_rtx (cond);
/* Turn the condition into a scaled branch probability. */
if (cond == const0_rtx)
cond = const1_rtx;
else if (cond == const1_rtx)
cond = GEN_INT (REG_BR_PROB_BASE - 1);
else
if (cond == const1_rtx)
cond = GEN_INT (REG_BR_PROB_BASE);
else if (cond != const0_rtx)
abort ();
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,30 +900,29 @@ mostly_true_jump (jump_insn, condition)
rtx jump_insn, condition;
{
rtx target_label = JUMP_LABEL (jump_insn);
rtx insn;
rtx insn, note;
int rare_dest = rare_destination (target_label);
int rare_fallthrough = rare_destination (NEXT_INSN (jump_insn));
/* If branch probabilities are available, then use that number since it
always gives a correct answer. */
if (flag_branch_probabilities)
note = find_reg_note (jump_insn, REG_BR_PROB, 0);
if (note)
{
rtx note = find_reg_note (jump_insn, REG_BR_PROB, 0);
if (note)
{
int prob = XINT (note, 0);
int prob = INTVAL (XEXP (note, 0));
if (prob >= REG_BR_PROB_BASE * 9 / 10)
return 2;
else if (prob >= REG_BR_PROB_BASE / 2)
return 1;
else if (prob >= REG_BR_PROB_BASE / 10)
return 0;
else
return -1;
}
if (prob >= REG_BR_PROB_BASE * 9 / 10)
return 2;
else if (prob >= REG_BR_PROB_BASE / 2)
return 1;
else if (prob >= REG_BR_PROB_BASE / 10)
return 0;
else
return -1;
}
/* ??? Ought to use estimate_probability instead. */
/* If this is a branch outside a loop, it is highly unlikely. */
if (GET_CODE (PATTERN (jump_insn)) == SET
&& GET_CODE (SET_SRC (PATTERN (jump_insn))) == IF_THEN_ELSE
......
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