[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
This commit is contained in:
parent
04f0fcf7bd
commit
56d8ffc170
|
@ -1,3 +1,13 @@
|
||||||
|
2016-11-23 James Greenhalgh <james.greenhalgh@arm.com>
|
||||||
|
|
||||||
|
* 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__.
|
||||||
|
|
||||||
2016-11-23 James Greenhalgh <james.greenhalgh@arm.com>
|
2016-11-23 James Greenhalgh <james.greenhalgh@arm.com>
|
||||||
|
|
||||||
* common.opt (fpermitted-flt-eval-methods): New.
|
* common.opt (fpermitted-flt-eval-methods): New.
|
||||||
|
|
|
@ -1,3 +1,17 @@
|
||||||
|
2016-11-23 James Greenhalgh <james.greenhalgh@arm.com>
|
||||||
|
|
||||||
|
* 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__.
|
||||||
|
|
||||||
2016-11-23 James Greenhalgh <james.greenhalgh@arm.com>
|
2016-11-23 James Greenhalgh <james.greenhalgh@arm.com>
|
||||||
|
|
||||||
* c-opts.c (c_common_post_options): Add logic to handle the default
|
* c-opts.c (c_common_post_options): Add logic to handle the default
|
||||||
|
|
|
@ -7950,4 +7950,86 @@ cb_get_suggestion (cpp_reader *, const char *goal,
|
||||||
return bm.get_best_meaningful_candidate ();
|
return bm.get_best_meaningful_candidate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the latice point which is the wider of the two FLT_EVAL_METHOD
|
||||||
|
modes X, Y. This isn't just >, as the FLT_EVAL_METHOD values added
|
||||||
|
by C TS 18661-3 for interchange types that are computed in their
|
||||||
|
native precision are larger than the C11 values for evaluating in the
|
||||||
|
precision of float/double/long double. If either mode is
|
||||||
|
FLT_EVAL_METHOD_UNPREDICTABLE, return that. */
|
||||||
|
|
||||||
|
enum flt_eval_method
|
||||||
|
excess_precision_mode_join (enum flt_eval_method x,
|
||||||
|
enum flt_eval_method y)
|
||||||
|
{
|
||||||
|
if (x == FLT_EVAL_METHOD_UNPREDICTABLE
|
||||||
|
|| y == FLT_EVAL_METHOD_UNPREDICTABLE)
|
||||||
|
return FLT_EVAL_METHOD_UNPREDICTABLE;
|
||||||
|
|
||||||
|
/* GCC only supports one interchange type right now, _Float16. If
|
||||||
|
we're evaluating _Float16 in 16-bit precision, then flt_eval_method
|
||||||
|
will be FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16. */
|
||||||
|
if (x == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
|
||||||
|
return y;
|
||||||
|
if (y == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
|
||||||
|
return x;
|
||||||
|
|
||||||
|
/* Other values for flt_eval_method are directly comparable, and we want
|
||||||
|
the maximum. */
|
||||||
|
return MAX (x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the value that should be set for FLT_EVAL_METHOD in the
|
||||||
|
context of ISO/IEC TS 18861-3.
|
||||||
|
|
||||||
|
This relates to the effective excess precision seen by the user,
|
||||||
|
which is the join point of the precision the target requests for
|
||||||
|
-fexcess-precision={standard,fast} and the implicit excess precision
|
||||||
|
the target uses. */
|
||||||
|
|
||||||
|
static enum flt_eval_method
|
||||||
|
c_ts18661_flt_eval_method (void)
|
||||||
|
{
|
||||||
|
enum flt_eval_method implicit
|
||||||
|
= targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
|
||||||
|
|
||||||
|
enum excess_precision_type flag_type
|
||||||
|
= (flag_excess_precision_cmdline == EXCESS_PRECISION_STANDARD
|
||||||
|
? EXCESS_PRECISION_TYPE_STANDARD
|
||||||
|
: EXCESS_PRECISION_TYPE_FAST);
|
||||||
|
|
||||||
|
enum flt_eval_method requested
|
||||||
|
= targetm.c.excess_precision (flag_type);
|
||||||
|
|
||||||
|
return excess_precision_mode_join (implicit, requested);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* As c_cpp_ts18661_flt_eval_method, but clamps the expected values to
|
||||||
|
those that were permitted by C11. That is to say, eliminates
|
||||||
|
FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16. */
|
||||||
|
|
||||||
|
static enum flt_eval_method
|
||||||
|
c_c11_flt_eval_method (void)
|
||||||
|
{
|
||||||
|
return excess_precision_mode_join (c_ts18661_flt_eval_method (),
|
||||||
|
FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the value that should be set for FLT_EVAL_METHOD.
|
||||||
|
MAYBE_C11_ONLY_P is TRUE if we should check
|
||||||
|
FLAG_PERMITTED_EVAL_METHODS as to whether we should limit the possible
|
||||||
|
values we can return to those from C99/C11, and FALSE otherwise.
|
||||||
|
See the comments on c_ts18661_flt_eval_method for what value we choose
|
||||||
|
to set here. */
|
||||||
|
|
||||||
|
int
|
||||||
|
c_flt_eval_method (bool maybe_c11_only_p)
|
||||||
|
{
|
||||||
|
if (maybe_c11_only_p
|
||||||
|
&& flag_permitted_flt_eval_methods
|
||||||
|
== PERMITTED_FLT_EVAL_METHODS_C11)
|
||||||
|
return c_c11_flt_eval_method ();
|
||||||
|
else
|
||||||
|
return c_ts18661_flt_eval_method ();
|
||||||
|
}
|
||||||
|
|
||||||
#include "gt-c-family-c-common.h"
|
#include "gt-c-family-c-common.h"
|
||||||
|
|
|
@ -1546,6 +1546,11 @@ extern int tm_attr_to_mask (tree);
|
||||||
extern tree tm_mask_to_attr (int);
|
extern tree tm_mask_to_attr (int);
|
||||||
extern tree find_tm_attribute (tree);
|
extern tree find_tm_attribute (tree);
|
||||||
|
|
||||||
|
extern enum flt_eval_method
|
||||||
|
excess_precision_mode_join (enum flt_eval_method, enum flt_eval_method);
|
||||||
|
|
||||||
|
extern int c_flt_eval_method (bool ts18661_p);
|
||||||
|
|
||||||
#if CHECKING_P
|
#if CHECKING_P
|
||||||
namespace selftest {
|
namespace selftest {
|
||||||
extern void c_format_c_tests (void);
|
extern void c_format_c_tests (void);
|
||||||
|
|
|
@ -728,6 +728,31 @@ cpp_atomic_builtins (cpp_reader *pfile)
|
||||||
(have_swap[psize]? 2 : 1));
|
(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. */
|
/* Return the value for __GCC_IEC_559. */
|
||||||
static int
|
static int
|
||||||
cpp_iec_559_value (void)
|
cpp_iec_559_value (void)
|
||||||
|
@ -770,16 +795,17 @@ cpp_iec_559_value (void)
|
||||||
|| !dfmt->has_signed_zero)
|
|| !dfmt->has_signed_zero)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
/* In strict C standards conformance mode, consider unpredictable
|
/* In strict C standards conformance mode, consider a back-end providing
|
||||||
excess precision to mean lack of IEEE 754 support. The same
|
more implicit excess precision than the explicit excess precision
|
||||||
applies to unpredictable contraction. For C++, and outside
|
the front-end options would require to mean a lack of IEEE 754
|
||||||
strict conformance mode, do not consider these options to mean
|
support. For C++, and outside strict conformance mode, do not consider
|
||||||
lack of IEEE 754 support. */
|
this to mean a lack of IEEE 754 support. */
|
||||||
|
|
||||||
if (flag_iso
|
if (flag_iso
|
||||||
&& !c_dialect_cxx ()
|
&& !c_dialect_cxx ()
|
||||||
&& TARGET_FLT_EVAL_METHOD != 0
|
&& !c_cpp_flt_eval_method_iec_559 ())
|
||||||
&& flag_excess_precision_cmdline != EXCESS_PRECISION_STANDARD)
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
if (flag_iso
|
if (flag_iso
|
||||||
&& !c_dialect_cxx ()
|
&& !c_dialect_cxx ()
|
||||||
&& flag_fp_contract_mode == FP_CONTRACT_FAST)
|
&& 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",
|
builtin_define_with_int_value ("__GCC_IEC_559_COMPLEX",
|
||||||
cpp_iec_559_complex_value ());
|
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__",
|
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. */
|
/* And decfloat.h needs this. */
|
||||||
builtin_define_with_int_value ("__DEC_EVAL_METHOD__",
|
builtin_define_with_int_value ("__DEC_EVAL_METHOD__",
|
||||||
|
@ -1188,25 +1227,38 @@ c_cpp_builtins (cpp_reader *pfile)
|
||||||
gcc_assert (found_suffix);
|
gcc_assert (found_suffix);
|
||||||
}
|
}
|
||||||
builtin_define_with_value (macro_name, suffix, 0);
|
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;
|
bool excess_precision = false;
|
||||||
if (TARGET_FLT_EVAL_METHOD != 0
|
machine_mode float16_type_mode = (float16_type_node
|
||||||
&& mode != TYPE_MODE (long_double_type_node)
|
? TYPE_MODE (float16_type_node)
|
||||||
&& (mode == TYPE_MODE (float_type_node)
|
: VOIDmode);
|
||||||
|| mode == TYPE_MODE (double_type_node)))
|
switch (targetm.c.excess_precision
|
||||||
switch (TARGET_FLT_EVAL_METHOD)
|
(EXCESS_PRECISION_TYPE_IMPLICIT))
|
||||||
{
|
{
|
||||||
case -1:
|
case FLT_EVAL_METHOD_UNPREDICTABLE:
|
||||||
case 2:
|
case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
|
||||||
excess_precision = true;
|
excess_precision = (mode == float16_type_mode
|
||||||
break;
|
|| mode == TYPE_MODE (float_type_node)
|
||||||
|
|| mode == TYPE_MODE (double_type_node));
|
||||||
|
break;
|
||||||
|
|
||||||
case 1:
|
case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
|
||||||
excess_precision = mode == TYPE_MODE (float_type_node);
|
excess_precision = (mode == float16_type_mode
|
||||||
break;
|
|| mode == TYPE_MODE (float_type_node));
|
||||||
|
break;
|
||||||
default:
|
case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
|
||||||
gcc_unreachable ();
|
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)
|
macro_name = (char *) alloca (strlen (name)
|
||||||
+ sizeof ("__LIBGCC__EXCESS_"
|
+ sizeof ("__LIBGCC__EXCESS_"
|
||||||
"PRECISION__"));
|
"PRECISION__"));
|
||||||
|
|
|
@ -8987,15 +8987,14 @@ them to store all pertinent intermediate computations into variables.
|
||||||
@item -fexcess-precision=@var{style}
|
@item -fexcess-precision=@var{style}
|
||||||
@opindex fexcess-precision
|
@opindex fexcess-precision
|
||||||
This option allows further control over excess precision on machines
|
This option allows further control over excess precision on machines
|
||||||
where floating-point registers have more precision than the IEEE
|
where floating-point operations occur in a format with more precision or
|
||||||
@code{float} and @code{double} types and the processor does not
|
range than the IEEE standard and interchange floating-point types. By
|
||||||
support operations rounding to those types. By default,
|
default, @option{-fexcess-precision=fast} is in effect; this means that
|
||||||
@option{-fexcess-precision=fast} is in effect; this means that
|
operations may be carried out in a wider precision than the types specified
|
||||||
operations are carried out in the precision of the registers and that
|
in the source if that would result in faster code, and it is unpredictable
|
||||||
it is unpredictable when rounding to the types specified in the source
|
when rounding to the types specified in the source code takes place.
|
||||||
code takes place. When compiling C, if
|
When compiling C, if @option{-fexcess-precision=standard} is specified then
|
||||||
@option{-fexcess-precision=standard} is specified then excess
|
excess precision follows the rules specified in ISO C99; in particular,
|
||||||
precision follows the rules specified in ISO C99; in particular,
|
|
||||||
both casts and assignments cause values to be rounded to their
|
both casts and assignments cause values to be rounded to their
|
||||||
semantic types (whereas @option{-ffloat-store} only affects
|
semantic types (whereas @option{-ffloat-store} only affects
|
||||||
assignments). This option is enabled by default for C if a strict
|
assignments). This option is enabled by default for C if a strict
|
||||||
|
|
|
@ -129,21 +129,73 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
|
||||||
#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \
|
#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \
|
||||||
|| (defined (__cplusplus) && __cplusplus >= 201103L)
|
|| (defined (__cplusplus) && __cplusplus >= 201103L)
|
||||||
/* The floating-point expression evaluation method.
|
/* The floating-point expression evaluation method. The precise
|
||||||
-1 indeterminate
|
definitions of these values are generalised to include support for
|
||||||
0 evaluate all operations and constants just to the range and
|
the interchange and extended types defined in ISO/IEC TS 18661-3.
|
||||||
precision of the type
|
Prior to this (for C99/C11) the definitions were:
|
||||||
1 evaluate operations and constants of type float and double
|
|
||||||
to the range and precision of the double type, evaluate
|
-1 indeterminate
|
||||||
long double operations and constants to the range and
|
0 evaluate all operations and constants just to the range and
|
||||||
precision of the long double type
|
precision of the type
|
||||||
2 evaluate all operations and constants to the range and
|
1 evaluate operations and constants of type float and double
|
||||||
precision of the long double type
|
to the range and precision of the double type, evaluate
|
||||||
|
long double operations and constants to the range and
|
||||||
|
precision of the long double type
|
||||||
|
2 evaluate all operations and constants to the range and
|
||||||
|
precision of the long double type
|
||||||
|
|
||||||
|
The TS 18661-3 definitions are:
|
||||||
|
|
||||||
|
-1 indeterminate
|
||||||
|
0 evaluate all operations and constants, whose semantic type has
|
||||||
|
at most the range and precision of float, to the range and
|
||||||
|
precision of float; evaluate all other operations and constants
|
||||||
|
to the range and precision of the semantic type.
|
||||||
|
1 evaluate all operations and constants, whose semantic type has
|
||||||
|
at most the range and precision of double, to the range and
|
||||||
|
precision of double; evaluate all other operations and constants
|
||||||
|
to the range and precision of the semantic type.
|
||||||
|
2 evaluate all operations and constants, whose semantic type has
|
||||||
|
at most the range and precision of long double, to the range and
|
||||||
|
precision of long double; evaluate all other operations and
|
||||||
|
constants to the range and precision of the semantic type.
|
||||||
|
N where _FloatN is a supported interchange floating type
|
||||||
|
evaluate all operations and constants, whose semantic type has
|
||||||
|
at most the range and precision of the _FloatN type, to the
|
||||||
|
range and precision of the _FloatN type; evaluate all other
|
||||||
|
operations and constants to the range and precision of the
|
||||||
|
semantic type.
|
||||||
|
N + 1, where _FloatNx is a supported extended floating type
|
||||||
|
evaluate operations and constants, whose semantic type has at
|
||||||
|
most the range and precision of the _FloatNx type, to the range
|
||||||
|
and precision of the _FloatNx type; evaluate all other
|
||||||
|
operations and constants to the range and precision of the
|
||||||
|
semantic type.
|
||||||
|
|
||||||
|
The compiler predefines two macros:
|
||||||
|
|
||||||
|
__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.
|
||||||
|
|
||||||
|
Here we want to use __FLT_EVAL_METHOD__, unless
|
||||||
|
__STDC_WANT_IEC_60559_TYPES_EXT__ is defined, in which case the user
|
||||||
|
is specifically asking for the ISO/IEC TS 18661-3 types, so we use
|
||||||
|
__FLT_EVAL_METHOD_TS_18661_3__.
|
||||||
|
|
||||||
??? This ought to change with the setting of the fp control word;
|
??? This ought to change with the setting of the fp control word;
|
||||||
the value provided by the compiler assumes the widest setting. */
|
the value provided by the compiler assumes the widest setting. */
|
||||||
#undef FLT_EVAL_METHOD
|
#undef FLT_EVAL_METHOD
|
||||||
|
#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||||
|
#define FLT_EVAL_METHOD __FLT_EVAL_METHOD_TS_18661_3__
|
||||||
|
#else
|
||||||
#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
|
#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Number of decimal digits, n, such that any floating-point number in the
|
/* Number of decimal digits, n, such that any floating-point number in the
|
||||||
widest supported floating type with pmax radix b digits can be rounded
|
widest supported floating type with pmax radix b digits can be rounded
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2016-11-23 James Greenhalgh <james.greenhalgh@arm.com>
|
||||||
|
|
||||||
|
* gcc.dg/fpermitted-flt-eval-methods_3.c: New.
|
||||||
|
* gcc.dg/fpermitted-flt-eval-methods_4.c: Likewise.
|
||||||
|
|
||||||
2016-11-23 James Greenhalgh <james.greenhalgh@arm.com>
|
2016-11-23 James Greenhalgh <james.greenhalgh@arm.com>
|
||||||
|
|
||||||
* gcc.dg/fpermitted-flt-eval-methods_1.c: New.
|
* gcc.dg/fpermitted-flt-eval-methods_1.c: New.
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
/* { dg-do run } */
|
||||||
|
/* { dg-options "-std=c11" } */
|
||||||
|
|
||||||
|
/* Test that when compiling with -std=c11, we only see the C99/C11 values
|
||||||
|
for FLT_EVAL_METHOD. */
|
||||||
|
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
|
int main (int argc, char** argv)
|
||||||
|
{
|
||||||
|
switch (FLT_EVAL_METHOD)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case -1:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* { dg-do run } */
|
||||||
|
/* { dg-options "-std=c11" } */
|
||||||
|
|
||||||
|
/* Test that when compiling with -std=c11 and defining
|
||||||
|
__STDC_WANT_IEC_60559_TYPES_EXT__, we only see the ISO/IEC TS
|
||||||
|
18661-3 values for FLT_EVAL_METHOD. */
|
||||||
|
|
||||||
|
#define __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||||
|
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
|
int main (int argc, char** argv)
|
||||||
|
{
|
||||||
|
switch (__FLT_EVAL_METHOD__)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 16:
|
||||||
|
case -1:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
36
gcc/toplev.c
36
gcc/toplev.c
|
@ -1680,41 +1680,17 @@ backend_init (void)
|
||||||
init_regs ();
|
init_regs ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize excess precision settings. */
|
/* Initialize excess precision settings.
|
||||||
|
|
||||||
|
We have no need to modify anything here, just keep track of what the
|
||||||
|
user requested. We'll figure out any appropriate relaxations
|
||||||
|
later. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_excess_precision (void)
|
init_excess_precision (void)
|
||||||
{
|
{
|
||||||
/* Adjust excess precision handling based on the target options. If
|
|
||||||
the front end cannot handle it, flag_excess_precision_cmdline
|
|
||||||
will already have been set accordingly in the post_options
|
|
||||||
hook. */
|
|
||||||
gcc_assert (flag_excess_precision_cmdline != EXCESS_PRECISION_DEFAULT);
|
gcc_assert (flag_excess_precision_cmdline != EXCESS_PRECISION_DEFAULT);
|
||||||
flag_excess_precision = flag_excess_precision_cmdline;
|
flag_excess_precision = flag_excess_precision_cmdline;
|
||||||
if (flag_unsafe_math_optimizations)
|
|
||||||
flag_excess_precision = EXCESS_PRECISION_FAST;
|
|
||||||
if (flag_excess_precision == EXCESS_PRECISION_STANDARD)
|
|
||||||
{
|
|
||||||
int flt_eval_method = TARGET_FLT_EVAL_METHOD;
|
|
||||||
switch (flt_eval_method)
|
|
||||||
{
|
|
||||||
case -1:
|
|
||||||
case 0:
|
|
||||||
/* Either the target acts unpredictably (-1) or has all the
|
|
||||||
operations required not to have excess precision (0). */
|
|
||||||
flag_excess_precision = EXCESS_PRECISION_FAST;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
case 2:
|
|
||||||
/* In these cases, predictable excess precision makes
|
|
||||||
sense. */
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Any other implementation-defined FLT_EVAL_METHOD values
|
|
||||||
require the compiler to handle the associated excess
|
|
||||||
precision rules in excess_precision_type. */
|
|
||||||
gcc_unreachable ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize things that are both lang-dependent and target-dependent.
|
/* Initialize things that are both lang-dependent and target-dependent.
|
||||||
|
|
133
gcc/tree.c
133
gcc/tree.c
|
@ -8855,50 +8855,99 @@ build_complex_type (tree component_type, bool named)
|
||||||
tree
|
tree
|
||||||
excess_precision_type (tree type)
|
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;
|
case REAL_TYPE:
|
||||||
switch (TREE_CODE (type))
|
{
|
||||||
{
|
machine_mode type_mode = TYPE_MODE (type);
|
||||||
case REAL_TYPE:
|
switch (target_flt_eval_method)
|
||||||
switch (flt_eval_method)
|
{
|
||||||
{
|
case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
|
||||||
case 1:
|
if (type_mode == float16_type_mode)
|
||||||
if (TYPE_MODE (type) == TYPE_MODE (float_type_node))
|
return float_type_node;
|
||||||
return double_type_node;
|
break;
|
||||||
break;
|
case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
|
||||||
case 2:
|
if (type_mode == float16_type_mode
|
||||||
if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
|
|| type_mode == float_type_mode)
|
||||||
|| TYPE_MODE (type) == TYPE_MODE (double_type_node))
|
return double_type_node;
|
||||||
return long_double_type_node;
|
break;
|
||||||
break;
|
case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
|
||||||
default:
|
if (type_mode == float16_type_mode
|
||||||
gcc_unreachable ();
|
|| type_mode == float_type_mode
|
||||||
}
|
|| type_mode == double_type_mode)
|
||||||
break;
|
return long_double_type_node;
|
||||||
case COMPLEX_TYPE:
|
break;
|
||||||
if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
|
default:
|
||||||
return NULL_TREE;
|
gcc_unreachable ();
|
||||||
switch (flt_eval_method)
|
}
|
||||||
{
|
break;
|
||||||
case 1:
|
}
|
||||||
if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node))
|
case COMPLEX_TYPE:
|
||||||
return complex_double_type_node;
|
{
|
||||||
break;
|
if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
|
||||||
case 2:
|
return NULL_TREE;
|
||||||
if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node)
|
machine_mode type_mode = TYPE_MODE (TREE_TYPE (type));
|
||||||
|| (TYPE_MODE (TREE_TYPE (type))
|
switch (target_flt_eval_method)
|
||||||
== TYPE_MODE (double_type_node)))
|
{
|
||||||
return complex_long_double_type_node;
|
case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
|
||||||
break;
|
if (type_mode == float16_type_mode)
|
||||||
default:
|
return complex_float_type_node;
|
||||||
gcc_unreachable ();
|
break;
|
||||||
}
|
case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
|
||||||
break;
|
if (type_mode == float16_type_mode
|
||||||
default:
|
|| type_mode == float_type_mode)
|
||||||
break;
|
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;
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue