+2015-11-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/68501
+ * target.def (builtin_reciprocal): Replace the 3 arguments with
+ a gcall * one, adjust description.
+ * targhooks.h (default_builtin_reciprocal): Replace the 3 arguments
+ with a gcall * one.
+ * targhooks.c (default_builtin_reciprocal): Likewise.
+ * tree-ssa-math-opts.c (pass_cse_reciprocals::execute): Use
+ targetm.builtin_reciprocal even on internal functions, adjust
+ the arguments and allow replacing an internal function with normal
+ built-in.
+ * config/i386/i386.c (ix86_builtin_reciprocal): Replace the 3 arguments
+ with a gcall * one. Handle internal fns too.
+ * config/rs6000/rs6000.c (rs6000_builtin_reciprocal): Likewise.
+ * config/aarch64/aarch64.c (aarch64_builtin_reciprocal): Likewise.
+ * doc/tm.texi (builtin_reciprocal): Document.
+
2015-11-30 Richard Biener <rguenther@suse.de>
PR tree-optimization/68592
reciprocal square root builtins. */
static tree
-aarch64_builtin_reciprocal (unsigned int fn,
- bool md_fn,
- bool)
+aarch64_builtin_reciprocal (gcall *call)
{
if (flag_trapping_math
|| !flag_unsafe_math_optimizations
|| optimize_size
|| ! (aarch64_tune_params.extra_tuning_flags
& AARCH64_EXTRA_TUNE_RECIP_SQRT))
- {
return NULL_TREE;
- }
+ if (gimple_call_internal_p (call)
+ return NULL_TREE;
+
+ tree fndecl = gimple_call_fndecl (call);
+ enum built_in_function fn = DECL_FUNCTION_CODE (fndecl);
+ bool md_fn = DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD;
return aarch64_builtin_rsqrt (fn, md_fn);
}
reciprocal of the function, or NULL_TREE if not available. */
static tree
-ix86_builtin_reciprocal (unsigned int fn, bool md_fn, bool)
+ix86_builtin_reciprocal (gcall *call)
{
if (! (TARGET_SSE_MATH && !optimize_insn_for_size_p ()
&& flag_finite_math_only && !flag_trapping_math
&& flag_unsafe_math_optimizations))
return NULL_TREE;
- if (md_fn)
+ if (gimple_call_internal_p (call))
+ switch (gimple_call_internal_fn (call))
+ {
+ tree type;
+ case IFN_SQRT:
+ type = TREE_TYPE (gimple_call_lhs (call));
+ switch (TYPE_MODE (type))
+ {
+ /* Vectorized version of sqrt to rsqrt conversion. */
+ case V4SFmode:
+ return ix86_get_builtin (IX86_BUILTIN_RSQRTPS_NR);
+
+ case V8SFmode:
+ return ix86_get_builtin (IX86_BUILTIN_RSQRTPS_NR256);
+
+ default:
+ return NULL_TREE;
+ }
+
+ default:
+ return NULL_TREE;
+ }
+
+ tree fndecl = gimple_call_fndecl (call);
+ if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
/* Machine dependent builtins. */
- switch (fn)
+ switch (DECL_FUNCTION_CODE (fndecl))
{
/* Vectorized version of sqrt to rsqrt conversion. */
case IX86_BUILTIN_SQRTPS_NR:
}
else
/* Normal builtins. */
- switch (fn)
+ switch (DECL_FUNCTION_CODE (fndecl))
{
/* Sqrt to rsqrt conversion. */
case BUILT_IN_SQRTF:
reciprocal of the function, or NULL_TREE if not available. */
static tree
-rs6000_builtin_reciprocal (unsigned int fn, bool md_fn,
- bool sqrt ATTRIBUTE_UNUSED)
+rs6000_builtin_reciprocal (gcall *call)
{
if (optimize_insn_for_size_p ())
return NULL_TREE;
- if (md_fn)
- switch (fn)
+ if (gimple_call_internal_p (call))
+ switch (gimple_call_internal_fn (call))
+ {
+ tree type;
+ case IFN_SQRT:
+ type = TREE_TYPE (gimple_call_lhs (call));
+ switch (TYPE_MODE (type))
+ {
+ case V2DFmode:
+ if (!RS6000_RECIP_AUTO_RSQRTE_P (V2DFmode))
+ return NULL_TREE;
+
+ return rs6000_builtin_decls[VSX_BUILTIN_RSQRT_2DF];
+
+ case V4SFmode:
+ if (!RS6000_RECIP_AUTO_RSQRTE_P (V4SFmode))
+ return NULL_TREE;
+
+ return rs6000_builtin_decls[VSX_BUILTIN_RSQRT_4SF];
+
+ default:
+ return NULL_TREE;
+ }
+
+ default:
+ return NULL_TREE;
+ }
+
+ tree fndecl = gimple_call_fndecl (call);
+ if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
+ switch (DECL_FUNCTION_CODE (fndecl))
{
case VSX_BUILTIN_XVSQRTDP:
if (!RS6000_RECIP_AUTO_RSQRTE_P (V2DFmode))
}
else
- switch (fn)
+ switch (DECL_FUNCTION_CODE (fndecl))
{
case BUILT_IN_SQRT:
if (!RS6000_RECIP_AUTO_RSQRTE_P (DFmode))
The default version returns true for all decls.
@end deftypefn
-@deftypefn {Target Hook} tree TARGET_BUILTIN_RECIPROCAL (unsigned @var{fn}, bool @var{md_fn}, bool @var{sqrt})
+@deftypefn {Target Hook} tree TARGET_BUILTIN_RECIPROCAL (gcall *@var{call})
This hook should return the DECL of a function that implements reciprocal of
-the builtin function with builtin function code @var{fn}, or
-@code{NULL_TREE} if such a function is not available. @var{md_fn} is true
-when @var{fn} is a code of a machine-dependent builtin function. When
-@var{sqrt} is true, additional optimizations that apply only to the reciprocal
-of a square root function are performed, and only reciprocals of @code{sqrt}
-function are valid.
+the builtin or internal function call @var{call}, or
+@code{NULL_TREE} if such a function is not available.
@end deftypefn
@deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD (void)
DEFHOOK
(builtin_reciprocal,
"This hook should return the DECL of a function that implements reciprocal of\n\
-the builtin function with builtin function code @var{fn}, or\n\
-@code{NULL_TREE} if such a function is not available. @var{md_fn} is true\n\
-when @var{fn} is a code of a machine-dependent builtin function. When\n\
-@var{sqrt} is true, additional optimizations that apply only to the reciprocal\n\
-of a square root function are performed, and only reciprocals of @code{sqrt}\n\
-function are valid.",
- tree, (unsigned fn, bool md_fn, bool sqrt),
+the builtin or internal function call @var{call}, or\n\
+@code{NULL_TREE} if such a function is not available.",
+ tree, (gcall *call),
default_builtin_reciprocal)
/* For a vendor-specific TYPE, return a pointer to a statically-allocated
/* Reciprocal. */
tree
-default_builtin_reciprocal (unsigned int fn ATTRIBUTE_UNUSED,
- bool md_fn ATTRIBUTE_UNUSED,
- bool sqrt ATTRIBUTE_UNUSED)
+default_builtin_reciprocal (gcall *)
{
return NULL_TREE;
}
extern int default_builtin_vectorization_cost (enum vect_cost_for_stmt, tree, int);
-extern tree default_builtin_reciprocal (unsigned int, bool, bool);
+extern tree default_builtin_reciprocal (gcall *);
extern HOST_WIDE_INT default_vector_alignment (const_tree);
if (is_gimple_call (stmt1)
&& gimple_call_lhs (stmt1)
- && (fndecl = gimple_call_fndecl (stmt1))
- && (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD))
+ && (gimple_call_internal_p (stmt1)
+ || ((fndecl = gimple_call_fndecl (stmt1))
+ && (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+ || (DECL_BUILT_IN_CLASS (fndecl)
+ == BUILT_IN_MD)))))
{
- enum built_in_function code;
- bool md_code, fail;
+ bool fail;
imm_use_iterator ui;
use_operand_p use_p;
- code = DECL_FUNCTION_CODE (fndecl);
- md_code = DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD;
-
- fndecl = targetm.builtin_reciprocal (code, md_code, false);
+ fndecl = targetm.builtin_reciprocal (as_a <gcall *> (stmt1));
if (!fndecl)
continue;
continue;
gimple_replace_ssa_lhs (stmt1, arg1);
- gimple_call_set_fndecl (stmt1, fndecl);
- update_stmt (stmt1);
+ if (gimple_call_internal_p (stmt1))
+ {
+ auto_vec<tree, 4> args;
+ for (unsigned int i = 0;
+ i < gimple_call_num_args (stmt1); i++)
+ args.safe_push (gimple_call_arg (stmt1, i));
+ gcall *stmt2 = gimple_build_call_vec (fndecl, args);
+ gimple_call_set_lhs (stmt2, arg1);
+ if (gimple_vdef (stmt1))
+ {
+ gimple_set_vdef (stmt2, gimple_vdef (stmt1));
+ SSA_NAME_DEF_STMT (gimple_vdef (stmt2)) = stmt2;
+ }
+ gimple_set_vuse (stmt2, gimple_vuse (stmt1));
+ gimple_stmt_iterator gsi2 = gsi_for_stmt (stmt1);
+ gsi_replace (&gsi2, stmt2, true);
+ }
+ else
+ {
+ gimple_call_set_fndecl (stmt1, fndecl);
+ update_stmt (stmt1);
+ }
reciprocal_stats.rfuncs_inserted++;
FOR_EACH_IMM_USE_STMT (stmt, ui, arg1)