* PR 71020: Handle abnormal PHIs in tree-call-cdce.c
@ 2016-05-18 9:10 Richard Sandiford
2016-05-18 11:22 ` Richard Biener
0 siblings, 1 reply; 2+ messages in thread
From: Richard Sandiford @ 2016-05-18 9:10 UTC (permalink / raw)
To: gcc-patches
The PR is about a case where tree-call-cdce.c causes two abnormal
PHIs for the same variable to be live at the same time, leading to
a coalescing failure. It seemed like getting rid of these kinds of
input would be generally useful, so I added a utility to tree-dfa.c.
Tested on x86_64-linux-gnu. OK to install?
Thanks,
Richard
gcc/
PR middle-end/71020
* tree-dfa.h (replace_abnormal_ssa_names): Declare.
* tree-dfa.c (replace_abnormal_ssa_names): New function.
* tree-call-cdce.c: Include tree-dfa.h.
(can_guard_call_p): New function, extracted from...
(can_use_internal_fn): ...here.
(shrink_wrap_one_built_in_call_with_conds): Remove failure path
and return void.
(shrink_wrap_one_built_in_call): Likewise.
(use_internal_fn): Likewise.
(shrink_wrap_conditional_dead_built_in_calls): Update accordingly
and return void. Call replace_abnormal_ssa_names.
(pass_call_cdce::execute): Check can_guard_call_p during the
initial walk. Assume shrink_wrap_conditional_dead_built_in_calls
will always change something.
gcc/testsuite/
* gcc.dg/torture/pr71020.c: New test.
Index: gcc/tree-dfa.h
===================================================================
--- gcc/tree-dfa.h
+++ gcc/tree-dfa.h
@@ -35,6 +35,7 @@ extern tree get_addr_base_and_unit_offset_1 (tree, HOST_WIDE_INT *,
tree (*) (tree));
extern tree get_addr_base_and_unit_offset (tree, HOST_WIDE_INT *);
extern bool stmt_references_abnormal_ssa_name (gimple *);
+extern void replace_abnormal_ssa_names (gimple *);
extern void dump_enumerated_decls (FILE *, int);
Index: gcc/tree-dfa.c
===================================================================
--- gcc/tree-dfa.c
+++ gcc/tree-dfa.c
@@ -823,6 +823,29 @@ stmt_references_abnormal_ssa_name (gimple *stmt)
return false;
}
+/* If STMT takes any abnormal PHI values as input, replace them with
+ local copies. */
+
+void
+replace_abnormal_ssa_names (gimple *stmt)
+{
+ ssa_op_iter oi;
+ use_operand_p use_p;
+
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, oi, SSA_OP_USE)
+ {
+ tree op = USE_FROM_PTR (use_p);
+ if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
+ {
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ tree new_name = make_ssa_name (TREE_TYPE (op));
+ gassign *assign = gimple_build_assign (new_name, op);
+ gsi_insert_before (&gsi, assign, GSI_SAME_STMT);
+ SET_USE (use_p, new_name);
+ }
+ }
+}
+
/* Pair of tree and a sorting index, for dump_enumerated_decls. */
struct GTY(()) numbered_tree
{
Index: gcc/tree-call-cdce.c
===================================================================
--- gcc/tree-call-cdce.c
+++ gcc/tree-call-cdce.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-into-ssa.h"
#include "builtins.h"
#include "internal-fn.h"
+#include "tree-dfa.h"
\f
/* This pass serves two closely-related purposes:
@@ -349,6 +350,15 @@ edom_only_function (gcall *call)
return false;
}
}
+
+/* Return true if it is structurally possible to guard CALL. */
+
+static bool
+can_guard_call_p (gimple *call)
+{
+ return (!stmt_ends_bb_p (call)
+ || find_fallthru_edge (gimple_bb (call)->succs));
+}
\f
/* A helper function to generate gimple statements for one bound
comparison, so that the built-in function is called whenever
@@ -747,11 +757,9 @@ gen_shrink_wrap_conditions (gcall *bi_call, vec<gimple *> conds,
#define ERR_PROB 0.01
/* Shrink-wrap BI_CALL so that it is only called when one of the NCONDS
- conditions in CONDS is false.
+ conditions in CONDS is false. */
- Return true on success, in which case the cfg will have been updated. */
-
-static bool
+static void
shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
unsigned int nconds)
{
@@ -795,11 +803,10 @@ shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
/* Now find the join target bb -- split bi_call_bb if needed. */
if (stmt_ends_bb_p (bi_call))
{
- /* If the call must be the last in the bb, don't split the block,
- it could e.g. have EH edges. */
+ /* We checked that there was a fallthrough edge in
+ can_guard_call_p. */
join_tgt_in_edge_from_call = find_fallthru_edge (bi_call_bb->succs);
- if (join_tgt_in_edge_from_call == NULL)
- return false;
+ gcc_assert (join_tgt_in_edge_from_call);
free_dominance_info (CDI_DOMINATORS);
}
else
@@ -898,28 +905,19 @@ shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
" into error conditions.\n",
LOCATION_FILE (loc), LOCATION_LINE (loc));
}
-
- return true;
}
/* Shrink-wrap BI_CALL so that it is only called when it might set errno
- (but is always called if it would set errno).
-
- Return true on success, in which case the cfg will have been updated. */
+ (but is always called if it would set errno). */
-static bool
+static void
shrink_wrap_one_built_in_call (gcall *bi_call)
{
unsigned nconds = 0;
auto_vec<gimple *, 12> conds;
gen_shrink_wrap_conditions (bi_call, conds, &nconds);
- /* This can happen if the condition generator decides
- it is not beneficial to do the transformation. Just
- return false and do not do any transformation for
- the call. */
- if (nconds == 0)
- return false;
- return shrink_wrap_one_built_in_call_with_conds (bi_call, conds, nconds);
+ gcc_assert (nconds != 0);
+ shrink_wrap_one_built_in_call_with_conds (bi_call, conds, nconds);
}
/* Return true if built-in function call CALL could be implemented using
@@ -933,11 +931,6 @@ can_use_internal_fn (gcall *call)
if (!gimple_vdef (call))
return false;
- /* Punt if we can't conditionalize the call. */
- basic_block bb = gimple_bb (call);
- if (stmt_ends_bb_p (call) && !find_fallthru_edge (bb->succs))
- return false;
-
/* See whether there is an internal function for this built-in. */
if (replacement_internal_fn (call) == IFN_LAST)
return false;
@@ -951,18 +944,25 @@ can_use_internal_fn (gcall *call)
return true;
}
-/* Implement built-in function call CALL using an internal function.
- Return true on success, in which case the cfg will have changed. */
+/* Implement built-in function call CALL using an internal function. */
-static bool
+static void
use_internal_fn (gcall *call)
{
+ /* We'll be inserting another call with the same arguments after the
+ lhs has been set, so prevent any possible coalescing failure from
+ having both values live at once. See PR 71020. */
+ replace_abnormal_ssa_names (call);
+
unsigned nconds = 0;
auto_vec<gimple *, 12> conds;
if (can_test_argument_range (call))
- gen_shrink_wrap_conditions (call, conds, &nconds);
- if (nconds == 0 && !edom_only_function (call))
- return false;
+ {
+ gen_shrink_wrap_conditions (call, conds, &nconds);
+ gcc_assert (nconds != 0);
+ }
+ else
+ gcc_assert (edom_only_function (call));
internal_fn ifn = replacement_internal_fn (call);
gcc_assert (ifn != IFN_LAST);
@@ -1008,35 +1008,26 @@ use_internal_fn (gcall *call)
}
}
- if (!shrink_wrap_one_built_in_call_with_conds (call, conds, nconds))
- /* It's too late to back out now. */
- gcc_unreachable ();
- return true;
+ shrink_wrap_one_built_in_call_with_conds (call, conds, nconds);
}
/* The top level function for conditional dead code shrink
wrapping transformation. */
-static bool
+static void
shrink_wrap_conditional_dead_built_in_calls (vec<gcall *> calls)
{
- bool changed = false;
unsigned i = 0;
unsigned n = calls.length ();
- if (n == 0)
- return false;
-
for (; i < n ; i++)
{
gcall *bi_call = calls[i];
if (gimple_call_lhs (bi_call))
- changed |= use_internal_fn (bi_call);
+ use_internal_fn (bi_call);
else
- changed |= shrink_wrap_one_built_in_call (bi_call);
+ shrink_wrap_one_built_in_call (bi_call);
}
-
- return changed;
}
namespace {
@@ -1079,7 +1070,6 @@ pass_call_cdce::execute (function *fun)
{
basic_block bb;
gimple_stmt_iterator i;
- bool something_changed = false;
auto_vec<gcall *> cond_dead_built_in_calls;
FOR_EACH_BB_FN (bb, fun)
{
@@ -1096,7 +1086,8 @@ pass_call_cdce::execute (function *fun)
&& gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)
&& (gimple_call_lhs (stmt)
? can_use_internal_fn (stmt)
- : can_test_argument_range (stmt)))
+ : can_test_argument_range (stmt))
+ && can_guard_call_p (stmt))
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -1114,19 +1105,12 @@ pass_call_cdce::execute (function *fun)
if (!cond_dead_built_in_calls.exists ())
return 0;
- something_changed
- = shrink_wrap_conditional_dead_built_in_calls (cond_dead_built_in_calls);
-
- if (something_changed)
- {
- free_dominance_info (CDI_POST_DOMINATORS);
- /* As we introduced new control-flow we need to insert PHI-nodes
- for the call-clobbers of the remaining call. */
- mark_virtual_operands_for_renaming (fun);
- return TODO_update_ssa;
- }
-
- return 0;
+ shrink_wrap_conditional_dead_built_in_calls (cond_dead_built_in_calls);
+ free_dominance_info (CDI_POST_DOMINATORS);
+ /* As we introduced new control-flow we need to insert PHI-nodes
+ for the call-clobbers of the remaining call. */
+ mark_virtual_operands_for_renaming (fun);
+ return TODO_update_ssa;
}
} // anon namespace
Index: gcc/testsuite/gcc.dg/torture/pr71020.c
===================================================================
--- /dev/null
+++ gcc/testsuite/gcc.dg/torture/pr71020.c
@@ -0,0 +1,76 @@
+/* { dg-options "-funsafe-math-optimizations" } */
+
+double random_double (void);
+int setjmp (void *);
+void do_something (void);
+
+#define TEST_UNARY(FUNC) \
+ double \
+ FUNC##_dead (void *buffer) \
+ { \
+ double d = random_double (); \
+ setjmp (buffer); \
+ __builtin_##FUNC (d); \
+ d += 1; \
+ do_something (); \
+ return d; \
+ } \
+ \
+ double \
+ FUNC##_live (void *buffer) \
+ { \
+ double d = random_double (); \
+ setjmp (buffer); \
+ d = __builtin_##FUNC (d); \
+ do_something (); \
+ return d; \
+ }
+
+
+#define TEST_BINARY(FUNC) \
+ double \
+ FUNC##_dead (void *buffer) \
+ { \
+ double d1 = random_double (); \
+ double d2 = random_double (); \
+ setjmp (buffer); \
+ __builtin_##FUNC (d1, d2); \
+ d1 += 1; \
+ d2 += 1; \
+ do_something (); \
+ return d1 + d2; \
+ } \
+ \
+ double \
+ FUNC##_live (void *buffer) \
+ { \
+ double d1 = random_double (); \
+ double d2 = random_double (); \
+ setjmp (buffer); \
+ d1 = __builtin_##FUNC (d1, d2); \
+ d2 += 1; \
+ return d1 + d2; \
+ }
+
+TEST_UNARY (acos)
+TEST_UNARY (asin)
+TEST_UNARY (asinh)
+TEST_UNARY (atan)
+TEST_UNARY (atanh)
+TEST_UNARY (cos)
+TEST_UNARY (cosh)
+TEST_UNARY (exp)
+TEST_UNARY (expm1)
+TEST_UNARY (exp2)
+TEST_UNARY (exp10)
+TEST_UNARY (log)
+TEST_UNARY (log2)
+TEST_UNARY (log10)
+TEST_UNARY (log1p)
+TEST_UNARY (significand)
+TEST_UNARY (sin)
+TEST_UNARY (sinh)
+TEST_UNARY (sqrt)
+
+TEST_BINARY (fmod)
+TEST_BINARY (remainder)
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: PR 71020: Handle abnormal PHIs in tree-call-cdce.c
2016-05-18 9:10 PR 71020: Handle abnormal PHIs in tree-call-cdce.c Richard Sandiford
@ 2016-05-18 11:22 ` Richard Biener
0 siblings, 0 replies; 2+ messages in thread
From: Richard Biener @ 2016-05-18 11:22 UTC (permalink / raw)
To: GCC Patches, richard.sandiford
On Wed, May 18, 2016 at 11:10 AM, Richard Sandiford
<richard.sandiford@arm.com> wrote:
> The PR is about a case where tree-call-cdce.c causes two abnormal
> PHIs for the same variable to be live at the same time, leading to
> a coalescing failure. It seemed like getting rid of these kinds of
> input would be generally useful, so I added a utility to tree-dfa.c.
>
> Tested on x86_64-linux-gnu. OK to install?
Ok.
Thanks,
Richard.
> Thanks,
> Richard
>
>
> gcc/
> PR middle-end/71020
> * tree-dfa.h (replace_abnormal_ssa_names): Declare.
> * tree-dfa.c (replace_abnormal_ssa_names): New function.
> * tree-call-cdce.c: Include tree-dfa.h.
> (can_guard_call_p): New function, extracted from...
> (can_use_internal_fn): ...here.
> (shrink_wrap_one_built_in_call_with_conds): Remove failure path
> and return void.
> (shrink_wrap_one_built_in_call): Likewise.
> (use_internal_fn): Likewise.
> (shrink_wrap_conditional_dead_built_in_calls): Update accordingly
> and return void. Call replace_abnormal_ssa_names.
> (pass_call_cdce::execute): Check can_guard_call_p during the
> initial walk. Assume shrink_wrap_conditional_dead_built_in_calls
> will always change something.
>
> gcc/testsuite/
> * gcc.dg/torture/pr71020.c: New test.
>
> Index: gcc/tree-dfa.h
> ===================================================================
> --- gcc/tree-dfa.h
> +++ gcc/tree-dfa.h
> @@ -35,6 +35,7 @@ extern tree get_addr_base_and_unit_offset_1 (tree, HOST_WIDE_INT *,
> tree (*) (tree));
> extern tree get_addr_base_and_unit_offset (tree, HOST_WIDE_INT *);
> extern bool stmt_references_abnormal_ssa_name (gimple *);
> +extern void replace_abnormal_ssa_names (gimple *);
> extern void dump_enumerated_decls (FILE *, int);
>
>
> Index: gcc/tree-dfa.c
> ===================================================================
> --- gcc/tree-dfa.c
> +++ gcc/tree-dfa.c
> @@ -823,6 +823,29 @@ stmt_references_abnormal_ssa_name (gimple *stmt)
> return false;
> }
>
> +/* If STMT takes any abnormal PHI values as input, replace them with
> + local copies. */
> +
> +void
> +replace_abnormal_ssa_names (gimple *stmt)
> +{
> + ssa_op_iter oi;
> + use_operand_p use_p;
> +
> + FOR_EACH_SSA_USE_OPERAND (use_p, stmt, oi, SSA_OP_USE)
> + {
> + tree op = USE_FROM_PTR (use_p);
> + if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
> + {
> + gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
> + tree new_name = make_ssa_name (TREE_TYPE (op));
> + gassign *assign = gimple_build_assign (new_name, op);
> + gsi_insert_before (&gsi, assign, GSI_SAME_STMT);
> + SET_USE (use_p, new_name);
> + }
> + }
> +}
> +
> /* Pair of tree and a sorting index, for dump_enumerated_decls. */
> struct GTY(()) numbered_tree
> {
> Index: gcc/tree-call-cdce.c
> ===================================================================
> --- gcc/tree-call-cdce.c
> +++ gcc/tree-call-cdce.c
> @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
> #include "tree-into-ssa.h"
> #include "builtins.h"
> #include "internal-fn.h"
> +#include "tree-dfa.h"
>
>
> /* This pass serves two closely-related purposes:
> @@ -349,6 +350,15 @@ edom_only_function (gcall *call)
> return false;
> }
> }
> +
> +/* Return true if it is structurally possible to guard CALL. */
> +
> +static bool
> +can_guard_call_p (gimple *call)
> +{
> + return (!stmt_ends_bb_p (call)
> + || find_fallthru_edge (gimple_bb (call)->succs));
> +}
>
> /* A helper function to generate gimple statements for one bound
> comparison, so that the built-in function is called whenever
> @@ -747,11 +757,9 @@ gen_shrink_wrap_conditions (gcall *bi_call, vec<gimple *> conds,
> #define ERR_PROB 0.01
>
> /* Shrink-wrap BI_CALL so that it is only called when one of the NCONDS
> - conditions in CONDS is false.
> + conditions in CONDS is false. */
>
> - Return true on success, in which case the cfg will have been updated. */
> -
> -static bool
> +static void
> shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
> unsigned int nconds)
> {
> @@ -795,11 +803,10 @@ shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
> /* Now find the join target bb -- split bi_call_bb if needed. */
> if (stmt_ends_bb_p (bi_call))
> {
> - /* If the call must be the last in the bb, don't split the block,
> - it could e.g. have EH edges. */
> + /* We checked that there was a fallthrough edge in
> + can_guard_call_p. */
> join_tgt_in_edge_from_call = find_fallthru_edge (bi_call_bb->succs);
> - if (join_tgt_in_edge_from_call == NULL)
> - return false;
> + gcc_assert (join_tgt_in_edge_from_call);
> free_dominance_info (CDI_DOMINATORS);
> }
> else
> @@ -898,28 +905,19 @@ shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
> " into error conditions.\n",
> LOCATION_FILE (loc), LOCATION_LINE (loc));
> }
> -
> - return true;
> }
>
> /* Shrink-wrap BI_CALL so that it is only called when it might set errno
> - (but is always called if it would set errno).
> -
> - Return true on success, in which case the cfg will have been updated. */
> + (but is always called if it would set errno). */
>
> -static bool
> +static void
> shrink_wrap_one_built_in_call (gcall *bi_call)
> {
> unsigned nconds = 0;
> auto_vec<gimple *, 12> conds;
> gen_shrink_wrap_conditions (bi_call, conds, &nconds);
> - /* This can happen if the condition generator decides
> - it is not beneficial to do the transformation. Just
> - return false and do not do any transformation for
> - the call. */
> - if (nconds == 0)
> - return false;
> - return shrink_wrap_one_built_in_call_with_conds (bi_call, conds, nconds);
> + gcc_assert (nconds != 0);
> + shrink_wrap_one_built_in_call_with_conds (bi_call, conds, nconds);
> }
>
> /* Return true if built-in function call CALL could be implemented using
> @@ -933,11 +931,6 @@ can_use_internal_fn (gcall *call)
> if (!gimple_vdef (call))
> return false;
>
> - /* Punt if we can't conditionalize the call. */
> - basic_block bb = gimple_bb (call);
> - if (stmt_ends_bb_p (call) && !find_fallthru_edge (bb->succs))
> - return false;
> -
> /* See whether there is an internal function for this built-in. */
> if (replacement_internal_fn (call) == IFN_LAST)
> return false;
> @@ -951,18 +944,25 @@ can_use_internal_fn (gcall *call)
> return true;
> }
>
> -/* Implement built-in function call CALL using an internal function.
> - Return true on success, in which case the cfg will have changed. */
> +/* Implement built-in function call CALL using an internal function. */
>
> -static bool
> +static void
> use_internal_fn (gcall *call)
> {
> + /* We'll be inserting another call with the same arguments after the
> + lhs has been set, so prevent any possible coalescing failure from
> + having both values live at once. See PR 71020. */
> + replace_abnormal_ssa_names (call);
> +
> unsigned nconds = 0;
> auto_vec<gimple *, 12> conds;
> if (can_test_argument_range (call))
> - gen_shrink_wrap_conditions (call, conds, &nconds);
> - if (nconds == 0 && !edom_only_function (call))
> - return false;
> + {
> + gen_shrink_wrap_conditions (call, conds, &nconds);
> + gcc_assert (nconds != 0);
> + }
> + else
> + gcc_assert (edom_only_function (call));
>
> internal_fn ifn = replacement_internal_fn (call);
> gcc_assert (ifn != IFN_LAST);
> @@ -1008,35 +1008,26 @@ use_internal_fn (gcall *call)
> }
> }
>
> - if (!shrink_wrap_one_built_in_call_with_conds (call, conds, nconds))
> - /* It's too late to back out now. */
> - gcc_unreachable ();
> - return true;
> + shrink_wrap_one_built_in_call_with_conds (call, conds, nconds);
> }
>
> /* The top level function for conditional dead code shrink
> wrapping transformation. */
>
> -static bool
> +static void
> shrink_wrap_conditional_dead_built_in_calls (vec<gcall *> calls)
> {
> - bool changed = false;
> unsigned i = 0;
>
> unsigned n = calls.length ();
> - if (n == 0)
> - return false;
> -
> for (; i < n ; i++)
> {
> gcall *bi_call = calls[i];
> if (gimple_call_lhs (bi_call))
> - changed |= use_internal_fn (bi_call);
> + use_internal_fn (bi_call);
> else
> - changed |= shrink_wrap_one_built_in_call (bi_call);
> + shrink_wrap_one_built_in_call (bi_call);
> }
> -
> - return changed;
> }
>
> namespace {
> @@ -1079,7 +1070,6 @@ pass_call_cdce::execute (function *fun)
> {
> basic_block bb;
> gimple_stmt_iterator i;
> - bool something_changed = false;
> auto_vec<gcall *> cond_dead_built_in_calls;
> FOR_EACH_BB_FN (bb, fun)
> {
> @@ -1096,7 +1086,8 @@ pass_call_cdce::execute (function *fun)
> && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)
> && (gimple_call_lhs (stmt)
> ? can_use_internal_fn (stmt)
> - : can_test_argument_range (stmt)))
> + : can_test_argument_range (stmt))
> + && can_guard_call_p (stmt))
> {
> if (dump_file && (dump_flags & TDF_DETAILS))
> {
> @@ -1114,19 +1105,12 @@ pass_call_cdce::execute (function *fun)
> if (!cond_dead_built_in_calls.exists ())
> return 0;
>
> - something_changed
> - = shrink_wrap_conditional_dead_built_in_calls (cond_dead_built_in_calls);
> -
> - if (something_changed)
> - {
> - free_dominance_info (CDI_POST_DOMINATORS);
> - /* As we introduced new control-flow we need to insert PHI-nodes
> - for the call-clobbers of the remaining call. */
> - mark_virtual_operands_for_renaming (fun);
> - return TODO_update_ssa;
> - }
> -
> - return 0;
> + shrink_wrap_conditional_dead_built_in_calls (cond_dead_built_in_calls);
> + free_dominance_info (CDI_POST_DOMINATORS);
> + /* As we introduced new control-flow we need to insert PHI-nodes
> + for the call-clobbers of the remaining call. */
> + mark_virtual_operands_for_renaming (fun);
> + return TODO_update_ssa;
> }
>
> } // anon namespace
> Index: gcc/testsuite/gcc.dg/torture/pr71020.c
> ===================================================================
> --- /dev/null
> +++ gcc/testsuite/gcc.dg/torture/pr71020.c
> @@ -0,0 +1,76 @@
> +/* { dg-options "-funsafe-math-optimizations" } */
> +
> +double random_double (void);
> +int setjmp (void *);
> +void do_something (void);
> +
> +#define TEST_UNARY(FUNC) \
> + double \
> + FUNC##_dead (void *buffer) \
> + { \
> + double d = random_double (); \
> + setjmp (buffer); \
> + __builtin_##FUNC (d); \
> + d += 1; \
> + do_something (); \
> + return d; \
> + } \
> + \
> + double \
> + FUNC##_live (void *buffer) \
> + { \
> + double d = random_double (); \
> + setjmp (buffer); \
> + d = __builtin_##FUNC (d); \
> + do_something (); \
> + return d; \
> + }
> +
> +
> +#define TEST_BINARY(FUNC) \
> + double \
> + FUNC##_dead (void *buffer) \
> + { \
> + double d1 = random_double (); \
> + double d2 = random_double (); \
> + setjmp (buffer); \
> + __builtin_##FUNC (d1, d2); \
> + d1 += 1; \
> + d2 += 1; \
> + do_something (); \
> + return d1 + d2; \
> + } \
> + \
> + double \
> + FUNC##_live (void *buffer) \
> + { \
> + double d1 = random_double (); \
> + double d2 = random_double (); \
> + setjmp (buffer); \
> + d1 = __builtin_##FUNC (d1, d2); \
> + d2 += 1; \
> + return d1 + d2; \
> + }
> +
> +TEST_UNARY (acos)
> +TEST_UNARY (asin)
> +TEST_UNARY (asinh)
> +TEST_UNARY (atan)
> +TEST_UNARY (atanh)
> +TEST_UNARY (cos)
> +TEST_UNARY (cosh)
> +TEST_UNARY (exp)
> +TEST_UNARY (expm1)
> +TEST_UNARY (exp2)
> +TEST_UNARY (exp10)
> +TEST_UNARY (log)
> +TEST_UNARY (log2)
> +TEST_UNARY (log10)
> +TEST_UNARY (log1p)
> +TEST_UNARY (significand)
> +TEST_UNARY (sin)
> +TEST_UNARY (sinh)
> +TEST_UNARY (sqrt)
> +
> +TEST_BINARY (fmod)
> +TEST_BINARY (remainder)
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2016-05-18 11:22 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-18 9:10 PR 71020: Handle abnormal PHIs in tree-call-cdce.c Richard Sandiford
2016-05-18 11:22 ` Richard Biener
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).