This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Canonicalize FP "X + (-C)" as "X - C"
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 11 Jul 2004 10:12:25 -0600 (MDT)
- Subject: [PATCH] Canonicalize FP "X + (-C)" as "X - C"
The following patch affects how tree constant folding canonicalizes
floating point additions and subtractions of immediate constants.
For integer operations, GCC prefers to canonicalize such expressions
to always be additions by creating positive and negative constants.
The proposal is that for floating point expressions we do the reverse
and canonicalize floating point expressions such that the immediate
constant is always positive by using addition or subtraction as
appropriate.
The two motivations for this policy are (i) that many architectures
store constant floating point values in constant pools. By attempting
to keep these values canonical, we attempt to reduce pool size, and
can reuse/CSE/GCSE these values. And (ii) that several architectures
have instructions for efficiently loading floating point constants,
such as the x87's "fld1" instruction. By keeping constants positive,
we get more opportunities to use these instructions. I believe that
there are no architectures that don't provide both floating point
addition and subtraction, or where one is slower than the other.
To demonstrate (i) consider the following function:
double x, y;
void foo()
{
x += 5.0;
y -= 5.0;
}
Currently GCC generates the following "-O2 -fomit-frame-pointer":
.LC7: .long 1084227584
.LC8: .long -1063256064
foo: flds .LC7
faddl x
fstpl x
flds .LC8
faddl y
fstpl y
ret
With the patch below we now generate:
.LC9: .long 1084227584
foo: flds .LC9
fldl x
fadd %st(1), %st
fxch %st(1)
fsubrl y
fxch %st(1)
fstpl x
fstpl y
ret
which has one less memory access, and a smaller constant pool. The
improvement is probably more obvious for rs6000 and other architectures
that can reuse this intermediate without manipulating a register stack.
To demonstrate (ii) consider the following function
double bar(double x)
{
return x - 1.0;
}
Currently we generate the following
.LC2: .long -1082130432
bar: flds .LC2
faddl 4(%esp)
ret
but with the patch below we now get
bar: fld1
fsubrl 4(%esp)
ret
The mechanics of the patch are straight forward, but I thought I'd
ask whether anyone's unhappy that we canonicalize integer and floating
point expressions differently. At the moment this doesn't affect RTL
canonicalization, but clearly this change has implications there.
The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all default languages, and regression tested with a
top-level "make -k check" with no new failures.
Ok for mainline?
2004-07-11 Roger Sayle <roger@eyesopen.com>
* fold-const.c (fold) <PLUS_EXPR>: Canonicalize X + -C as X - C for
floating point additions, to keep real immediate constant positive.
<MINUS_EXPR>: For floating point subtractions, only transform X - -C
into X + C, and leave positive real constants as X - C.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.421
diff -c -3 -p -r1.421 fold-const.c
*** fold-const.c 8 Jul 2004 17:40:22 -0000 1.421
--- fold-const.c 11 Jul 2004 03:48:56 -0000
*************** fold (tree expr)
*** 6589,6594 ****
--- 6589,6605 ----
if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
return non_lvalue (fold_convert (type, arg1));
+ /* Convert X + -C into X - C. */
+ if (TREE_CODE (arg1) == REAL_CST
+ && REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1)))
+ {
+ tem = fold_negate_const (arg1, type);
+ if (!TREE_OVERFLOW (arg1) || !flag_trapping_math)
+ return fold (build2 (MINUS_EXPR, type,
+ fold_convert (type, arg0),
+ fold_convert (type, tem)));
+ }
+
/* Convert x+x into x*2.0. */
if (operand_equal_p (arg0, arg1, 0)
&& SCALAR_FLOAT_TYPE_P (type))
*************** fold (tree expr)
*** 6921,6927 ****
/* A - B -> A + (-B) if B is easily negatable. */
if (!wins && negate_expr_p (arg1)
! && (FLOAT_TYPE_P (type)
|| (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv)))
return fold (build2 (PLUS_EXPR, type, arg0, negate_expr (arg1)));
--- 6932,6941 ----
/* A - B -> A + (-B) if B is easily negatable. */
if (!wins && negate_expr_p (arg1)
! && ((FLOAT_TYPE_P (type)
! /* Avoid this transformation if B is a positive REAL_CST. */
! && (TREE_CODE (arg1) != REAL_CST
! || REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1))))
|| (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv)))
return fold (build2 (PLUS_EXPR, type, arg0, negate_expr (arg1)));
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