This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Constant fold (c1/x)*c2 as (c1*c2)/x with -ffast-math
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 24 Aug 2003 21:12:05 -0600 (MDT)
- Subject: [PATCH] Constant fold (c1/x)*c2 as (c1*c2)/x with -ffast-math
The following patch adds two more constant folding transformations
that are only enabled with -funsafe-math-optimizations.
(c1/x)*c2 => (c1*c2)/x
c1/(x*c2) => (c1/c2)/x
Whilst I was there I also tidied up some of the code in fold <RDIV_EXPR>
where we were using braces around single statements, and where we weren't
recursively calling fold after building new subexpression trees.
The following patch has been tested on i686-pc-linux-gnu with a complete
"make bootstrap", all languages except treelang, and regression tested
with a top-level "make -k check" with no new failures.
Ok for mainline?
2003-08-24 Roger Sayle <roger@eyesopen.com>
* fold-const.c (fold <MULT_EXPR>): Optimize (C1/X)*C2 into
(C1*C2)/X when unsafe math optimizations are allowed.
(fold <RDIV_EXPR>): Optimize C1/(X*C2) into (C1/C2)/X with unsafe
math optimizations. Minor code clean-ups. Recursively call
fold when constructing sub-expressions.
* gcc.dg/20030824-1.c: New test case.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.297
diff -c -3 -p -r1.297 fold-const.c
*** fold-const.c 22 Aug 2003 06:45:13 -0000 1.297
--- fold-const.c 24 Aug 2003 22:55:35 -0000
*************** fold (tree expr)
*** 6060,6065 ****
--- 6060,6078 ----
&& real_minus_onep (arg1))
return fold (build1 (NEGATE_EXPR, type, arg0));
+ /* Convert (C1/X)*C2 into (C1*C2)/X. */
+ if (flag_unsafe_math_optimizations
+ && TREE_CODE (arg0) == RDIV_EXPR
+ && TREE_CODE (arg1) == REAL_CST
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST)
+ {
+ tree tem = const_binop (MULT_EXPR, TREE_OPERAND (arg0, 0),
+ arg1, 0);
+ if (tem)
+ return fold (build (RDIV_EXPR, type, tem,
+ TREE_OPERAND (arg0, 1)));
+ }
+
if (flag_unsafe_math_optimizations)
{
enum built_in_function fcode0 = builtin_mathfn_code (arg0);
*************** fold (tree expr)
*** 6393,6399 ****
arg1, 0)))
return fold (build (MULT_EXPR, type, arg0, tem));
/* Find the reciprocal if optimizing and the result is exact. */
! else if (optimize)
{
REAL_VALUE_TYPE r;
r = TREE_REAL_CST (arg1);
--- 6406,6412 ----
arg1, 0)))
return fold (build (MULT_EXPR, type, arg0, tem));
/* Find the reciprocal if optimizing and the result is exact. */
! if (optimize)
{
REAL_VALUE_TYPE r;
r = TREE_REAL_CST (arg1);
*************** fold (tree expr)
*** 6407,6425 ****
/* Convert A/B/C to A/(B*C). */
if (flag_unsafe_math_optimizations
&& TREE_CODE (arg0) == RDIV_EXPR)
! {
! return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
! build (MULT_EXPR, type, TREE_OPERAND (arg0, 1),
! arg1)));
! }
/* Convert A/(B/C) to (A/B)*C. */
if (flag_unsafe_math_optimizations
&& TREE_CODE (arg1) == RDIV_EXPR)
{
! return fold (build (MULT_EXPR, type,
! build (RDIV_EXPR, type, arg0,
! TREE_OPERAND (arg1, 0)),
! TREE_OPERAND (arg1, 1)));
}
if (flag_unsafe_math_optimizations)
--- 6420,6448 ----
/* Convert A/B/C to A/(B*C). */
if (flag_unsafe_math_optimizations
&& TREE_CODE (arg0) == RDIV_EXPR)
! return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
! fold (build (MULT_EXPR, type,
! TREE_OPERAND (arg0, 1), arg1))));
!
/* Convert A/(B/C) to (A/B)*C. */
if (flag_unsafe_math_optimizations
&& TREE_CODE (arg1) == RDIV_EXPR)
+ return fold (build (MULT_EXPR, type,
+ fold (build (RDIV_EXPR, type, arg0,
+ TREE_OPERAND (arg1, 0))),
+ TREE_OPERAND (arg1, 1)));
+
+ /* Convert C1/(X*C2) into (C1/C2)/X. */
+ if (flag_unsafe_math_optimizations
+ && TREE_CODE (arg1) == MULT_EXPR
+ && TREE_CODE (arg0) == REAL_CST
+ && TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST)
{
! tree tem = const_binop (RDIV_EXPR, arg0,
! TREE_OPERAND (arg1, 1), 0);
! if (tem)
! return fold (build (RDIV_EXPR, type, tem,
! TREE_OPERAND (arg1, 0)));
}
if (flag_unsafe_math_optimizations)
/* Copyright (C) 2003 Free Software Foundation.
Check that constant folding of mathematical expressions doesn't
break anything.
Written by Roger Sayle, 24th August 2003. */
/* { dg-do run } */
/* { dg-options "-O2 -ffast-math" } */
void abort(void);
double foo(double x)
{
return 12.0/(x*3.0);
}
double bar(double x)
{
return (3.0/x)*4.0;
}
int main()
{
if (foo(2.0) != 2.0)
abort ();
if (bar(2.0) != 6.0)
abort ();
return 0;
}
Roger
--
Roger Sayle, E-mail: roger@eyesopen.com
OpenEye Scientific Software, WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road, Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507. Fax: (+1) 505-473-0833