* expr.h (canonicalize_condition, get_condition): Add an int argument.
* gcse.c (fis_get_condition): Reimplement using get_condition, leaving
it to check whether the condition is still valid at the jump insn.
* ifcvt.c (noce_get_condition): Likewise.
(noce_get_alt_condition): Update call to canonicalize_condition.
* loop-iv.c (simplify_using_initial_values): Update call to
get_condition. Remove FIXME.
(check_simple_exit): Update call to get_condition.
* loop-unswitch.c (may_unswitch_on): Likewise.
* loop.c (check_dbra_loop): Likewise.
(canonicalize_condition, get_condition): Add an argument to say whether
the condition must still be valid at INSN.
(get_condition_for_loop): Update call to get_condition. Require that
the condition be valid at INSN.
* predict.c (estimate_probability): Update call to get_condition.
Remove unused earliest parameter.
(expected_value_to_br_prob): Update call to canonicalize_condition.
From-SVN: r85218
+2004-07-27 Richard Sandiford <rsandifo@redhat.com>
+
+ * expr.h (canonicalize_condition, get_condition): Add an int argument.
+ * gcse.c (fis_get_condition): Reimplement using get_condition, leaving
+ it to check whether the condition is still valid at the jump insn.
+ * ifcvt.c (noce_get_condition): Likewise.
+ (noce_get_alt_condition): Update call to canonicalize_condition.
+ * loop-iv.c (simplify_using_initial_values): Update call to
+ get_condition. Remove FIXME.
+ (check_simple_exit): Update call to get_condition.
+ * loop-unswitch.c (may_unswitch_on): Likewise.
+ * loop.c (check_dbra_loop): Likewise.
+ (canonicalize_condition, get_condition): Add an argument to say whether
+ the condition must still be valid at INSN.
+ (get_condition_for_loop): Update call to get_condition. Require that
+ the condition be valid at INSN.
+ * predict.c (estimate_probability): Update call to get_condition.
+ Remove unused earliest parameter.
+ (expected_value_to_br_prob): Update call to canonicalize_condition.
+
2004-07-26 Eric Christopher <echristo@redhat.com>
* tree-dfa.c (add_referenced_var): Register initializers of global
/* Given an insn and condition, return a canonical description of
the test being made. */
-extern rtx canonicalize_condition (rtx, rtx, int, rtx *, rtx, int);
+extern rtx canonicalize_condition (rtx, rtx, int, rtx *, rtx, int, int);
/* Given a JUMP_INSN, return a canonical description of the test
being made. */
-extern rtx get_condition (rtx, rtx *, int);
+extern rtx get_condition (rtx, rtx *, int, int);
/* Generate a conditional trap instruction. */
extern rtx gen_cond_trap (enum rtx_code, rtx, rtx, rtx);
rtx
fis_get_condition (rtx jump)
{
- rtx cond, set, tmp, insn, earliest;
- bool reverse;
-
- if (! any_condjump_p (jump))
- return NULL_RTX;
-
- set = pc_set (jump);
- cond = XEXP (SET_SRC (set), 0);
-
- /* If this branches to JUMP_LABEL when the condition is false,
- reverse the condition. */
- reverse = (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
- && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (jump));
-
- /* Use canonicalize_condition to do the dirty work of manipulating
- MODE_CC values and COMPARE rtx codes. */
- tmp = canonicalize_condition (jump, cond, reverse, &earliest, NULL_RTX,
- false);
- if (!tmp)
- return NULL_RTX;
-
- /* Verify that the given condition is valid at JUMP by virtue of not
- having been modified since EARLIEST. */
- for (insn = earliest; insn != jump; insn = NEXT_INSN (insn))
- if (INSN_P (insn) && modified_in_p (tmp, insn))
- break;
- if (insn == jump)
- return tmp;
-
- /* The condition was modified. See if we can get a partial result
- that doesn't follow all the reversals. Perhaps combine can fold
- them together later. */
- tmp = XEXP (tmp, 0);
- if (!REG_P (tmp) || GET_MODE_CLASS (GET_MODE (tmp)) != MODE_INT)
- return NULL_RTX;
- tmp = canonicalize_condition (jump, cond, reverse, &earliest, tmp,
- false);
- if (!tmp)
- return NULL_RTX;
-
- /* For sanity's sake, re-validate the new result. */
- for (insn = earliest; insn != jump; insn = NEXT_INSN (insn))
- if (INSN_P (insn) && modified_in_p (tmp, insn))
- return NULL_RTX;
-
- return tmp;
+ return get_condition (jump, NULL, false, true);
}
/* Check the comparison COND to see if we can safely form an implicit set from
}
cond = canonicalize_condition (if_info->jump, cond, reverse,
- earliest, target, false);
+ earliest, target, false, true);
if (! cond || ! reg_mentioned_p (target, cond))
return NULL;
static rtx
noce_get_condition (rtx jump, rtx *earliest)
{
- rtx cond, set, tmp, insn;
+ rtx cond, set, tmp;
bool reverse;
if (! any_condjump_p (jump))
/* Otherwise, fall back on canonicalize_condition to do the dirty
work of manipulating MODE_CC values and COMPARE rtx codes. */
-
- tmp = canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX,
- false);
- if (!tmp)
- return NULL_RTX;
-
- /* We are going to insert code before JUMP, not before EARLIEST.
- We must therefore be certain that the given condition is valid
- at JUMP by virtue of not having been modified since. */
- for (insn = *earliest; insn != jump; insn = NEXT_INSN (insn))
- if (INSN_P (insn) && modified_in_p (tmp, insn))
- break;
- if (insn == jump)
- return tmp;
-
- /* The condition was modified. See if we can get a partial result
- that doesn't follow all the reversals. Perhaps combine can fold
- them together later. */
- tmp = XEXP (tmp, 0);
- if (!REG_P (tmp) || GET_MODE_CLASS (GET_MODE (tmp)) != MODE_INT)
- return NULL_RTX;
- tmp = canonicalize_condition (jump, cond, reverse, earliest, tmp,
- false);
- if (!tmp)
- return NULL_RTX;
-
- /* For sanity's sake, re-validate the new result. */
- for (insn = *earliest; insn != jump; insn = NEXT_INSN (insn))
- if (INSN_P (insn) && modified_in_p (tmp, insn))
- return NULL_RTX;
-
- return tmp;
+ return canonicalize_condition (jump, cond, reverse, earliest,
+ NULL_RTX, false, true);
}
/* Return true if OP is ok for if-then-else processing. */
insn = BB_END (e->src);
if (any_condjump_p (insn))
{
- /* FIXME -- slightly wrong -- what if compared register
- gets altered between start of the condition and insn? */
- rtx cond = get_condition (BB_END (e->src), NULL, false);
+ rtx cond = get_condition (BB_END (e->src), NULL, false, true);
if (cond && (e->flags & EDGE_FALLTHRU))
cond = reversed_condition (cond);
desc->in_edge = ei;
/* Test whether the condition is suitable. */
- if (!(condition = get_condition (BB_END (ei->src), &at, false)))
+ if (!(condition = get_condition (BB_END (ei->src), &at, false, false)))
return;
if (ei->flags & EDGE_FALLTHRU)
return NULL_RTX;
/* Condition must be invariant. */
- test = get_condition (BB_END (bb), &at, true);
+ test = get_condition (BB_END (bb), &at, true, false);
if (!test)
return NULL_RTX;
/* Try to compute whether the compare/branch at the loop end is one or
two instructions. */
- get_condition (jump, &first_compare, false);
+ get_condition (jump, &first_compare, false, true);
if (first_compare == jump)
compare_and_branch = 1;
else if (first_compare == prev_nonnote_insn (jump))
If WANT_REG is nonzero, we wish the condition to be relative to that
register, if possible. Therefore, do not canonicalize the condition
further. If ALLOW_CC_MODE is nonzero, allow the condition returned
- to be a compare to a CC mode register. */
+ to be a compare to a CC mode register.
+
+ If VALID_AT_INSN_P, the condition must be valid at both *EARLIEST
+ and at INSN. */
rtx
canonicalize_condition (rtx insn, rtx cond, int reverse, rtx *earliest,
- rtx want_reg, int allow_cc_mode)
+ rtx want_reg, int allow_cc_mode, int valid_at_insn_p)
{
enum rtx_code code;
rtx prev = insn;
if (x)
{
+ /* If the caller is expecting the condition to be valid at INSN,
+ make sure X doesn't change before INSN. */
+ if (valid_at_insn_p)
+ if (modified_in_p (x, prev) || modified_between_p (x, prev, insn))
+ break;
if (COMPARISON_P (x))
code = GET_CODE (x);
if (reverse_code)
If EARLIEST is nonzero, 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 EARLIEST
+ is null, the returned condition will be valid at INSN.
If ALLOW_CC_MODE is nonzero, allow the condition returned to be a
- compare CC mode register. */
+ compare CC mode register.
+
+ VALID_AT_INSN_P is the same as for canonicalize_condition. */
rtx
-get_condition (rtx jump, rtx *earliest, int allow_cc_mode)
+get_condition (rtx jump, rtx *earliest, int allow_cc_mode, int valid_at_insn_p)
{
rtx cond;
int reverse;
&& XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (jump);
return canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX,
- allow_cc_mode);
+ allow_cc_mode, valid_at_insn_p);
}
/* Similar to above routine, except that we also put an invariant last
rtx
get_condition_for_loop (const struct loop *loop, rtx x)
{
- rtx comparison = get_condition (x, (rtx*) 0, false);
+ rtx comparison = get_condition (x, (rtx*) 0, false, true);
if (comparison == 0
|| ! loop_invariant_p (loop, XEXP (comparison, 0))
FOR_EACH_BB (bb)
{
rtx last_insn = BB_END (bb);
- rtx cond, earliest;
+ rtx cond;
edge e;
if (! can_predict_insn_p (last_insn))
}
}
- cond = get_condition (last_insn, &earliest, false);
+ cond = get_condition (last_insn, NULL, false, false);
if (! cond)
continue;
(lt r70, r71)
Could use cselib to try and reduce this further. */
cond = XEXP (SET_SRC (pc_set (insn)), 0);
- cond = canonicalize_condition (insn, cond, 0, NULL, ev_reg, false);
+ cond = canonicalize_condition (insn, cond, 0, NULL, ev_reg,
+ false, false);
if (! cond || XEXP (cond, 0) != ev_reg
|| GET_CODE (XEXP (cond, 1)) != CONST_INT)
continue;