This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR30028, fold sin, cos to sincos on the tree-level
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 7 Dec 2006 19:27:40 +0100 (CET)
- Subject: [PATCH] Fix PR30028, fold sin, cos to sincos on the tree-level
This makes us recognize uses of sin and cos on the same argument and
insert a call to sincos instead. This should improve SPEC2000 lucas
and Polyhedron fatigue (as soon as the frontend get's access to the
required builtins).
Bootstrapped and tested on x86_64-unknown-linux-gnu.
Ok for mainline?
Thanks,
Richard.
:ADDPATCH middle-end:
2006-12-07 Richard Guenther <rguenther@suse.de>
PR tree-optimization/30028
* tree-ssa-math-opts.c (execute_cse_reciprocals_1): Gate
with !optimize_size && flag_unsafe_math_optimizations.
(gate_cse_reciprocals): Only gate with optimize.
(execute_cse_sincos_1): New routine to CSE sin and cos to sincos.
(execute_cse_reciprocals): Call it.
* gcc.dg/builtins-61.c: New testcase.
Index: testsuite/gcc.dg/builtins-61.c
===================================================================
*** testsuite/gcc.dg/builtins-61.c (revision 0)
--- testsuite/gcc.dg/builtins-61.c (revision 0)
***************
*** 0 ****
--- 1,40 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -ffinite-math-only -fdump-tree-optimized" } */
+
+ double test1 (double x)
+ {
+ double s, c;
+ s = __builtin_sin (x);
+ c = __builtin_cos (x);
+ return s + c;
+ }
+
+ double test2 (double x)
+ {
+ double s, c;
+ x = x * 2;
+ s = __builtin_sin (x);
+ c = __builtin_cos (x);
+ return s + c;
+ }
+
+ double test3 (double x, int b)
+ {
+ double s, c;
+ if (b)
+ x = x * 2;
+ s = __builtin_sin (x);
+ c = __builtin_cos (x);
+ return s + c;
+ }
+
+ double test4 (double x)
+ {
+ double s;
+ x = x * 2;
+ s = __builtin_sin (x);
+ return s;
+ }
+
+ /* { dg-final { scan-tree-dump-times "cexpi" 3 "optimized" } } */
+ /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: tree-ssa-math-opts.c
===================================================================
*** tree-ssa-math-opts.c (revision 119622)
--- tree-ssa-math-opts.c (working copy)
*************** execute_cse_reciprocals_1 (block_stmt_it
*** 401,406 ****
--- 401,409 ----
struct occurrence *occ;
int count = 0, threshold;
+ if (optimize_size || !flag_unsafe_math_optimizations)
+ return;
+
gcc_assert (FLOAT_TYPE_P (TREE_TYPE (def)) && is_gimple_reg (def));
FOR_EACH_IMM_USE_FAST (use_p, use_iter, def)
*************** execute_cse_reciprocals_1 (block_stmt_it
*** 440,450 ****
occ_head = NULL;
}
static bool
gate_cse_reciprocals (void)
{
! return optimize && !optimize_size && flag_unsafe_math_optimizations;
}
--- 443,559 ----
occ_head = NULL;
}
+ /* Look for sin, cos and cexpi calls with the same argument NAME and
+ create a single call to cexpi CSEing the result in this case.
+ Note this function completely lacks cost considerations and
+ so even transforms if (f) sin(x) else cos(x). */
+
+ static void
+ execute_cse_sincos_1 (tree name)
+ {
+ block_stmt_iterator bsi;
+ imm_use_iterator use_iter;
+ tree use_stmt, fndecl, res, call, stmt, type, arg_def_stmt;
+ bool seen_cos = false, seen_sin = false, seen_cexpi = false;
+
+ /* sin, cos and cexpi may trap with non-finite math (+-Inf arguments). */
+ if (!flag_finite_math_only)
+ return;
+
+ type = TREE_TYPE (name);
+ FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, name)
+ {
+ if (TREE_CODE (use_stmt) != GIMPLE_MODIFY_STMT
+ || TREE_CODE (GIMPLE_STMT_OPERAND (use_stmt, 1)) != CALL_EXPR)
+ continue;
+
+ fndecl = get_callee_fndecl (GIMPLE_STMT_OPERAND (use_stmt, 1));
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ CASE_FLT_FN (BUILT_IN_COS):
+ seen_cos = true;
+ break;
+
+ CASE_FLT_FN (BUILT_IN_SIN):
+ seen_sin = true;
+ break;
+
+ CASE_FLT_FN (BUILT_IN_CEXPI):
+ seen_cexpi = true;
+ break;
+
+ default:;
+ }
+ }
+
+ if (seen_cos + seen_sin + seen_cexpi <= 1)
+ return;
+
+ /* Simply insert cexpi at the argument definition site. */
+ fndecl = mathfn_built_in (type, BUILT_IN_CEXPI);
+ if (!fndecl)
+ return;
+ res = make_rename_temp (TREE_TYPE (TREE_TYPE (fndecl)), "sincostmp");
+ call = build_function_call_expr (fndecl, build_tree_list (NULL_TREE, name));
+ stmt = build2 (GIMPLE_MODIFY_STMT, NULL_TREE, res, call);
+
+ arg_def_stmt = SSA_NAME_DEF_STMT (name);
+ if (TREE_CODE (arg_def_stmt) == GIMPLE_MODIFY_STMT)
+ {
+ bsi = bsi_for_stmt (arg_def_stmt);
+ bsi_insert_after (&bsi, stmt, BSI_SAME_STMT);
+ }
+ else if (TREE_CODE (arg_def_stmt) == PHI_NODE)
+ {
+ bsi = bsi_after_labels (bb_for_stmt (arg_def_stmt));
+ bsi_insert_before (&bsi, stmt, BSI_SAME_STMT);
+ }
+ else if (TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
+ {
+ bsi = bsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
+ bsi_insert_before (&bsi, stmt, BSI_SAME_STMT);
+ }
+ update_stmt (stmt);
+
+ /* And adjust the old call sites. */
+ FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, name)
+ {
+ if (TREE_CODE (use_stmt) != GIMPLE_MODIFY_STMT
+ || TREE_CODE (GIMPLE_STMT_OPERAND (use_stmt, 1)) != CALL_EXPR)
+ continue;
+
+ fndecl = get_callee_fndecl (GIMPLE_STMT_OPERAND (use_stmt, 1));
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ CASE_FLT_FN (BUILT_IN_COS):
+ GIMPLE_STMT_OPERAND (use_stmt, 1) = fold_build1 (REALPART_EXPR,
+ type, res);
+ update_stmt (use_stmt);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_SIN):
+ GIMPLE_STMT_OPERAND (use_stmt, 1) = fold_build1 (IMAGPART_EXPR,
+ type, res);
+ update_stmt (use_stmt);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_CEXPI):
+ if (use_stmt != stmt)
+ {
+ GIMPLE_STMT_OPERAND (use_stmt, 1) = res;
+ update_stmt (use_stmt);
+ }
+ break;
+
+ default:;
+ }
+ }
+ }
static bool
gate_cse_reciprocals (void)
{
! return optimize;
}
*************** execute_cse_reciprocals (void)
*** 490,500 ****
--- 599,632 ----
for (bsi = bsi_after_labels (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
tree stmt = bsi_stmt (bsi);
+ tree fndecl;
+
if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
&& (def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF)) != NULL
&& FLOAT_TYPE_P (TREE_TYPE (def))
&& TREE_CODE (def) == SSA_NAME)
execute_cse_reciprocals_1 (&bsi, def);
+
+ if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+ && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == CALL_EXPR
+ && (fndecl = get_callee_fndecl (GIMPLE_STMT_OPERAND (stmt, 1))))
+ {
+ tree arg;
+
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ CASE_FLT_FN (BUILT_IN_COS):
+ CASE_FLT_FN (BUILT_IN_SIN):
+ CASE_FLT_FN (BUILT_IN_CEXPI):
+ arg = GIMPLE_STMT_OPERAND (stmt, 1);
+ arg = TREE_VALUE (TREE_OPERAND (arg, 1));
+ if (TREE_CODE (arg) == SSA_NAME)
+ execute_cse_sincos_1 (arg);
+ break;
+
+ default:;
+ }
+ }
}
}