This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][2/n] Fix PR14541
- From: Richard Biener <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 3 Dec 2014 14:41:22 +0100 (CET)
- Subject: [PATCH][2/n] Fix PR14541
- Authentication-results: sourceware.org; auth=none
This moves sqrt simplification from GENERIC to patterns.
The testcase adjustment shows one of the side-effects I mentioned
in 1/n - simplification is delayed to SSA and for the testcase
we have to trick CCP not folding everything to a constant before
the expression simplification is done in forwprops folding of all
statements.
Boostrap and regtest ongoing on x86_64-unknown-linux-gnu.
Richard.
2014-12-03 Richard Biener <rguenther@suse.de>
PR middle-end/14541
* builtins.c (fold_builtin_sqrt): Implement simplifications ...
* match.pd: ... here as patterns.
* gcc.dg/builtins-47.c: Adjust.
Index: gcc/match.pd
===================================================================
*** gcc/match.pd.orig 2014-12-03 12:50:07.645992434 +0100
--- gcc/match.pd 2014-12-03 13:01:55.332967931 +0100
*************** along with GCC; see the file COPYING3.
*** 1005,1007 ****
--- 1005,1034 ----
(logs (pows @0 @1))
(mult @1 (logs @0)))))
+
+ /* fold_builtin_sqrt */
+ (if (flag_unsafe_math_optimizations)
+ /* Optimize sqrt(expN(x)) = expN(x*0.5). */
+ (for expfn (EXP10 POW10 EXP EXP2)
+ sqrtfn (SQRT)
+ (simplify
+ (sqrtfn (expfn @0))
+ (expfn (mult @0 { build_real (type, dconsthalf); }))))
+ /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
+ (for rootfn (SQRT CBRT)
+ sqrtfn (SQRT)
+ powfn (POW)
+ (simplify
+ (sqrtfn (rootfn @0))
+ (with
+ { REAL_VALUE_TYPE dconstroot;
+ if (BUILTIN_SQRT_P (rootfn)) dconstroot = dconsthalf;
+ else dconstroot = dconst_third ();
+ /* Adjust for the outer root. */
+ SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
+ dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); }
+ (powfn @0 { build_real (type, dconstroot); }))))
+ /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
+ (simplify
+ (SQRT (POW @0 @1))
+ (POW (abs @0) (mult @1 { build_real (TREE_TYPE (@1), dconsthalf); }))))
Index: gcc/builtins.c
===================================================================
*** gcc/builtins.c.orig 2014-12-03 12:50:06.292992480 +0100
--- gcc/builtins.c 2014-12-03 13:01:55.335967931 +0100
*************** static bool integer_valued_real_p (tree)
*** 164,170 ****
static tree fold_trunc_transparent_mathfn (location_t, tree, tree);
static rtx expand_builtin_fabs (tree, rtx, rtx);
static rtx expand_builtin_signbit (tree, rtx);
- static tree fold_builtin_sqrt (location_t, tree, tree);
static tree fold_builtin_cbrt (location_t, tree, tree);
static tree fold_builtin_pow (location_t, tree, tree, tree, tree);
static tree fold_builtin_powi (location_t, tree, tree, tree, tree);
--- 164,169 ----
*************** fold_builtin_cproj (location_t loc, tree
*** 7725,7804 ****
return NULL_TREE;
}
- /* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
- Return NULL_TREE if no simplification can be made. */
-
- static tree
- fold_builtin_sqrt (location_t loc, tree arg, tree type)
- {
-
- enum built_in_function fcode;
- tree res;
-
- if (!validate_arg (arg, REAL_TYPE))
- return NULL_TREE;
-
- /* Calculate the result when the argument is a constant. */
- if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
- return res;
-
- /* Optimize sqrt(expN(x)) = expN(x*0.5). */
- fcode = builtin_mathfn_code (arg);
- if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
- {
- tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
- arg = fold_build2_loc (loc, MULT_EXPR, type,
- CALL_EXPR_ARG (arg, 0),
- build_real (type, dconsthalf));
- return build_call_expr_loc (loc, expfn, 1, arg);
- }
-
- /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
- if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
- {
- tree powfn = mathfn_built_in (type, BUILT_IN_POW);
-
- if (powfn)
- {
- tree arg0 = CALL_EXPR_ARG (arg, 0);
- tree tree_root;
- /* The inner root was either sqrt or cbrt. */
- /* This was a conditional expression but it triggered a bug
- in Sun C 5.5. */
- REAL_VALUE_TYPE dconstroot;
- if (BUILTIN_SQRT_P (fcode))
- dconstroot = dconsthalf;
- else
- dconstroot = dconst_third ();
-
- /* Adjust for the outer root. */
- SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
- dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
- tree_root = build_real (type, dconstroot);
- return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
- }
- }
-
- /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
- if (flag_unsafe_math_optimizations
- && (fcode == BUILT_IN_POW
- || fcode == BUILT_IN_POWF
- || fcode == BUILT_IN_POWL))
- {
- tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
- tree arg0 = CALL_EXPR_ARG (arg, 0);
- tree arg1 = CALL_EXPR_ARG (arg, 1);
- tree narg1;
- if (!tree_expr_nonnegative_p (arg0))
- arg0 = build1 (ABS_EXPR, type, arg0);
- narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
- build_real (type, dconsthalf));
- return build_call_expr_loc (loc, powfn, 2, arg0, narg1);
- }
-
- return NULL_TREE;
- }
-
/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG.
Return NULL_TREE if no simplification can be made. */
--- 7724,7729 ----
*************** fold_builtin_1 (location_t loc, tree fnd
*** 10035,10041 ****
return fold_builtin_carg (loc, arg0, type);
CASE_FLT_FN (BUILT_IN_SQRT):
! return fold_builtin_sqrt (loc, arg0, type);
CASE_FLT_FN (BUILT_IN_CBRT):
return fold_builtin_cbrt (loc, arg0, type);
--- 9960,9968 ----
return fold_builtin_carg (loc, arg0, type);
CASE_FLT_FN (BUILT_IN_SQRT):
! if (validate_arg (arg0, REAL_TYPE))
! return do_mpfr_arg1 (arg0, type, mpfr_sqrt, &dconst0, NULL, true);
! break;
CASE_FLT_FN (BUILT_IN_CBRT):
return fold_builtin_cbrt (loc, arg0, type);
Index: gcc/testsuite/gcc.dg/builtins-47.c
===================================================================
*** gcc/testsuite/gcc.dg/builtins-47.c.orig 2011-10-10 16:22:07.000000000 +0200
--- gcc/testsuite/gcc.dg/builtins-47.c 2014-12-03 13:26:32.379916791 +0100
***************
*** 1,13 ****
/* { dg-do run } */
! /* { dg-options "-O -ffast-math -fdump-tree-gimple" } */
extern double sqrt (double);
extern double pow (double, double);
extern void abort (void);
int main ()
{
- double x = -1.0;
if (sqrt (pow (x, 2)) != 1.0)
abort();
if (sqrt (x*x) != 1.0)
--- 1,14 ----
/* { dg-do run } */
! /* { dg-options "-O -ffast-math -fdump-tree-cddce1" } */
extern double sqrt (double);
extern double pow (double, double);
extern void abort (void);
+ double x = -1.0;
+
int main ()
{
if (sqrt (pow (x, 2)) != 1.0)
abort();
if (sqrt (x*x) != 1.0)
*************** int main ()
*** 15,20 ****
return 0;
}
! /* { dg-final { scan-tree-dump-times "sqrt" 0 "gimple" } } */
! /* { dg-final { scan-tree-dump-times "pow" 0 "gimple" } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */
--- 16,21 ----
return 0;
}
! /* { dg-final { scan-tree-dump-times "sqrt" 0 "cddce1" } } */
! /* { dg-final { scan-tree-dump-times "pow" 0 "cddce1" } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */