Commit e9aaa5a5 by Richard Kenner

(fold, associate): If -ffast-math, associate FP mults.

(fold, case RDIV_EXPR): Split case; ignore division by 1.
If -ffast-math, convert to multply by reciprocal.
(fold, case *_DIV_EXPR): Simplify A/C1/C2.

From-SVN: r6780
parent d0cb4c65
...@@ -3666,9 +3666,13 @@ fold (expr) ...@@ -3666,9 +3666,13 @@ fold (expr)
associate: associate:
/* In most languages, can't associate operations on floats /* In most languages, can't associate operations on floats
through parentheses. Rather than remember where the parentheses through parentheses. Rather than remember where the parentheses
were, we don't associate floats at all. It shouldn't matter much. */ were, we don't associate floats at all. It shouldn't matter much.
if (FLOAT_TYPE_P (type)) However, associating multiplications is only very slightly
inaccurate, so do that if -ffast-math is specified. */
if (FLOAT_TYPE_P (type)
&& ! (flag_fast_math && code == MULT_EXPR))
goto binary; goto binary;
/* The varsign == -1 cases happen only for addition and subtraction. /* The varsign == -1 cases happen only for addition and subtraction.
It says that the arg that was split was really CON minus VAR. It says that the arg that was split was really CON minus VAR.
The rest of the code applies to all associative operations. */ The rest of the code applies to all associative operations. */
...@@ -3958,17 +3962,80 @@ fold (expr) ...@@ -3958,17 +3962,80 @@ fold (expr)
} }
goto binary; goto binary;
case RDIV_EXPR:
/* In most cases, do nothing with a divide by zero. */
#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
#ifndef REAL_INFINITY
if (TREE_CODE (arg1) == REAL_CST && real_zerop (arg1))
return t;
#endif
#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
/* In IEEE floating point, x/1 is not equivalent to x for snans.
However, ANSI says we can drop signals, so we can do this anyway. */
if (real_onep (arg1))
return non_lvalue (convert (type, arg0));
/* If ARG1 is a constant, we can convert this to a multiply by the
reciprocal. This does not have the same rounding properties,
so only do this if -ffast-math. We can actually always safely
do it if ARG1 is a power of two, but it's hard to tell if it is
or not in a portable manner. */
if (TREE_CODE (arg1) == REAL_CST && flag_fast_math
&& 0 != (tem = const_binop (code, build_real (type, dconst1),
arg1, 0)))
return fold (build (MULT_EXPR, type, arg0, tem));
goto binary;
case TRUNC_DIV_EXPR: case TRUNC_DIV_EXPR:
case ROUND_DIV_EXPR: case ROUND_DIV_EXPR:
case FLOOR_DIV_EXPR: case FLOOR_DIV_EXPR:
case CEIL_DIV_EXPR: case CEIL_DIV_EXPR:
case EXACT_DIV_EXPR: case EXACT_DIV_EXPR:
case RDIV_EXPR:
if (integer_onep (arg1)) if (integer_onep (arg1))
return non_lvalue (convert (type, arg0)); return non_lvalue (convert (type, arg0));
if (integer_zerop (arg1)) if (integer_zerop (arg1))
return t; return t;
/* If we have ((a / C1) / C2) where both division are the same type, tr
to simplify. First see if C1 * C2 overflows or not. */
if (TREE_CODE (arg0) == code && TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
tem = const_binop (MULT_EXPR, TREE_OPERAND (arg0, 1), arg1, 0);
/* If it overflows, the result is +/- 1 or zero, depending on
the signs of the two constants and the division operation. */
if (TREE_OVERFLOW (tem))
{
switch (code)
{
case EXACT_DIV_EXPR:
case TRUNC_DIV_EXPR:
tem = integer_zero_node;
break;
case FLOOR_DIV_EXPR:
/* -1 if signs disagree, else 0. */
tem = (((tree_int_cst_sgn (TREE_OPERAND (arg0, 1)) < 0)
!= (tree_int_cst_sgn (arg1) < 0))
? build_int_2 (-1, -1) : integer_zero_node);
break;
case CEIL_DIV_EXPR:
/* 1 if signs agree, else 0. */
tem = (((tree_int_cst_sgn (TREE_OPERAND (arg0, 1)) < 0)
== (tree_int_cst_sgn (arg1) < 0))
? integer_one_node : integer_zero_node);
break;
}
return omit_one_operand (type, tem, TREE_OPERAND (arg0, 0));
}
else
/* If no overflow, divide by C1*C2. */
return fold (build (code, type, TREE_OPERAND (arg0, 0), tem));
}
/* Look for ((a * C1) / C3) or (((a * C1) + C2) / C3), /* Look for ((a * C1) / C3) or (((a * C1) + C2) / C3),
where C1 % C3 == 0 or C3 % C1 == 0. We can simplify these where C1 % C3 == 0 or C3 % C1 == 0. We can simplify these
expressions, which often appear in the offsets or sizes of expressions, which often appear in the offsets or sizes of
...@@ -4044,14 +4111,6 @@ fold (expr) ...@@ -4044,14 +4111,6 @@ fold (expr)
} }
} }
#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
#ifndef REAL_INFINITY
if (TREE_CODE (arg1) == REAL_CST
&& real_zerop (arg1))
return t;
#endif
#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
goto binary; goto binary;
case CEIL_MOD_EXPR: case CEIL_MOD_EXPR:
......
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