Commit fab2f52c by Alexandre Oliva Committed by Alexandre Oliva

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
parent 347669a0
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.
......
......@@ -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
......
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.
......
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment