aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
authorJames Greenhalgh <james.greenhalgh@arm.com>2016-11-23 17:23:12 +0000
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>2016-11-23 17:23:12 +0000
commit56d8ffc170912cb1dee5900799acaf5d4857fde9 (patch)
treeb2e05c11d31890a7a8ef669c3474d40a7843da1c /gcc/tree.c
parent04f0fcf7bdfa1b4d153ca37df8843c44ed8c4d93 (diff)
downloadgcc-56d8ffc170912cb1dee5900799acaf5d4857fde9.zip
gcc-56d8ffc170912cb1dee5900799acaf5d4857fde9.tar.gz
gcc-56d8ffc170912cb1dee5900799acaf5d4857fde9.tar.bz2
[Patch 6/17] Migrate excess precision logic to use TARGET_EXCESS_PRECISION
gcc/ * toplev.c (init_excess_precision): Delete most logic. * tree.c (excess_precision_type): Rewrite to use TARGET_EXCESS_PRECISION. * doc/invoke.texi (-fexcess-precision): Document behaviour in a more generic fashion. * ginclude/float.h: Wrap definition of FLT_EVAL_METHOD in __STDC_WANT_IEC_60559_TYPES_EXT__. gcc/c-family/ * c-common.c (excess_precision_mode_join): New. (c_ts18661_flt_eval_method): New. (c_c11_flt_eval_method): Likewise. (c_flt_eval_method): Likewise. * c-common.h (excess_precision_mode_join): New. (c_flt_eval_method): Likewise. * c-cppbuiltin.c (c_cpp_flt_eval_method_iec_559): New. (cpp_iec_559_value): Call it. (c_cpp_builtins): Modify logic for __LIBGCC_*_EXCESS_PRECISION__, call c_flt_eval_method to set __FLT_EVAL_METHOD__ and __FLT_EVAL_METHOD_TS_18661_3__. gcc/testsuite/ * gcc.dg/fpermitted-flt-eval-methods_3.c: New. * gcc.dg/fpermitted-flt-eval-methods_4.c: Likewise. From-SVN: r242776
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c133
1 files changed, 91 insertions, 42 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index 80675db..4f3d678 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -8855,50 +8855,99 @@ build_complex_type (tree component_type, bool named)
tree
excess_precision_type (tree type)
{
- if (flag_excess_precision != EXCESS_PRECISION_FAST)
+ /* The target can give two different responses to the question of
+ which excess precision mode it would like depending on whether we
+ are in -fexcess-precision=standard or -fexcess-precision=fast. */
+
+ enum excess_precision_type requested_type
+ = (flag_excess_precision == EXCESS_PRECISION_FAST
+ ? EXCESS_PRECISION_TYPE_FAST
+ : EXCESS_PRECISION_TYPE_STANDARD);
+
+ enum flt_eval_method target_flt_eval_method
+ = targetm.c.excess_precision (requested_type);
+
+ /* The target should not ask for unpredictable float evaluation (though
+ it might advertise that implicitly the evaluation is unpredictable,
+ but we don't care about that here, it will have been reported
+ elsewhere). If it does ask for unpredictable evaluation, we have
+ nothing to do here. */
+ gcc_assert (target_flt_eval_method != FLT_EVAL_METHOD_UNPREDICTABLE);
+
+ /* Nothing to do. The target has asked for all types we know about
+ to be computed with their native precision and range. */
+ if (target_flt_eval_method == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+ return NULL_TREE;
+
+ /* The target will promote this type in a target-dependent way, so excess
+ precision ought to leave it alone. */
+ if (targetm.promoted_type (type) != NULL_TREE)
+ return NULL_TREE;
+
+ machine_mode float16_type_mode = (float16_type_node
+ ? TYPE_MODE (float16_type_node)
+ : VOIDmode);
+ machine_mode float_type_mode = TYPE_MODE (float_type_node);
+ machine_mode double_type_mode = TYPE_MODE (double_type_node);
+
+ switch (TREE_CODE (type))
{
- int flt_eval_method = TARGET_FLT_EVAL_METHOD;
- switch (TREE_CODE (type))
- {
- case REAL_TYPE:
- switch (flt_eval_method)
- {
- case 1:
- if (TYPE_MODE (type) == TYPE_MODE (float_type_node))
- return double_type_node;
- break;
- case 2:
- if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
- || TYPE_MODE (type) == TYPE_MODE (double_type_node))
- return long_double_type_node;
- break;
- default:
- gcc_unreachable ();
- }
- break;
- case COMPLEX_TYPE:
- if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
- return NULL_TREE;
- switch (flt_eval_method)
- {
- case 1:
- if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node))
- return complex_double_type_node;
- break;
- case 2:
- if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node)
- || (TYPE_MODE (TREE_TYPE (type))
- == TYPE_MODE (double_type_node)))
- return complex_long_double_type_node;
- break;
- default:
- gcc_unreachable ();
- }
- break;
- default:
- break;
- }
+ case REAL_TYPE:
+ {
+ machine_mode type_mode = TYPE_MODE (type);
+ switch (target_flt_eval_method)
+ {
+ case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+ if (type_mode == float16_type_mode)
+ return float_type_node;
+ break;
+ case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+ if (type_mode == float16_type_mode
+ || type_mode == float_type_mode)
+ return double_type_node;
+ break;
+ case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+ if (type_mode == float16_type_mode
+ || type_mode == float_type_mode
+ || type_mode == double_type_mode)
+ return long_double_type_node;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ break;
+ }
+ case COMPLEX_TYPE:
+ {
+ if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
+ return NULL_TREE;
+ machine_mode type_mode = TYPE_MODE (TREE_TYPE (type));
+ switch (target_flt_eval_method)
+ {
+ case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+ if (type_mode == float16_type_mode)
+ return complex_float_type_node;
+ break;
+ case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+ if (type_mode == float16_type_mode
+ || type_mode == float_type_mode)
+ return complex_double_type_node;
+ break;
+ case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+ if (type_mode == float16_type_mode
+ || type_mode == float_type_mode
+ || type_mode == double_type_mode)
+ return complex_long_double_type_node;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ break;
+ }
+ default:
+ break;
}
+
return NULL_TREE;
}