Commit 883cabde by Richard Sandiford Committed by Richard Sandiford

Extend tree-call-cdce to calls whose result is used

For -fmath-errno, builtins.c currently expands calls to sqrt to:

        y = sqrt_optab (x);
        if (y != y)
          [ sqrt (x); or errno = EDOM; ]

The drawbacks of this are:

- the call to sqrt is protected by the result of the optab rather
      than the input.  It would be better to check __builtin_isless (x, 0),
      like tree-call-cdce.c does.

- the branch isn't exposed at the gimple level and so gets little
      high-level optimisation.

- we do this for log too, but for log a zero input produces
      -inf rather than a NaN, and sets errno to ERANGE rather than EDOM.

This patch moves the code to tree-call-cdce.c instead, with the optab
operation being represented as an internal function.  This means that
we can use the existing argument-based range checks rather than the
result-based checks and that we get more gimple optimisation of
the branch.

Previously the pass was only enabled by default at -O2 or above,
but the old builtins.c code was enabled at -O.  The patch therefore
enables the pass at -O as well.

The previous patch to cfgexpand.c handled cases where functions
don't (or are assumed not to) set errno, so this patch makes
the builtins.c code dead.

Tested on x86_64-linux-gnu, aarch64-linux-gnu, arm-linux-gnueabi
and visium-elf (for the EDOM stuff).

gcc/
	* builtins.c (expand_errno_check, expand_builtin_mathfn)
	(expand_builtin_mathfn_2): Delete.
	(expand_builtin): Remove handling of functions with
	internal function equivalents.
	* internal-fn.def (SET_EDOM): New internal function.
	* internal-fn.h (set_edom_supported_p): Declare.
	* internal-fn.c (expand_SET_EDOM): New function.
	(set_edom_supported_p): Likewise.
	* tree-call-cdce.c: Include builtins.h and internal-fn.h.
	Rewrite comment at head of file.
	(is_call_dce_candidate): Rename to...
	(can_test_argument_range): ...this.  Don't check gimple_call_lhs
	or gimple_call_builtin_p here.
	(edom_only_function): New function.
	(shrink_wrap_one_built_in_call_with_conds): New function, split out
	from...
	(shrink_wrap_one_built_in_call): ...here.
	(can_use_internal_fn, use_internal_fn): New functions.
	(shrink_wrap_conditional_dead_built_in_calls): Call use_internal_fn
	for calls that have an lhs.
	(pass_call_cdce::gate): Remove optimize_function_for_speed_p check.
	(pass_call_cdce::execute): Skip blocks that are optimized for size.
	Check gimple_call_builtin_p here.  Use can_use_internal_fn for
	calls with an lhs.
	* opts.c (default_options_table): Enable -ftree-builtin-call-cdce
	at -O and above.

From-SVN: r230488
parent 4cfe7a6c
2015-11-17 Richard Sandiford <richard.sandiford@arm.com>
* builtins.c (expand_errno_check, expand_builtin_mathfn)
(expand_builtin_mathfn_2): Delete.
(expand_builtin): Remove handling of functions with
internal function equivalents.
* internal-fn.def (SET_EDOM): New internal function.
* internal-fn.h (set_edom_supported_p): Declare.
* internal-fn.c (expand_SET_EDOM): New function.
(set_edom_supported_p): Likewise.
* tree-call-cdce.c: Include builtins.h and internal-fn.h.
Rewrite comment at head of file.
(is_call_dce_candidate): Rename to...
(can_test_argument_range): ...this. Don't check gimple_call_lhs
or gimple_call_builtin_p here.
(edom_only_function): New function.
(shrink_wrap_one_built_in_call_with_conds): New function, split out
from...
(shrink_wrap_one_built_in_call): ...here.
(can_use_internal_fn, use_internal_fn): New functions.
(shrink_wrap_conditional_dead_built_in_calls): Call use_internal_fn
for calls that have an lhs.
(pass_call_cdce::gate): Remove optimize_function_for_speed_p check.
(pass_call_cdce::execute): Skip blocks that are optimized for size.
Check gimple_call_builtin_p here. Use can_use_internal_fn for
calls with an lhs.
* opts.c (default_options_table): Enable -ftree-builtin-call-cdce
at -O and above.
2015-11-17 Richard Sandiford <richard.sandiford@arm.com>
* builtins.h (called_as_built_in): Declare.
* builtins.c (called_as_built_in): Make external.
* internal-fn.h (expand_internal_call): Define a variant that
......@@ -2073,6 +2073,24 @@ expand_GOACC_REDUCTION (internal_fn, gcall *)
gcc_unreachable ();
}
/* Set errno to EDOM. */
static void
expand_SET_EDOM (internal_fn, gcall *)
{
#ifdef TARGET_EDOM
#ifdef GEN_ERRNO_RTX
rtx errno_rtx = GEN_ERRNO_RTX;
#else
rtx errno_rtx = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
#endif
emit_move_insn (errno_rtx,
gen_int_mode (TARGET_EDOM, GET_MODE (errno_rtx)));
#else
gcc_unreachable ();
#endif
}
/* Expand a call to FN using the operands in STMT. FN has a single
output operand and NARGS input operands. */
......@@ -2217,6 +2235,18 @@ direct_internal_fn_supported_p (internal_fn fn, tree type)
return direct_internal_fn_supported_p (fn, tree_pair (type, type));
}
/* Return true if IFN_SET_EDOM is supported. */
bool
set_edom_supported_p (void)
{
#ifdef TARGET_EDOM
return true;
#else
return false;
#endif
}
#define DEF_INTERNAL_OPTAB_FN(CODE, FLAGS, OPTAB, TYPE) \
static void \
expand_##CODE (internal_fn fn, gcall *stmt) \
......
......@@ -181,6 +181,10 @@ DEF_INTERNAL_FN (GOACC_LOOP, ECF_PURE | ECF_NOTHROW, NULL)
/* OpenACC reduction abstraction. See internal-fn.h for usage. */
DEF_INTERNAL_FN (GOACC_REDUCTION, ECF_NOTHROW | ECF_LEAF, NULL)
/* Set errno to EDOM, if GCC knows how to do that directly for the
current target. */
DEF_INTERNAL_FN (SET_EDOM, ECF_LEAF | ECF_NOTHROW, NULL)
#undef DEF_INTERNAL_INT_FN
#undef DEF_INTERNAL_FLT_FN
#undef DEF_INTERNAL_OPTAB_FN
......
......@@ -160,6 +160,7 @@ extern tree_pair direct_internal_fn_types (internal_fn, tree, tree *);
extern tree_pair direct_internal_fn_types (internal_fn, gcall *);
extern bool direct_internal_fn_supported_p (internal_fn, tree_pair);
extern bool direct_internal_fn_supported_p (internal_fn, tree);
extern bool set_edom_supported_p (void);
extern void expand_internal_call (gcall *);
extern void expand_internal_call (internal_fn, gcall *);
......
......@@ -478,6 +478,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fmove_loop_invariants, NULL, 1 },
{ OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_pta, NULL, 1 },
{ OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fssa_phiopt, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_builtin_call_dce, NULL, 1 },
/* -O2 optimizations. */
{ OPT_LEVELS_2_PLUS, OPT_finline_small_functions, NULL, 1 },
......@@ -503,7 +504,6 @@ static const struct default_options default_options_table[] =
REORDER_BLOCKS_ALGORITHM_STC },
{ OPT_LEVELS_2_PLUS, OPT_freorder_functions, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_vrp, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_builtin_call_dce, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_pre, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_switch_conversion, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fipa_cp, NULL, 1 },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment