Message ID | 20130304210128.GR12913@tucnak.redhat.com |
---|---|
State | New |
Headers | show |
[Sorry Jakub, mid-air collision. I just posted this comment to the PR.] Jakub Jelinek <jakub@redhat.com> writes: > Optimizing (truncate:A (subreg:B (truncate:C X) 0)) into > (truncate:A X) is wrong if C mode is narrower than A mode. > The following patch fixes that and simplifies it into > (subreg:A (truncate:C X 0)) instead. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? Thanks for the fix. Looks good to me FWIW. However... > --- gcc/simplify-rtx.c.jj 2013-02-12 11:23:37.000000000 +0100 > +++ gcc/simplify-rtx.c 2013-03-04 11:32:44.111721542 +0100 > @@ -757,8 +757,18 @@ simplify_truncation (enum machine_mode m > && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (op))) > && GET_CODE (SUBREG_REG (op)) == TRUNCATE > && subreg_lowpart_p (op)) > - return simplify_gen_unary (TRUNCATE, mode, XEXP (SUBREG_REG (op), 0), > - GET_MODE (XEXP (SUBREG_REG (op), 0))); > + { > + rtx inner = XEXP (SUBREG_REG (op), 0); > + if (GET_MODE_PRECISION (mode) > + <= GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))) > + return simplify_gen_unary (TRUNCATE, mode, inner, GET_MODE (inner)); > + /* If subreg above is paradoxical and C is narrower > + than A, return (subreg:A (truncate:C X) 0). */ > + if (GET_MODE_PRECISION (op_mode) > + > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))) > + return simplify_gen_subreg (mode, SUBREG_REG (op), > + GET_MODE (SUBREG_REG (op)), 0); > + } ...truncations can't be to a narrower mode (already asserted at the top of the function) so in some ways I think it would be clearer to have an "if ... else" rather than two "if"s. Richard
--- gcc/simplify-rtx.c.jj 2013-02-12 11:23:37.000000000 +0100 +++ gcc/simplify-rtx.c 2013-03-04 11:32:44.111721542 +0100 @@ -757,8 +757,18 @@ simplify_truncation (enum machine_mode m && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (op))) && GET_CODE (SUBREG_REG (op)) == TRUNCATE && subreg_lowpart_p (op)) - return simplify_gen_unary (TRUNCATE, mode, XEXP (SUBREG_REG (op), 0), - GET_MODE (XEXP (SUBREG_REG (op), 0))); + { + rtx inner = XEXP (SUBREG_REG (op), 0); + if (GET_MODE_PRECISION (mode) + <= GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))) + return simplify_gen_unary (TRUNCATE, mode, inner, GET_MODE (inner)); + /* If subreg above is paradoxical and C is narrower + than A, return (subreg:A (truncate:C X) 0). */ + if (GET_MODE_PRECISION (op_mode) + > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))) + return simplify_gen_subreg (mode, SUBREG_REG (op), + GET_MODE (SUBREG_REG (op)), 0); + } /* (truncate:A (truncate:B X)) is (truncate:A X). */ if (GET_CODE (op) == TRUNCATE) --- gcc/testsuite/gcc.dg/pr56494.c.jj 2013-03-04 11:37:16.285155928 +0100 +++ gcc/testsuite/gcc.dg/pr56494.c 2013-03-04 11:36:59.000000000 +0100 @@ -0,0 +1,13 @@ +/* PR rtl-optimization/56494 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftracer -w" } */ + +char a; +short b; +void bar (int); + +void +foo (void) +{ + bar ((!!b ? : (a *= a / 0)) >= (a = b)); +}