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] Negation related constant folding improvements (take 2)


The following revision of my "negation related constant folding
improvements" patch should address all of the issues previously
raised.

Firstly, we now check HONOR_SIGN_DEPENDENT_ROUNDING before performing
transformations that could result in multiplication or division having
a different sign.  Additionally, I've still split the REAL_CST case
out from the INTEGER_CST case in negate_expr, but I've exposed the
call to GCC's floating-point emulator, and kept the original test for
TREE_OVERFLOW, adding a comment about why this should be needed for
c4x.

Hopefully, this simplification and documentation of the code should
ease the task of improving support for non sign-magnitude floating
point formats in the future.


To answer Geoff Keating's question, yes we could probably try to
canonicalize -X*Y into X*-Y.  However, this wouldn't simplify the
patch below, as we need to test both symmetric cases as we already
canonicalize constants to the right with higher priority.


The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all languages except treelang, and regression tested
with a top-level "make -k check" with no new failures.

Ok for mainline?


2003-08-13  Roger Sayle  <roger@eyesopen.com>

	* fold-const.c (negate_expr_p): MULT_EXPRs and RDIV_EXPRs are easy
	to negate if either operand is easy to negate, if we don't care
	about sign-dependent rounding.
	(negate_expr): Make the logic to negate a REAL_CST explicit.
	Attempt to negate a MULT_EXPR or RDIV_EXPR by negating an operand
	that's easy to negatem if we don't honor sign-dependent rounding.
	(fold <MULT_EXPR>): Optimize -A * B as A * -B if B is easy to
	negate, and the symmetric A * -B as -A * B is A is easy to negate.
	(fold <RDIV_EXPR>): Likewise, optimize -A/B and C/-D as A/-B and
	-C/D if B and C are cheap to negate.  Add an explicit rule to
	optimize X/-1.0 as -X when we don't care about signaling NaNs.



Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.290
diff -c -3 -p -r1.290 fold-const.c
*** fold-const.c	12 Aug 2003 01:43:31 -0000	1.290
--- fold-const.c	13 Aug 2003 12:53:10 -0000
*************** negate_expr_p (tree t)
*** 847,852 ****
--- 847,864 ----
        /* We can't turn -(A-B) into B-A when we honor signed zeros.  */
        return ! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations;

+     case MULT_EXPR:
+       if (TREE_UNSIGNED (TREE_TYPE (t)))
+         break;
+
+       /* Fall through.  */
+
+     case RDIV_EXPR:
+       if (! HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (t))))
+ 	return negate_expr_p (TREE_OPERAND (t, 1))
+ 	       || negate_expr_p (TREE_OPERAND (t, 0));
+       break;
+
      default:
        break;
      }
*************** negate_expr (tree t)
*** 871,883 ****
    switch (TREE_CODE (t))
      {
      case INTEGER_CST:
-     case REAL_CST:
        if (! TREE_UNSIGNED (type)
  	  && 0 != (tem = fold (build1 (NEGATE_EXPR, type, t)))
  	  && ! TREE_OVERFLOW (tem))
  	return tem;
        break;

      case NEGATE_EXPR:
        return convert (type, TREE_OPERAND (t, 0));

--- 883,901 ----
    switch (TREE_CODE (t))
      {
      case INTEGER_CST:
        if (! TREE_UNSIGNED (type)
  	  && 0 != (tem = fold (build1 (NEGATE_EXPR, type, t)))
  	  && ! TREE_OVERFLOW (tem))
  	return tem;
        break;

+     case REAL_CST:
+       tem = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (t)));
+       /* Two's complement FP formats, such as c4x, may overflow.  */
+       if (! TREE_OVERFLOW (tem))
+ 	return convert (type, tem);
+       break;
+
      case NEGATE_EXPR:
        return convert (type, TREE_OPERAND (t, 0));

*************** negate_expr (tree t)
*** 890,895 ****
--- 908,937 ----
  				     TREE_OPERAND (t, 0))));
        break;

+     case MULT_EXPR:
+       if (TREE_UNSIGNED (TREE_TYPE (t)))
+         break;
+
+       /* Fall through.  */
+
+     case RDIV_EXPR:
+       if (! HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (t))))
+ 	{
+ 	  tem = TREE_OPERAND (t, 1);
+ 	  if (negate_expr_p (tem))
+ 	    return convert (type,
+ 			    fold (build (TREE_CODE (t), TREE_TYPE (t),
+ 					 TREE_OPERAND (t, 0),
+ 					 negate_expr (tem))));
+ 	  tem = TREE_OPERAND (t, 0);
+ 	  if (negate_expr_p (tem))
+ 	    return convert (type,
+ 			    fold (build (TREE_CODE (t), TREE_TYPE (t),
+ 					 negate_expr (tem),
+ 					 TREE_OPERAND (t, 1))));
+ 	}
+       break;
+
      default:
        break;
      }
*************** fold (tree expr)
*** 5965,5972 ****

      case MULT_EXPR:
        /* (-A) * (-B) -> A * B  */
!       if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR)
! 	return fold (build (MULT_EXPR, type, TREE_OPERAND (arg0, 0),
  			    TREE_OPERAND (arg1, 0)));

        if (! FLOAT_TYPE_P (type))
--- 6007,6019 ----

      case MULT_EXPR:
        /* (-A) * (-B) -> A * B  */
!       if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
! 	return fold (build (MULT_EXPR, type,
! 			    TREE_OPERAND (arg0, 0),
! 			    negate_expr (arg1)));
!       if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
! 	return fold (build (MULT_EXPR, type,
! 			    negate_expr (arg0),
  			    TREE_OPERAND (arg1, 0)));

        if (! FLOAT_TYPE_P (type))
*************** fold (tree expr)
*** 6315,6328 ****
  	return t;

        /* (-A) / (-B) -> A / B  */
!       if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR)
! 	return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
  			    TREE_OPERAND (arg1, 0)));

        /* In IEEE floating point, x/1 is not equivalent to x for snans.  */
        if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
  	  && real_onep (arg1))
  	return non_lvalue (convert (type, arg0));

        /* If ARG1 is a constant, we can convert this to a multiply by the
  	 reciprocal.  This does not have the same rounding properties,
--- 6362,6385 ----
  	return t;

        /* (-A) / (-B) -> A / B  */
!       if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
! 	return fold (build (RDIV_EXPR, type,
! 			    TREE_OPERAND (arg0, 0),
! 			    negate_expr (arg1)));
!       if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
! 	return fold (build (RDIV_EXPR, type,
! 			    negate_expr (arg0),
  			    TREE_OPERAND (arg1, 0)));

        /* In IEEE floating point, x/1 is not equivalent to x for snans.  */
        if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
  	  && real_onep (arg1))
  	return non_lvalue (convert (type, arg0));
+
+       /* In IEEE floating point, x/-1 is not equivalent to -x for snans.  */
+       if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+ 	  && real_minus_onep (arg1))
+ 	return non_lvalue (convert (type, negate_expr (arg0)));

        /* If ARG1 is a constant, we can convert this to a multiply by the
  	 reciprocal.  This does not have the same rounding properties,


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]