From: Alexandre Oliva Date: Wed, 20 Feb 2002 23:15:00 +0000 (+0000) Subject: combine.c (do_SUBST): Sanity check substitutions of CONST_INTs... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4161da12190d52eb1d622354e6ea67f67195c73c;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9538ca24128..7a64a64af8a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2002-02-20 Alexandre Oliva + + * 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 * c-decl.c (pushdecl): If no global declaration is found for an diff --git a/gcc/combine.c b/gcc/combine.c index eb825311613..dba799766ed 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -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--) diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 2db3ec0f7be..84b8cb240ce 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -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;