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] Constant fold -A - B as -B - A (take 3)


On Fri, 7 Feb 2003, Richard Henderson wrote:
> On Sat, Feb 01, 2003 at 01:19:54PM -0700, Roger Sayle wrote:
> > The only change to the original is the addition of the constraint
> > "FLOAT_TYPE_P (type) || ! TYPE_TRAP_SIGNED (type)" ...
>
> I'll allow this with FLOAT_TYPE_P, but not integral modes.

Many thanks to Richard Henderson and Richard Kenner for convinving
me of the perils of signed arithmetic overflow in GCC's middle end.
Whilst working on a solution for that, I think I'll take the offer
that's on the table, and apply this optimization only to floating
point types, as recommended above.


The following patch has been retested by a complete make bootstrap,
all languages except Ada and treelang, on i686-pc-linux-gnu and a
full "make -k check" with no new regressions.

Ok for mainline?


2003-01-18  Roger Sayle  <roger@eyesopen.com>

	* fold-const.c (negate_expr_p): New function to determine whether
	an expression can be negated cheaply.
	(fold) [MINUS_EXPR]: Use it to determine whether to transform
	-A - B into -B - A for floating point types.


Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.235
diff -c -3 -p -r1.235 fold-const.c
*** fold-const.c	16 Feb 2003 08:24:25 -0000	1.235
--- fold-const.c	16 Feb 2003 19:18:30 -0000
***************
*** 1,6 ****
  /* Fold a constant sub-tree into a single node for C-compiler
!    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2002,
!    1999, 2000, 2001, 2002 Free Software Foundation, Inc.

  This file is part of GCC.

--- 1,6 ----
  /* Fold a constant sub-tree into a single node for C-compiler
!    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
!    2000, 2001, 2002, 2003 Free Software Foundation, Inc.

  This file is part of GCC.

*************** static void encode		PARAMS ((HOST_WIDE_I
*** 63,68 ****
--- 63,69 ----
  static void decode		PARAMS ((HOST_WIDE_INT *,
  					 unsigned HOST_WIDE_INT *,
  					 HOST_WIDE_INT *));
+ static bool negate_expr_p	PARAMS ((tree));
  static tree negate_expr		PARAMS ((tree));
  static tree split_tree		PARAMS ((tree, enum tree_code, tree *, tree *,
  					 tree *, int));
*************** div_and_round_double (code, uns,
*** 835,840 ****
--- 836,890 ----
    return overflow;
  }

+ /* Determine whether an expression T can be cheaply negated using
+    the function negate_expr.  */
+
+ static bool
+ negate_expr_p (t)
+      tree t;
+ {
+   unsigned HOST_WIDE_INT val;
+   unsigned int prec;
+   tree type;
+
+   if (t == 0)
+     return false;
+
+   type = TREE_TYPE (t);
+
+   STRIP_SIGN_NOPS (t);
+   switch (TREE_CODE (t))
+     {
+     case INTEGER_CST:
+       if (TREE_UNSIGNED (type))
+ 	return false;
+
+       /* Check that -CST will not overflow type.  */
+       prec = TYPE_PRECISION (type);
+       if (prec > HOST_BITS_PER_WIDE_INT)
+ 	{
+ 	  if (TREE_INT_CST_LOW (t) != 0)
+ 	    return true;
+ 	  prec -= HOST_BITS_PER_WIDE_INT;
+ 	  val = TREE_INT_CST_HIGH (t);
+ 	}
+       else
+ 	val = TREE_INT_CST_LOW (t);
+       if (prec < HOST_BITS_PER_WIDE_INT)
+ 	val &= ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
+       return val != ((unsigned HOST_WIDE_INT) 1 << (prec - 1));
+
+     case REAL_CST:
+     case NEGATE_EXPR:
+     case MINUS_EXPR:
+       return true;
+
+     default:
+       break;
+     }
+   return false;
+ }
+
  /* Given T, an expression, return the negation of T.  Allow for T to be
     null, in which case return null.  */

*************** fold (expr)
*** 5479,5491 ****
        /* A - (-B) -> A + B */
        if (TREE_CODE (arg1) == NEGATE_EXPR)
  	return fold (build (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
!       /* (-A) - CST -> (-CST) - A   for floating point (what about ints ?)  */
!       if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == REAL_CST)
! 	return
! 	  fold (build (MINUS_EXPR, type,
! 		       build_real (TREE_TYPE (arg1),
! 				   REAL_VALUE_NEGATE (TREE_REAL_CST (arg1))),
! 		       TREE_OPERAND (arg0, 0)));

        if (! FLOAT_TYPE_P (type))
  	{
--- 5529,5542 ----
        /* A - (-B) -> A + B */
        if (TREE_CODE (arg1) == NEGATE_EXPR)
  	return fold (build (PLUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0)));
!       /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
!       if (TREE_CODE (arg0) == NEGATE_EXPR
! 	  && FLOAT_TYPE_P (type)
! 	  && negate_expr_p (arg1)
! 	  && (! TREE_SIDE_EFFECTS (arg0) || TREE_CONSTANT (arg1))
! 	  && (! TREE_SIDE_EFFECTS (arg1) || TREE_CONSTANT (arg0)))
! 	return fold (build (MINUS_EXPR, type, negate_expr (arg1),
! 			    TREE_OPERAND (arg0, 0)));

        if (! FLOAT_TYPE_P (type))
  	{

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


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