[Committed] Correct conditions to perform -(X-Y) -> Y-X

Roger Sayle roger@eyesopen.com
Mon Nov 13 03:30:00 GMT 2006


As recently pointed out by Revital Eres on the gcc list, we're currently
inconsistent between fold-const and simplify-rtx about when we can
simplify -(X-Y) to Y-X.  The issue is that fold still uses the historical
flag_unsafe_math_optimizations, where as simplify-rtx uses the newer and
more precise HONOR_SIGNED_ZEROS and HONOR_SIGN_DEPENDENT_ROUNDING macros.
Under the surface, HONOR_SIGNED_ZEROS actually just tests for
flag_unsafe_math_optimizations, and the command line "-ffast-math"
simultaneouly turns off both conditions.

The reason why HONOR_SIGNED_ZERO is significant for this transformation
is because "-0.0 - -0.0" is "+0.0" which when negated is "-0.0", but
clearly this isn't the same as "-0.0 - -0.0".  IEEE, got to love them.

The reason why HONOR_SIGN_DEPENDENT_ROUNDING is significant is that
although both -(X-Y) and Y-X only each have one rounding operation,
the sign of the value being rounded is different.  Hence in non-default
rounding modes, such as round to +Inf or round to -Inf, the results
may differ in the least significant bit.

The discrepancy between the tree-ssa and RTL optimizers is extremely
rare, both don't perform the operation by default, and do with
-ffast-math.  The only discrepancy is with the (conflicting?) options
-funsafe-math-optimizations and -frounding-math.


The following patch has been tested on x86_64-unknown-linux-gnu, with
a full "make bootstrap", all default languages including Ada, and
regression tested with a top-level "make -k check" with no new failures.


Committed to mainline as revision 118744.



2006-11-12  Roger Sayle  <roger@eyesopen.com>

	* fold-const.c (negate_expr_p) <PLUS_EXPR, MINUS_EXPR>: Correct/refine
	condition for transformations.  Use !HONOR_SIGN_DEPENDENT_ROUNDING
	&& !HONOR_SIGNED_ZEROS instead of flag_unsafe_math_optimizations.
	(fold_negate_expr) <PLUS_EXPR, MINUS_EXPR>: Likewise.


Index: fold-const.c
===================================================================
*** fold-const.c	(revision 118694)
--- fold-const.c	(working copy)
*************** negate_expr_p (tree t)
*** 971,977 ****
  	     && 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))
--- 971,978 ----
  	     && negate_expr_p (TREE_IMAGPART (t));

      case PLUS_EXPR:
!       if (HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
! 	  || HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
  	return false;
        /* -(A + B) -> (-B) - A.  */
        if (negate_expr_p (TREE_OPERAND (t, 1))
*************** negate_expr_p (tree t)
*** 983,989 ****

      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)
  	     && reorder_operands_p (TREE_OPERAND (t, 0),
  				    TREE_OPERAND (t, 1));

--- 984,991 ----

      case MINUS_EXPR:
        /* We can't turn -(A-B) into B-A when we honor signed zeros.  */
!       return !HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
! 	     && !HONOR_SIGNED_ZEROS (TYPE_MODE (type))
  	     && reorder_operands_p (TREE_OPERAND (t, 0),
  				    TREE_OPERAND (t, 1));

*************** fold_negate_expr (tree t)
*** 1095,1101 ****
        return 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))
--- 1097,1104 ----
        return TREE_OPERAND (t, 0);

      case PLUS_EXPR:
!       if (!HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
! 	  && !HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
  	{
  	  /* -(A + B) -> (-B) - A.  */
  	  if (negate_expr_p (TREE_OPERAND (t, 1))
*************** fold_negate_expr (tree t)
*** 1119,1125 ****

      case MINUS_EXPR:
        /* - (A - B) -> B - A  */
!       if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
  	  && reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)))
  	return fold_build2 (MINUS_EXPR, type,
  			    TREE_OPERAND (t, 1), TREE_OPERAND (t, 0));
--- 1122,1129 ----

      case MINUS_EXPR:
        /* - (A - B) -> B - A  */
!       if (!HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
! 	  && !HONOR_SIGNED_ZEROS (TYPE_MODE (type))
  	  && reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)))
  	return fold_build2 (MINUS_EXPR, type,
  			    TREE_OPERAND (t, 1), TREE_OPERAND (t, 0));


Roger
--



More information about the Gcc-patches mailing list