This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR19988, canonicalize to positive FP constants


This fixes PR19988 - a complaint that we fail to CSE the multiplication
in ((x + 0.1234 * y) * (x - 0.1234 * y)) because we fold
x - 0.1234 * y to x + -0.1234 * y.  For CSE it is better to canonicalize
to "same" things, including same constants.  So the suggested fix is
to try to canonicalize to positive floating point constants instead
of canonicalizing to PLUS_EXPR.

This not only fixes the above CSE case but also should reduce the
number of constant pool entries in some cases.

To check the impact of this patch I built SPEC2006 FP and compared
binaries which shows they are all identical.  The patch will regress
its testcase on architectures with FMAs due to the exposed CSE
opportunity and the inability of combine to handle multiple-use
operands in this case.  Like CSEd widenings for widening multiplication
detection this should probably be enhanced during RTL expansion or
a tree lowering pass (I opened PR42802 for this).  Note that the
existing FMA code that is emitted is suboptimal as it loads two
constants instead of one, so I doubt the single additional
multiplication makes the generated code worse.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Any opinions?  If not I'm going to apply this in a few days and
close the bug.

Thanks,
Richard.

2010-01-19  Richard Guenther  <rguenther@suse.de>

	PR middle-end/19988
	* fold-const.c (negate_expr_p): Pretend only negative
	real constants are easily negatable.

	* gcc.dg/pr19988.c: New testcase.

Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c	(revision 156009)
--- gcc/fold-const.c	(working copy)
*************** negate_expr_p (tree t)
*** 1129,1138 ****
  	      && TYPE_OVERFLOW_WRAPS (type));
  
      case FIXED_CST:
-     case REAL_CST:
      case NEGATE_EXPR:
        return true;
  
      case COMPLEX_CST:
        return negate_expr_p (TREE_REALPART (t))
  	     && negate_expr_p (TREE_IMAGPART (t));
--- 1129,1142 ----
  	      && TYPE_OVERFLOW_WRAPS (type));
  
      case FIXED_CST:
      case NEGATE_EXPR:
        return true;
  
+     case REAL_CST:
+       /* We want to canonicalize to positive real constants.  Pretend
+          that only negative ones can be easily negated.  */
+       return REAL_VALUE_NEGATIVE (TREE_REAL_CST (t));
+ 
      case COMPLEX_CST:
        return negate_expr_p (TREE_REALPART (t))
  	     && negate_expr_p (TREE_IMAGPART (t));
Index: gcc/testsuite/gcc.dg/pr19988.c
===================================================================
*** gcc/testsuite/gcc.dg/pr19988.c	(revision 0)
--- gcc/testsuite/gcc.dg/pr19988.c	(revision 0)
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-optimized -fdump-tree-original" } */
+ 
+ double foo(double x, double y)
+ {
+   return ((x + 0.1234 * y) * (x - 0.1234 * y));
+ }
+ 
+ /* Keep positive constants during folding.  */
+ /* { dg-final { scan-tree-dump-times " 1.23" 2 "original" } } */
+ /* CSE one multiplication.  */
+ /* { dg-final { scan-tree-dump-times " \\\* " 2 "optimized" } } */
+ /* { dg-final { cleanup-tree-dump "original" } } */
+ /* { dg-final { cleanup-tree-dump "optimized" } } */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]