combine.c (do_SUBST): Sanity check substitutions of CONST_INTs...

* combine.c (do_SUBST): Sanity check substitutions of
CONST_INTs, and reject them in SUBREGs and ZERO_EXTENDs.
(subst): Simplify SUBREG or ZERO_EXTEND instead of SUBSTing a
CONST_INT into its operand.
(known_cond): Likewise, for ZERO_EXTEND.
* simplify-rtx.c (simplify_unary_operation): Fix condition to
allow for simplification of wide modes.  Reject CONST_INTs in
ZERO_EXTEND when their actual mode is not given.

From-SVN: r49920
This commit is contained in:
Alexandre Oliva 2002-02-20 23:15:00 +00:00 committed by Alexandre Oliva
parent 8e8d61f5c1
commit 4161da1219
3 changed files with 90 additions and 5 deletions

View File

@ -1,3 +1,14 @@
2002-02-20 Alexandre Oliva <aoliva@redhat.com>
* combine.c (do_SUBST): Sanity check substitutions of
CONST_INTs, and reject them in SUBREGs and ZERO_EXTENDs.
(subst): Simplify SUBREG or ZERO_EXTEND instead of SUBSTing a
CONST_INT into its operand.
(known_cond): Likewise, for ZERO_EXTEND.
* simplify-rtx.c (simplify_unary_operation): Fix condition to
allow for simplification of wide modes. Reject CONST_INTs in
ZERO_EXTEND when their actual mode is not given.
2002-02-20 Alexandre Oliva <aoliva@redhat.com>
* c-decl.c (pushdecl): If no global declaration is found for an

View File

@ -424,6 +424,33 @@ do_SUBST (into, newval)
if (oldval == newval)
return;
/* We'd like to catch as many invalid transformations here as
possible. Unfortunately, there are way too many mode changes
that are perfectly valid, so we'd waste too much effort for
little gain doing the checks here. Focus on catching invalid
transformations involving integer constants. */
if (GET_MODE_CLASS (GET_MODE (oldval)) == MODE_INT
&& GET_CODE (newval) == CONST_INT)
{
/* Sanity check that we're replacing oldval with a CONST_INT
that is a valid sign-extension for the original mode. */
if (INTVAL (newval) != trunc_int_for_mode (INTVAL (newval),
GET_MODE (oldval)))
abort ();
/* Replacing the operand of a SUBREG or a ZERO_EXTEND with a
CONST_INT is not valid, because after the replacement, the
original mode would be gone. Unfortunately, we can't tell
when do_SUBST is called to replace the operand thereof, so we
perform this test on oldval instead, checking whether an
invalid replacement took place before we got here. */
if ((GET_CODE (oldval) == SUBREG
&& GET_CODE (SUBREG_REG (oldval)) == CONST_INT)
|| (GET_CODE (oldval) == ZERO_EXTEND
&& GET_CODE (XEXP (oldval, 0)) == CONST_INT))
abort ();
}
if (undobuf.frees)
buf = undobuf.frees, undobuf.frees = buf->next;
else
@ -3505,7 +3532,24 @@ subst (x, from, to, in_dest, unique_copy)
if (GET_CODE (new) == CLOBBER && XEXP (new, 0) == const0_rtx)
return new;
SUBST (XEXP (x, i), new);
if (GET_CODE (new) == CONST_INT && GET_CODE (x) == SUBREG)
{
x = simplify_subreg (GET_MODE (x), new,
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x));
if (! x)
abort ();
}
else if (GET_CODE (new) == CONST_INT
&& GET_CODE (x) == ZERO_EXTEND)
{
x = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
new, GET_MODE (XEXP (x, 0)));
if (! x)
abort ();
}
else
SUBST (XEXP (x, i), new);
}
}
}
@ -7449,6 +7493,31 @@ known_cond (x, cond, reg, val)
return x;
}
/* We don't have to handle SIGN_EXTEND here, because even in the
case of replacing something with a modeless CONST_INT, a
CONST_INT is already (supposed to be) a valid sign extension for
its narrower mode, which implies it's already properly
sign-extended for the wider mode. Now, for ZERO_EXTEND, the
story is different. */
else if (code == ZERO_EXTEND)
{
enum machine_mode inner_mode = GET_MODE (XEXP (x, 0));
rtx new, r = known_cond (XEXP (x, 0), cond, reg, val);
if (XEXP (x, 0) != r)
{
/* We must simplify the zero_extend here, before we lose
track of the original inner_mode. */
new = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
r, inner_mode);
if (new)
return new;
else
SUBST (XEXP (x, 0), r);
}
return x;
}
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)

View File

@ -528,8 +528,10 @@ simplify_unary_operation (code, mode, op, op_mode)
break;
case ZERO_EXTEND:
/* When zero-extending a CONST_INT, we need to know its
original mode. */
if (op_mode == VOIDmode)
op_mode = mode;
abort ();
if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT)
{
/* If we were really extending the mode,
@ -587,7 +589,8 @@ simplify_unary_operation (code, mode, op, op_mode)
/* We can do some operations on integer CONST_DOUBLEs. Also allow
for a DImode operation on a CONST_INT. */
else if (GET_MODE (trueop) == VOIDmode && width <= HOST_BITS_PER_INT * 2
else if (GET_MODE (trueop) == VOIDmode
&& width <= HOST_BITS_PER_WIDE_INT * 2
&& (GET_CODE (trueop) == CONST_DOUBLE
|| GET_CODE (trueop) == CONST_INT))
{
@ -631,8 +634,10 @@ simplify_unary_operation (code, mode, op, op_mode)
break;
case ZERO_EXTEND:
if (op_mode == VOIDmode
|| GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT)
if (op_mode == VOIDmode)
abort ();
if (GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT)
return 0;
hv = 0;