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] 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:;
+ 		}
+ 	    }
  	}
      }
  


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