diff options
author | Alexandre Oliva <aoliva@redhat.com> | 2005-03-24 05:57:52 +0000 |
---|---|---|
committer | Alexandre Oliva <aoliva@gcc.gnu.org> | 2005-03-24 05:57:52 +0000 |
commit | fab2f52cf844f20ec3b575d41ad7e5c2d817190d (patch) | |
tree | 0505157da8df3cd049d8bef6cf9e8998c96a240f /gcc | |
parent | 347669a079a7005bf211e57cba5db24d0b99f2f3 (diff) | |
download | gcc-fab2f52cf844f20ec3b575d41ad7e5c2d817190d.zip gcc-fab2f52cf844f20ec3b575d41ad7e5c2d817190d.tar.gz gcc-fab2f52cf844f20ec3b575d41ad7e5c2d817190d.tar.bz2 |
re PR rtl-optimization/20532 (Bad code for DImode left shifts by 31 and then 1)
gcc/ChangeLog:
PR rtl-optimization/20532
* simplify-rtx.c (simplify_binary_operation_1): Protect from
overflow when adding coefficients for PLUS or MINUS.
(simplify_binary_operation_1): Handle CONST_DOUBLE exact power of
two as multiplier.
gcc/testsuite/ChangeLog:
PR rtl-optimization/20532
* gcc.target/i386/badshift.c: New.
From-SVN: r96982
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 90 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/badshift.c | 28 |
4 files changed, 113 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 081b91a..933e4e4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2005-03-24 Alexandre Oliva <aoliva@redhat.com> + + PR rtl-optimization/20532 + * simplify-rtx.c (simplify_binary_operation_1): Protect from + overflow when adding coefficients for PLUS or MINUS. + (simplify_binary_operation_1): Handle CONST_DOUBLE exact power of + two as multiplier. + 2005-03-23 Joseph S. Myers <joseph@codesourcery.com> * langhooks.h (truthvalue_conversion): Remove. diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index a703331..865d6f9 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -1257,44 +1257,67 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, if (! FLOAT_MODE_P (mode)) { - HOST_WIDE_INT coeff0 = 1, coeff1 = 1; + HOST_WIDE_INT coeff0h = 0, coeff1h = 0; + unsigned HOST_WIDE_INT coeff0l = 1, coeff1l = 1; rtx lhs = op0, rhs = op1; if (GET_CODE (lhs) == NEG) - coeff0 = -1, lhs = XEXP (lhs, 0); + { + coeff0l = -1; + coeff0h = -1; + lhs = XEXP (lhs, 0); + } else if (GET_CODE (lhs) == MULT && GET_CODE (XEXP (lhs, 1)) == CONST_INT) - coeff0 = INTVAL (XEXP (lhs, 1)), lhs = XEXP (lhs, 0); + { + coeff0l = INTVAL (XEXP (lhs, 1)); + coeff0h = INTVAL (XEXP (lhs, 1)) < 0 ? -1 : 0; + lhs = XEXP (lhs, 0); + } else if (GET_CODE (lhs) == ASHIFT && GET_CODE (XEXP (lhs, 1)) == CONST_INT && INTVAL (XEXP (lhs, 1)) >= 0 && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT) { - coeff0 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1)); + coeff0l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1)); + coeff0h = 0; lhs = XEXP (lhs, 0); } if (GET_CODE (rhs) == NEG) - coeff1 = -1, rhs = XEXP (rhs, 0); + { + coeff1l = -1; + coeff1h = -1; + rhs = XEXP (rhs, 0); + } else if (GET_CODE (rhs) == MULT && GET_CODE (XEXP (rhs, 1)) == CONST_INT) { - coeff1 = INTVAL (XEXP (rhs, 1)), rhs = XEXP (rhs, 0); + coeff1l = INTVAL (XEXP (rhs, 1)); + coeff1h = INTVAL (XEXP (rhs, 1)) < 0 ? -1 : 0; + rhs = XEXP (rhs, 0); } else if (GET_CODE (rhs) == ASHIFT && GET_CODE (XEXP (rhs, 1)) == CONST_INT && INTVAL (XEXP (rhs, 1)) >= 0 && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT) { - coeff1 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1)); + coeff1l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1)); + coeff1h = 0; rhs = XEXP (rhs, 0); } if (rtx_equal_p (lhs, rhs)) { rtx orig = gen_rtx_PLUS (mode, op0, op1); - tem = simplify_gen_binary (MULT, mode, lhs, - GEN_INT (coeff0 + coeff1)); + rtx coeff; + unsigned HOST_WIDE_INT l; + HOST_WIDE_INT h; + + add_double (coeff0l, coeff0h, coeff1l, coeff1h, &l, &h); + coeff = immed_double_const (l, h, mode); + + tem = simplify_gen_binary (MULT, mode, lhs, coeff); return rtx_cost (tem, SET) <= rtx_cost (orig, SET) ? tem : 0; } @@ -1405,46 +1428,67 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, if (! FLOAT_MODE_P (mode)) { - HOST_WIDE_INT coeff0 = 1, coeff1 = 1; + HOST_WIDE_INT coeff0h = 0, negcoeff1h = -1; + unsigned HOST_WIDE_INT coeff0l = 1, negcoeff1l = -1; rtx lhs = op0, rhs = op1; if (GET_CODE (lhs) == NEG) - coeff0 = -1, lhs = XEXP (lhs, 0); + { + coeff0l = -1; + coeff0h = -1; + lhs = XEXP (lhs, 0); + } else if (GET_CODE (lhs) == MULT && GET_CODE (XEXP (lhs, 1)) == CONST_INT) { - coeff0 = INTVAL (XEXP (lhs, 1)), lhs = XEXP (lhs, 0); + coeff0l = INTVAL (XEXP (lhs, 1)); + coeff0h = INTVAL (XEXP (lhs, 1)) < 0 ? -1 : 0; + lhs = XEXP (lhs, 0); } else if (GET_CODE (lhs) == ASHIFT && GET_CODE (XEXP (lhs, 1)) == CONST_INT && INTVAL (XEXP (lhs, 1)) >= 0 && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT) { - coeff0 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1)); + coeff0l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1)); + coeff0h = 0; lhs = XEXP (lhs, 0); } if (GET_CODE (rhs) == NEG) - coeff1 = - 1, rhs = XEXP (rhs, 0); + { + negcoeff1l = 1; + negcoeff1h = 0; + rhs = XEXP (rhs, 0); + } else if (GET_CODE (rhs) == MULT && GET_CODE (XEXP (rhs, 1)) == CONST_INT) { - coeff1 = INTVAL (XEXP (rhs, 1)), rhs = XEXP (rhs, 0); + negcoeff1l = -INTVAL (XEXP (rhs, 1)); + negcoeff1h = INTVAL (XEXP (rhs, 1)) <= 0 ? 0 : -1; + rhs = XEXP (rhs, 0); } else if (GET_CODE (rhs) == ASHIFT && GET_CODE (XEXP (rhs, 1)) == CONST_INT && INTVAL (XEXP (rhs, 1)) >= 0 && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT) { - coeff1 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1)); + negcoeff1l = -(((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1))); + negcoeff1h = -1; rhs = XEXP (rhs, 0); } if (rtx_equal_p (lhs, rhs)) { rtx orig = gen_rtx_MINUS (mode, op0, op1); - tem = simplify_gen_binary (MULT, mode, lhs, - GEN_INT (coeff0 - coeff1)); + rtx coeff; + unsigned HOST_WIDE_INT l; + HOST_WIDE_INT h; + + add_double (coeff0l, coeff0h, negcoeff1l, negcoeff1h, &l, &h); + coeff = immed_double_const (l, h, mode); + + tem = simplify_gen_binary (MULT, mode, lhs, coeff); return rtx_cost (tem, SET) <= rtx_cost (orig, SET) ? tem : 0; } @@ -1531,6 +1575,16 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, || val != HOST_BITS_PER_WIDE_INT - 1)) return simplify_gen_binary (ASHIFT, mode, op0, GEN_INT (val)); + /* Likewise for multipliers wider than a word. */ + else if (GET_CODE (trueop1) == CONST_DOUBLE + && (GET_MODE (trueop1) == VOIDmode + || GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_INT) + && GET_MODE (op0) == mode + && CONST_DOUBLE_LOW (trueop1) == 0 + && (val = exact_log2 (CONST_DOUBLE_HIGH (trueop1))) >= 0) + return simplify_gen_binary (ASHIFT, mode, op0, + GEN_INT (val + HOST_BITS_PER_WIDE_INT)); + /* x*2 is x+x and x*(-1) is -x */ if (GET_CODE (trueop1) == CONST_DOUBLE && GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 465d516..41fd479 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-03-24 Alexandre Oliva <aoliva@redhat.com> + + PR rtl-optimization/20532 + * gcc.target/i386/badshift.c: New. + 2005-03-23 Francois-Xavier Coudert <coudert@clipper.ens.fr> * pr18025.f90: New test. diff --git a/gcc/testsuite/gcc.target/i386/badshift.c b/gcc/testsuite/gcc.target/i386/badshift.c new file mode 100644 index 0000000..ddbf613 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/badshift.c @@ -0,0 +1,28 @@ +/* PR rtl-optimization/20532 */ + +/* { dg-do run } */ +/* { dg-options "-m32 -march=i386 -O1" } */ + +/* We used to optimize the DImode shift-by-32 to zero because in combine + we turned: + + (v << 31) * (v << 31) + + into: + + (v * (((HOST_WIDE_INT)1 << 31) + ((HOST_WIDE_INT)1 << 31))) + + With a 32-bit HOST_WIDE_INT, the coefficient overflowed to zero. */ + +unsigned long long int badshift(unsigned long long int v) +{ + return v << 31 << 1; +} + +extern void abort (); + +int main() { + if (badshift (1) == 0) + abort (); + return 0; +} |