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 folding MINUS_EXPR improvements


The following patch implements several small improvements to GCC's
constant folding of subtraction.

The first is that we now constant fold -(A+B) into either (-A)-B or
(-B)-A, if either A or B is easily negated respectively, and in the
latter that we're allowed to reorder the evaluations of A and B.

Consider, the function

int foo(int a, int b, int c)
{
  return - (a + (b - c));
}

Without this patch, GCC currently implements this function using an
addition, a subtraction and a negation.  Both Microsoft Visual C/C++
and GCC with this patch implement it using only two subtractions, as
"(c - b) - a".

Other improvements include moving the optimization of "(A*C) - (B*C) ->
(A-B)*C" out of the integer-only optimizations, and also enabling it for
floating point calculations, with flag_unsafe_math_optimizations.  I also
took the opportunity of adding the related "A*C1 - A*C2 -> A*(C1-C2)".

Finally, I've added "A - B -> A + (-B)" for floating point types, or
when we know integer arithmetic overflow doesn't trap and wraps around.


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?



2004-02-01  Roger Sayle  <roger@eyesopen.com>

	* fold-const.c (negate_expr_p, negate_expr): Optimize -(A+B) into
	either (-A)-B or (-B)-A, if A or B is easily negated respectively.
	(fold) <MINUS_EXPR>: Optimize (A*C) - (B*C) -> (A-B)*C for both
	integer types and floating point with unsafe_math_optimizations.
	Add similar optimization for (A*C1) - (A*C2) -> A*(C1-C2).
	Optimize A - B as A + (-B), if B is easily negated.


Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.325
diff -c -3 -p -r1.325 fold-const.c
*** fold-const.c	23 Jan 2004 16:52:07 -0000	1.325
--- fold-const.c	1 Feb 2004 21:09:40 -0000
*************** negate_expr_p (tree t)
*** 879,884 ****
--- 879,895 ----
        return negate_expr_p (TREE_REALPART (t))
  	     && negate_expr_p (TREE_IMAGPART (t));

+     case PLUS_EXPR:
+       if (FLOAT_TYPE_P (type) && !flag_unsafe_math_optimizations)
+ 	return false;
+       /* -(A + B) -> (-B) - A.  */
+       if (negate_expr_p (TREE_OPERAND (t, 1))
+ 	  && reorder_operands_p (TREE_OPERAND (t, 0),
+ 				 TREE_OPERAND (t, 1)))
+ 	return true;
+       /* -(A + B) -> (-A) - B.  */
+       return negate_expr_p (TREE_OPERAND (t, 0));
+
      case MINUS_EXPR:
        /* We can't turn -(A-B) into B-A when we honor signed zeros.  */
        return (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
*************** negate_expr (tree t)
*** 980,985 ****
--- 991,1016 ----
      case NEGATE_EXPR:
        return convert (type, TREE_OPERAND (t, 0));

+     case PLUS_EXPR:
+       if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+ 	{
+ 	  /* -(A + B) -> (-B) - A.  */
+ 	  if (negate_expr_p (TREE_OPERAND (t, 1))
+ 	      && reorder_operands_p (TREE_OPERAND (t, 0),
+ 				     TREE_OPERAND (t, 1)))
+ 	    return convert (type,
+ 			    fold (build (MINUS_EXPR, TREE_TYPE (t),
+ 					 negate_expr (TREE_OPERAND (t, 1)),
+ 					 TREE_OPERAND (t, 0))));
+ 	  /* -(A + B) -> (-A) - B.  */
+ 	  if (negate_expr_p (TREE_OPERAND (t, 0)))
+ 	    return convert (type,
+ 			    fold (build (MINUS_EXPR, TREE_TYPE (t),
+ 					 negate_expr (TREE_OPERAND (t, 0)),
+ 					 TREE_OPERAND (t, 1))));
+ 	}
+       break;
+
      case MINUS_EXPR:
        /* - (A - B) -> B - A  */
        if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
*************** fold (tree expr)
*** 6097,6115 ****
  	  if (integer_zerop (arg1))
  	    return non_lvalue (convert (type, arg0));

- 	  /* (A * C) - (B * C) -> (A-B) * C.  Since we are most concerned
- 	     about the case where C is a constant, just try one of the
- 	     four possibilities.  */
-
- 	  if (TREE_CODE (arg0) == MULT_EXPR && TREE_CODE (arg1) == MULT_EXPR
- 	      && operand_equal_p (TREE_OPERAND (arg0, 1),
- 				  TREE_OPERAND (arg1, 1), 0))
- 	    return fold (build (MULT_EXPR, type,
- 				fold (build (MINUS_EXPR, type,
- 					     TREE_OPERAND (arg0, 0),
- 					     TREE_OPERAND (arg1, 0))),
- 				TREE_OPERAND (arg0, 1)));
-
  	  /* Fold A - (A & B) into ~B & A.  */
  	  if (!TREE_SIDE_EFFECTS (arg0)
  	      && TREE_CODE (arg1) == BIT_AND_EXPR)
--- 6128,6133 ----
*************** fold (tree expr)
*** 6165,6170 ****
--- 6183,6216 ----
        if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
  	  && operand_equal_p (arg0, arg1, 0))
  	return convert (type, integer_zero_node);
+
+       /* 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 (build (PLUS_EXPR, type, arg0, negate_expr (arg1)));
+
+       if (TREE_CODE (arg0) == MULT_EXPR
+ 	  && TREE_CODE (arg1) == MULT_EXPR
+ 	  && (INTEGRAL_TYPE_P (type) || flag_unsafe_math_optimizations))
+ 	{
+           /* (A * C) - (B * C) -> (A-B) * C.  */
+ 	  if (operand_equal_p (TREE_OPERAND (arg0, 1),
+ 			       TREE_OPERAND (arg1, 1), 0))
+ 	    return fold (build (MULT_EXPR, type,
+ 				fold (build (MINUS_EXPR, type,
+ 					     TREE_OPERAND (arg0, 0),
+ 					     TREE_OPERAND (arg1, 0))),
+ 				TREE_OPERAND (arg0, 1)));
+           /* (A * C1) - (A * C2) -> A * (C1-C2).  */
+ 	  if (operand_equal_p (TREE_OPERAND (arg0, 0),
+ 			       TREE_OPERAND (arg1, 0), 0))
+ 	    return fold (build (MULT_EXPR, type,
+ 				TREE_OPERAND (arg0, 0),
+ 				fold (build (MINUS_EXPR, type,
+ 					     TREE_OPERAND (arg0, 1),
+ 					     TREE_OPERAND (arg1, 1)))));
+ 	}

        goto associate;


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]