expmed.c (const_mult_add_overflow_p): New.

* expmed.c (const_mult_add_overflow_p): New.
        * expr.h: Declare it.
        * loop.c (maybe_eliminate_biv_1) [COMPARE]: Use it.
        Don't eliminate the biv if the giv has a constant multiplier and
        the rhs argument of the comparison does satisfy the predicate.
        Use expand_mult_add to compute the replacement constant.

From-SVN: r54075
This commit is contained in:
Eric Botcazou 2002-05-30 21:33:32 +00:00 committed by Richard Henderson
parent d18b1ed89e
commit ce60bf25b2
4 changed files with 69 additions and 6 deletions

View File

@ -1,3 +1,12 @@
2002-05-30 Eric Botcazou <ebotcazou@multimania.com>
* expmed.c (const_mult_add_overflow_p): New.
* expr.h: Declare it.
* loop.c (maybe_eliminate_biv_1) [COMPARE]: Use it.
Don't eliminate the biv if the giv has a constant multiplier and
the rhs argument of the comparison does satisfy the predicate.
Use expand_mult_add to compute the replacement constant.
2002-05-30 Osku Salerma <osku@iki.fi>
* c-common.c (c_common_attribute_table): Add "may_alias" entry.

View File

@ -4156,6 +4156,44 @@ make_tree (type, x)
}
}
/* Check whether the multiplication X * MULT + ADD overflows.
X, MULT and ADD must be CONST_*.
MODE is the machine mode for the computation.
X and MULT must have mode MODE. ADD may have a different mode.
So can X (defaults to same as MODE).
UNSIGNEDP is non-zero to do unsigned multiplication. */
bool
const_mult_add_overflow_p (x, mult, add, mode, unsignedp)
rtx x, mult, add;
enum machine_mode mode;
int unsignedp;
{
tree type, mult_type, add_type, result;
type = (*lang_hooks.types.type_for_mode) (mode, unsignedp);
/* In order to get a proper overflow indication from an unsigned
type, we have to pretend that it's a sizetype. */
mult_type = type;
if (unsignedp)
{
mult_type = copy_node (type);
TYPE_IS_SIZETYPE (mult_type) = 1;
}
add_type = (GET_MODE (add) == VOIDmode ? mult_type
: (*lang_hooks.types.type_for_mode) (GET_MODE (add), unsignedp));
result = fold (build (PLUS_EXPR, mult_type,
fold (build (MULT_EXPR, mult_type,
make_tree (mult_type, x),
make_tree (mult_type, mult))),
make_tree (add_type, add)));
return TREE_CONSTANT_OVERFLOW (result);
}
/* Return an rtx representing the value of X * MULT + ADD.
TARGET is a suggestion for where to store the result (an rtx).
MODE is the machine mode for the computation.

View File

@ -758,6 +758,7 @@ extern rtx extract_bit_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
enum machine_mode, enum machine_mode,
HOST_WIDE_INT));
extern rtx expand_mult PARAMS ((enum machine_mode, rtx, rtx, rtx, int));
extern bool const_mult_add_overflow_p PARAMS ((rtx, rtx, rtx, enum machine_mode, int));
extern rtx expand_mult_add PARAMS ((rtx, rtx, rtx, rtx,enum machine_mode, int));
extern rtx expand_mult_highpart_adjust PARAMS ((enum machine_mode, rtx, rtx, rtx, rtx, int));

View File

@ -8863,6 +8863,22 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
if (! biv_elimination_giv_has_0_offset (bl->biv, v, insn))
continue;
/* Don't eliminate if the linear combination that makes up
the giv overflows when it is applied to ARG. */
if (GET_CODE (arg) == CONST_INT)
{
rtx add_val;
if (GET_CODE (v->add_val) == CONST_INT)
add_val = v->add_val;
else
add_val = const0_rtx;
if (const_mult_add_overflow_p (arg, v->mult_val,
add_val, mode, 1))
continue;
}
if (! eliminate_p)
return 1;
@ -8873,13 +8889,10 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
the derived constant can be directly placed in the COMPARE,
do so. */
if (GET_CODE (arg) == CONST_INT
&& GET_CODE (v->mult_val) == CONST_INT
&& GET_CODE (v->add_val) == CONST_INT)
{
validate_change (insn, &XEXP (x, arg_operand),
GEN_INT (INTVAL (arg)
* INTVAL (v->mult_val)
+ INTVAL (v->add_val)), 1);
tem = expand_mult_add (arg, NULL_RTX, v->mult_val,
v->add_val, mode, 1);
}
else
{
@ -8888,8 +8901,10 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
loop_iv_add_mult_emit_before (loop, arg,
v->mult_val, v->add_val,
tem, where_bb, where_insn);
validate_change (insn, &XEXP (x, arg_operand), tem, 1);
}
validate_change (insn, &XEXP (x, arg_operand), tem, 1);
if (apply_change_group ())
return 1;
}