aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-family/c-cppbuiltin.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/c-family/c-cppbuiltin.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/c-family/c-cppbuiltin.c')
-rw-r--r--gcc/c-family/c-cppbuiltin.c106
1 files changed, 79 insertions, 27 deletions
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 5c88e91..e2419e8 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -728,6 +728,31 @@ cpp_atomic_builtins (cpp_reader *pfile)
(have_swap[psize]? 2 : 1));
}
+/* Return TRUE if the implicit excess precision in which the back-end will
+ compute floating-point calculations is not more than the explicit
+ excess precision that the front-end will apply under
+ -fexcess-precision=[standard|fast].
+
+ More intuitively, return TRUE if the excess precision proposed by the
+ front-end is the excess precision that will actually be used. */
+
+static bool
+c_cpp_flt_eval_method_iec_559 (void)
+{
+ enum excess_precision_type front_end_ept
+ = (flag_excess_precision_cmdline == EXCESS_PRECISION_STANDARD
+ ? EXCESS_PRECISION_TYPE_STANDARD
+ : EXCESS_PRECISION_TYPE_FAST);
+
+ enum flt_eval_method back_end
+ = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
+
+ enum flt_eval_method front_end
+ = targetm.c.excess_precision (front_end_ept);
+
+ return excess_precision_mode_join (front_end, back_end) == front_end;
+}
+
/* Return the value for __GCC_IEC_559. */
static int
cpp_iec_559_value (void)
@@ -770,16 +795,17 @@ cpp_iec_559_value (void)
|| !dfmt->has_signed_zero)
ret = 0;
- /* In strict C standards conformance mode, consider unpredictable
- excess precision to mean lack of IEEE 754 support. The same
- applies to unpredictable contraction. For C++, and outside
- strict conformance mode, do not consider these options to mean
- lack of IEEE 754 support. */
+ /* In strict C standards conformance mode, consider a back-end providing
+ more implicit excess precision than the explicit excess precision
+ the front-end options would require to mean a lack of IEEE 754
+ support. For C++, and outside strict conformance mode, do not consider
+ this to mean a lack of IEEE 754 support. */
+
if (flag_iso
&& !c_dialect_cxx ()
- && TARGET_FLT_EVAL_METHOD != 0
- && flag_excess_precision_cmdline != EXCESS_PRECISION_STANDARD)
+ && !c_cpp_flt_eval_method_iec_559 ())
ret = 0;
+
if (flag_iso
&& !c_dialect_cxx ()
&& flag_fp_contract_mode == FP_CONTRACT_FAST)
@@ -1045,9 +1071,22 @@ c_cpp_builtins (cpp_reader *pfile)
builtin_define_with_int_value ("__GCC_IEC_559_COMPLEX",
cpp_iec_559_complex_value ());
- /* float.h needs to know this. */
+ /* float.h needs these to correctly set FLT_EVAL_METHOD
+
+ We define two values:
+
+ __FLT_EVAL_METHOD__
+ Which, depending on the value given for
+ -fpermitted-flt-eval-methods, may be limited to only those values
+ for FLT_EVAL_METHOD defined in C99/C11.
+
+ __FLT_EVAL_METHOD_TS_18661_3__
+ Which always permits the values for FLT_EVAL_METHOD defined in
+ ISO/IEC TS 18661-3. */
builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
- TARGET_FLT_EVAL_METHOD);
+ c_flt_eval_method (true));
+ builtin_define_with_int_value ("__FLT_EVAL_METHOD_TS_18661_3__",
+ c_flt_eval_method (false));
/* And decfloat.h needs this. */
builtin_define_with_int_value ("__DEC_EVAL_METHOD__",
@@ -1188,25 +1227,38 @@ c_cpp_builtins (cpp_reader *pfile)
gcc_assert (found_suffix);
}
builtin_define_with_value (macro_name, suffix, 0);
+
+ /* The way __LIBGCC_*_EXCESS_PRECISION__ is used is about
+ eliminating excess precision from results assigned to
+ variables - meaning it should be about the implicit excess
+ precision only. */
bool excess_precision = false;
- if (TARGET_FLT_EVAL_METHOD != 0
- && mode != TYPE_MODE (long_double_type_node)
- && (mode == TYPE_MODE (float_type_node)
- || mode == TYPE_MODE (double_type_node)))
- switch (TARGET_FLT_EVAL_METHOD)
- {
- case -1:
- case 2:
- excess_precision = true;
- break;
-
- case 1:
- excess_precision = mode == TYPE_MODE (float_type_node);
- break;
-
- default:
- gcc_unreachable ();
- }
+ machine_mode float16_type_mode = (float16_type_node
+ ? TYPE_MODE (float16_type_node)
+ : VOIDmode);
+ switch (targetm.c.excess_precision
+ (EXCESS_PRECISION_TYPE_IMPLICIT))
+ {
+ case FLT_EVAL_METHOD_UNPREDICTABLE:
+ case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+ excess_precision = (mode == float16_type_mode
+ || mode == TYPE_MODE (float_type_node)
+ || mode == TYPE_MODE (double_type_node));
+ break;
+
+ case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+ excess_precision = (mode == float16_type_mode
+ || mode == TYPE_MODE (float_type_node));
+ break;
+ case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+ excess_precision = mode == float16_type_mode;
+ break;
+ case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16:
+ excess_precision = false;
+ break;
+ default:
+ gcc_unreachable ();
+ }
macro_name = (char *) alloca (strlen (name)
+ sizeof ("__LIBGCC__EXCESS_"
"PRECISION__"));