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]

[Committed] PR24964: Optimize fabs(x)*fabs(x) as x*x


The following patch resolves the missed-optimization aspect of
PR 24964.  Although this is marked as a tree-optimization PR that
could be cured by the addition of a tree combiner, the transformation
in question is also missing from the RTL optimizers and therefore
missed by combine.  These transformations, fabs(x)*fabs(x) -> x*x
and -x*-x -> x*x, are already implemented in fold-const.c.

The following patch has been bootstraped on x86_64-unknown-linux-gnu,
all default languages, and regression tested with a top-level "make
-k check" with no new failures.  Historically, RTL simplifications
aren't normally tested in the testsuite, but I broke tradition and
added a gcc.target test for x87, even though this optimization also
applies equally well to PPC (the source of the PR) and even SSE math
on x86_64.  I also took the liberty of one or two minor clean-ups
in this function, including adding a descriptive comment above it.

Committed to mainline as revision 114206.



2006-05-29  Roger Sayle  <roger@eyesopen.com>

	PR tree-optimization/24964
	* simplify-rtx.c (simplify_binary_operation_1): Add function comment.
	<MULT>: Minor clean-up.  Don't convert x*-1.0 into -x if we honor
	signaling NaNs.  Optimize -x*-x as x*x for all float modes, and
	abs(x)*abs(x) as x*x for scalar floating point modes.

	* gcc.target/i386/387-10.c: New test case.


Index: simplify-rtx.c
===================================================================
*** simplify-rtx.c	(revision 114176)
--- simplify-rtx.c	(working copy)
*************** simplify_binary_operation (enum rtx_code
*** 1472,1477 ****
--- 1472,1482 ----
    return simplify_binary_operation_1 (code, mode, op0, op1, trueop0, trueop1);
  }

+ /* Subroutine of simplify_binary_operation.  Simplify a binary operation
+    CODE with result mode MODE, operating on OP0 and OP1.  If OP0 and/or
+    OP1 are constant pool references, TRUEOP0 and TRUEOP1 represent the
+    actual constants.  */
+
  static rtx
  simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
  			     rtx op0, rtx op1, rtx trueop0, rtx trueop1)
*************** simplify_binary_operation_1 (enum rtx_co
*** 1907,1918 ****
  	return simplify_gen_binary (ASHIFT, mode, op0, GEN_INT (val));

        /* Likewise for multipliers wider than a word.  */
!       else if (GET_CODE (trueop1) == CONST_DOUBLE
! 	       && (GET_MODE (trueop1) == VOIDmode
! 		   || GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_INT)
! 	       && GET_MODE (op0) == mode
! 	       && CONST_DOUBLE_LOW (trueop1) == 0
! 	       && (val = exact_log2 (CONST_DOUBLE_HIGH (trueop1))) >= 0)
  	return simplify_gen_binary (ASHIFT, mode, op0,
  				    GEN_INT (val + HOST_BITS_PER_WIDE_INT));

--- 1912,1923 ----
  	return simplify_gen_binary (ASHIFT, mode, op0, GEN_INT (val));

        /* Likewise for multipliers wider than a word.  */
!       if (GET_CODE (trueop1) == CONST_DOUBLE
! 	  && (GET_MODE (trueop1) == VOIDmode
! 	      || GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_INT)
! 	  && GET_MODE (op0) == mode
! 	  && CONST_DOUBLE_LOW (trueop1) == 0
! 	  && (val = exact_log2 (CONST_DOUBLE_HIGH (trueop1))) >= 0)
  	return simplify_gen_binary (ASHIFT, mode, op0,
  				    GEN_INT (val + HOST_BITS_PER_WIDE_INT));

*************** simplify_binary_operation_1 (enum rtx_co
*** 1927,1936 ****
  	  if (REAL_VALUES_EQUAL (d, dconst2))
  	    return simplify_gen_binary (PLUS, mode, op0, copy_rtx (op0));

! 	  if (REAL_VALUES_EQUAL (d, dconstm1))
  	    return simplify_gen_unary (NEG, mode, op0, mode);
  	}

        /* Reassociate multiplication, but for floating point MULTs
  	 only when the user specifies unsafe math optimizations.  */
        if (! FLOAT_MODE_P (mode)
--- 1932,1958 ----
  	  if (REAL_VALUES_EQUAL (d, dconst2))
  	    return simplify_gen_binary (PLUS, mode, op0, copy_rtx (op0));

! 	  if (!HONOR_SNANS (mode)
! 	      && REAL_VALUES_EQUAL (d, dconstm1))
  	    return simplify_gen_unary (NEG, mode, op0, mode);
  	}

+       /* Optimize -x * -x as x * x.  */
+       if (FLOAT_MODE_P (mode)
+ 	  && GET_CODE (op0) == NEG
+ 	  && GET_CODE (op1) == NEG
+ 	  && rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0))
+ 	  && !side_effects_p (XEXP (op0, 0)))
+ 	return simplify_gen_binary (MULT, mode, XEXP (op0, 0), XEXP (op1, 0));
+
+       /* Likewise, optimize abs(x) * abs(x) as x * x.  */
+       if (SCALAR_FLOAT_MODE_P (mode)
+ 	  && GET_CODE (op0) == ABS
+ 	  && GET_CODE (op1) == ABS
+ 	  && rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0))
+ 	  && !side_effects_p (XEXP (op0, 0)))
+ 	return simplify_gen_binary (MULT, mode, XEXP (op0, 0), XEXP (op1, 0));
+
        /* Reassociate multiplication, but for floating point MULTs
  	 only when the user specifies unsafe math optimizations.  */
        if (! FLOAT_MODE_P (mode)


/* PR tree-optimization/24964 */
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 -mfpmath=387" } */

double fabs(double x);

double test1(double x)
{
  double t = fabs(x);
  return t*t;
}

double test2(double x)
{
  double t = -x;
  return t*t;
}

/* { dg-final { scan-assembler-not "fchs" } } */
/* { dg-final { scan-assembler-not "fabs" } } */


Roger
--


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