This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Committed] PR24964: Optimize fabs(x)*fabs(x) as x*x
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 29 May 2006 10:04:52 -0600 (MDT)
- Subject: [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
--