377 lines
12 KiB
Diff
377 lines
12 KiB
Diff
|
|
diff -Nurp a/gcc/common.opt b/gcc/common.opt
|
||
|
|
--- a/gcc/common.opt 2021-02-18 21:22:07.216000000 +0800
|
||
|
|
+++ b/gcc/common.opt 2021-02-19 16:04:17.876000000 +0800
|
||
|
|
@@ -1506,6 +1506,32 @@ ffp-int-builtin-inexact
|
||
|
|
Common Report Var(flag_fp_int_builtin_inexact) Init(1) Optimization
|
||
|
|
Allow built-in functions ceil, floor, round, trunc to raise \"inexact\" exceptions.
|
||
|
|
|
||
|
|
+fftz
|
||
|
|
+Common Report Var(flag_ftz) Optimization
|
||
|
|
+Control fpcr register for flush to zero.
|
||
|
|
+
|
||
|
|
+fp-model=
|
||
|
|
+Common Joined RejectNegative Enum(fp_model) Var(flag_fp_model) Init(FP_MODEL_NORMAL) Optimization
|
||
|
|
+-fp-model=[normal|fast|precise|except|strict] Perform floating-point precision control.
|
||
|
|
+
|
||
|
|
+Enum
|
||
|
|
+Name(fp_model) Type(enum fp_model) UnknownError(unknown floating point precision model %qs)
|
||
|
|
+
|
||
|
|
+EnumValue
|
||
|
|
+Enum(fp_model) String(normal) Value(FP_MODEL_NORMAL)
|
||
|
|
+
|
||
|
|
+EnumValue
|
||
|
|
+Enum(fp_model) String(fast) Value(FP_MODEL_FAST)
|
||
|
|
+
|
||
|
|
+EnumValue
|
||
|
|
+Enum(fp_model) String(precise) Value(FP_MODEL_PRECISE)
|
||
|
|
+
|
||
|
|
+EnumValue
|
||
|
|
+Enum(fp_model) String(except) Value(FP_MODEL_EXCEPT)
|
||
|
|
+
|
||
|
|
+EnumValue
|
||
|
|
+Enum(fp_model) String(strict) Value(FP_MODEL_STRICT)
|
||
|
|
+
|
||
|
|
; Nonzero means don't put addresses of constant functions in registers.
|
||
|
|
; Used for compiling the Unix kernel, where strange substitutions are
|
||
|
|
; done on the assembly output.
|
||
|
|
diff -Nurp a/gcc/config/aarch64/aarch64-linux.h b/gcc/config/aarch64/aarch64-linux.h
|
||
|
|
--- a/gcc/config/aarch64/aarch64-linux.h 2021-02-18 21:22:07.220000000 +0800
|
||
|
|
+++ b/gcc/config/aarch64/aarch64-linux.h 2021-02-18 21:23:55.932000000 +0800
|
||
|
|
@@ -50,7 +50,8 @@
|
||
|
|
#define LINK_SPEC LINUX_TARGET_LINK_SPEC AARCH64_ERRATA_LINK_SPEC
|
||
|
|
|
||
|
|
#define GNU_USER_TARGET_MATHFILE_SPEC \
|
||
|
|
- "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s}"
|
||
|
|
+ "%{Ofast|ffast-math|funsafe-math-optimizations|fp-model=fast|fftz:\
|
||
|
|
+ %{!fno-ftz:crtfastmath.o%s}}"
|
||
|
|
|
||
|
|
#undef ENDFILE_SPEC
|
||
|
|
#define ENDFILE_SPEC \
|
||
|
|
diff -Nurp a/gcc/flag-types.h b/gcc/flag-types.h
|
||
|
|
--- a/gcc/flag-types.h 2020-03-12 19:07:21.000000000 +0800
|
||
|
|
+++ b/gcc/flag-types.h 2021-02-18 21:23:55.932000000 +0800
|
||
|
|
@@ -207,6 +207,15 @@ enum fp_contract_mode {
|
||
|
|
FP_CONTRACT_FAST = 2
|
||
|
|
};
|
||
|
|
|
||
|
|
+/* Floating-point precision mode. */
|
||
|
|
+enum fp_model {
|
||
|
|
+ FP_MODEL_NORMAL = 0,
|
||
|
|
+ FP_MODEL_FAST = 1,
|
||
|
|
+ FP_MODEL_PRECISE = 2,
|
||
|
|
+ FP_MODEL_EXCEPT = 3,
|
||
|
|
+ FP_MODEL_STRICT = 4
|
||
|
|
+};
|
||
|
|
+
|
||
|
|
/* Scalar storage order kind. */
|
||
|
|
enum scalar_storage_order_kind {
|
||
|
|
SSO_NATIVE = 0,
|
||
|
|
diff -Nurp a/gcc/fortran/options.c b/gcc/fortran/options.c
|
||
|
|
--- a/gcc/fortran/options.c 2020-03-12 19:07:21.000000000 +0800
|
||
|
|
+++ b/gcc/fortran/options.c 2021-02-18 21:23:55.932000000 +0800
|
||
|
|
@@ -247,6 +247,7 @@ form_from_filename (const char *filename
|
||
|
|
return f_form;
|
||
|
|
}
|
||
|
|
|
||
|
|
+static void gfc_handle_fpe_option (const char *arg, bool trap);
|
||
|
|
|
||
|
|
/* Finalize commandline options. */
|
||
|
|
|
||
|
|
@@ -274,6 +275,13 @@ gfc_post_options (const char **pfilename
|
||
|
|
if (flag_protect_parens == -1)
|
||
|
|
flag_protect_parens = !optimize_fast;
|
||
|
|
|
||
|
|
+ /* If fp-model=precise/strict, turn on all ffpe-trap and ffpe-summary. */
|
||
|
|
+ if (flag_fp_model == FP_MODEL_EXCEPT || flag_fp_model == FP_MODEL_STRICT)
|
||
|
|
+ {
|
||
|
|
+ gfc_handle_fpe_option ("all", false);
|
||
|
|
+ gfc_handle_fpe_option ("invalid,zero,overflow,underflow", true);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
/* -Ofast sets implies -fstack-arrays unless an explicit size is set for
|
||
|
|
stack arrays. */
|
||
|
|
if (flag_stack_arrays == -1 && flag_max_stack_var_size == -2)
|
||
|
|
diff -Nurp a/gcc/opts.c b/gcc/opts.c
|
||
|
|
--- a/gcc/opts.c 2021-02-18 21:22:07.424000000 +0800
|
||
|
|
+++ b/gcc/opts.c 2021-02-19 16:00:08.628000000 +0800
|
||
|
|
@@ -196,6 +196,7 @@ static void set_debug_level (enum debug_
|
||
|
|
struct gcc_options *opts_set,
|
||
|
|
location_t loc);
|
||
|
|
static void set_fast_math_flags (struct gcc_options *opts, int set);
|
||
|
|
+static void set_fp_model_flags (struct gcc_options *opts, int set);
|
||
|
|
static void decode_d_option (const char *arg, struct gcc_options *opts,
|
||
|
|
location_t loc, diagnostic_context *dc);
|
||
|
|
static void set_unsafe_math_optimizations_flags (struct gcc_options *opts,
|
||
|
|
@@ -2433,6 +2434,10 @@ common_handle_option (struct gcc_options
|
||
|
|
set_fast_math_flags (opts, value);
|
||
|
|
break;
|
||
|
|
|
||
|
|
+ case OPT_fp_model_:
|
||
|
|
+ set_fp_model_flags (opts, value);
|
||
|
|
+ break;
|
||
|
|
+
|
||
|
|
case OPT_funsafe_math_optimizations:
|
||
|
|
set_unsafe_math_optimizations_flags (opts, value);
|
||
|
|
break;
|
||
|
|
@@ -2905,6 +2910,69 @@ set_fast_math_flags (struct gcc_options
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
+/* Handle fp-model options. */
|
||
|
|
+static void
|
||
|
|
+set_fp_model_flags (struct gcc_options *opts, int set)
|
||
|
|
+{
|
||
|
|
+ enum fp_model model = (enum fp_model) set;
|
||
|
|
+ switch (model)
|
||
|
|
+ {
|
||
|
|
+ case FP_MODEL_FAST:
|
||
|
|
+ /* Equivalent to open ffast-math. */
|
||
|
|
+ set_fast_math_flags (opts, 1);
|
||
|
|
+ break;
|
||
|
|
+
|
||
|
|
+ case FP_MODEL_PRECISE:
|
||
|
|
+ /* Equivalent to close ffast-math. */
|
||
|
|
+ set_fast_math_flags (opts, 0);
|
||
|
|
+ /* Turn on -frounding-math -fsignaling-nans. */
|
||
|
|
+ if (!opts->frontend_set_flag_signaling_nans)
|
||
|
|
+ opts->x_flag_signaling_nans = 1;
|
||
|
|
+ if (!opts->frontend_set_flag_rounding_math)
|
||
|
|
+ opts->x_flag_rounding_math = 1;
|
||
|
|
+ opts->x_flag_expensive_optimizations = 0;
|
||
|
|
+ opts->x_flag_code_hoisting = 0;
|
||
|
|
+ opts->x_flag_predictive_commoning = 0;
|
||
|
|
+ opts->x_flag_fp_contract_mode = FP_CONTRACT_OFF;
|
||
|
|
+ break;
|
||
|
|
+
|
||
|
|
+ case FP_MODEL_EXCEPT:
|
||
|
|
+ if (!opts->frontend_set_flag_signaling_nans)
|
||
|
|
+ opts->x_flag_signaling_nans = 1;
|
||
|
|
+ if (!opts->frontend_set_flag_errno_math)
|
||
|
|
+ opts->x_flag_errno_math = 1;
|
||
|
|
+ if (!opts->frontend_set_flag_trapping_math)
|
||
|
|
+ opts->x_flag_trapping_math = 1;
|
||
|
|
+ opts->x_flag_fp_int_builtin_inexact = 1;
|
||
|
|
+ /* Also turn on ffpe-trap in fortran. */
|
||
|
|
+ break;
|
||
|
|
+
|
||
|
|
+ case FP_MODEL_STRICT:
|
||
|
|
+ /* Turn on both precise and except. */
|
||
|
|
+ if (!opts->frontend_set_flag_signaling_nans)
|
||
|
|
+ opts->x_flag_signaling_nans = 1;
|
||
|
|
+ if (!opts->frontend_set_flag_rounding_math)
|
||
|
|
+ opts->x_flag_rounding_math = 1;
|
||
|
|
+ opts->x_flag_expensive_optimizations = 0;
|
||
|
|
+ opts->x_flag_code_hoisting = 0;
|
||
|
|
+ opts->x_flag_predictive_commoning = 0;
|
||
|
|
+ if (!opts->frontend_set_flag_errno_math)
|
||
|
|
+ opts->x_flag_errno_math = 1;
|
||
|
|
+ if (!opts->frontend_set_flag_trapping_math)
|
||
|
|
+ opts->x_flag_trapping_math = 1;
|
||
|
|
+ opts->x_flag_fp_int_builtin_inexact = 1;
|
||
|
|
+ opts->x_flag_fp_contract_mode = FP_CONTRACT_OFF;
|
||
|
|
+ break;
|
||
|
|
+
|
||
|
|
+ case FP_MODEL_NORMAL:
|
||
|
|
+ /* Do nothing. */
|
||
|
|
+ break;
|
||
|
|
+
|
||
|
|
+ default:
|
||
|
|
+ gcc_unreachable ();
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
/* When -funsafe-math-optimizations is set the following
|
||
|
|
flags are set as well. */
|
||
|
|
static void
|
||
|
|
diff -Nurp a/gcc/opts-common.c b/gcc/opts-common.c
|
||
|
|
--- a/gcc/opts-common.c 2020-03-12 19:07:21.000000000 +0800
|
||
|
|
+++ b/gcc/opts-common.c 2021-02-19 09:49:18.880000000 +0800
|
||
|
|
@@ -26,7 +26,8 @@ along with GCC; see the file COPYING3.
|
||
|
|
#include "diagnostic.h"
|
||
|
|
#include "spellcheck.h"
|
||
|
|
|
||
|
|
-static void prune_options (struct cl_decoded_option **, unsigned int *);
|
||
|
|
+static void prune_options (struct cl_decoded_option **, unsigned int *,
|
||
|
|
+ unsigned int);
|
||
|
|
|
||
|
|
/* An option that is undocumented, that takes a joined argument, and
|
||
|
|
that doesn't fit any of the classes of uses (language/common,
|
||
|
|
@@ -968,7 +969,7 @@ decode_cmdline_options_to_array (unsigne
|
||
|
|
|
||
|
|
*decoded_options = opt_array;
|
||
|
|
*decoded_options_count = num_decoded_options;
|
||
|
|
- prune_options (decoded_options, decoded_options_count);
|
||
|
|
+ prune_options (decoded_options, decoded_options_count, lang_mask);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Return true if NEXT_OPT_IDX cancels OPT_IDX. Return false if the
|
||
|
|
@@ -989,11 +990,108 @@ cancel_option (int opt_idx, int next_opt
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
+/* Check whether opt_idx exists in decoded_options array bewteen index
|
||
|
|
+ start and end. If found, return its index in decoded_options,
|
||
|
|
+ else return end. */
|
||
|
|
+static unsigned int
|
||
|
|
+find_opt_idx (struct cl_decoded_option *decoded_options,
|
||
|
|
+ unsigned int decoded_options_count,
|
||
|
|
+ unsigned int start, unsigned int end, unsigned int opt_idx)
|
||
|
|
+{
|
||
|
|
+ gcc_assert (end <= decoded_options_count);
|
||
|
|
+ gcc_assert (opt_idx < cl_options_count);
|
||
|
|
+ unsigned int k;
|
||
|
|
+ for (k = start; k < end; k++)
|
||
|
|
+ {
|
||
|
|
+ if (decoded_options[k].opt_index == opt_idx)
|
||
|
|
+ {
|
||
|
|
+ return k;
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ return k;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+/* remove the opt_index element from decoded_options array. */
|
||
|
|
+static unsigned int
|
||
|
|
+remove_option (struct cl_decoded_option *decoded_options,
|
||
|
|
+ unsigned int decoded_options_count,
|
||
|
|
+ unsigned int opt_index)
|
||
|
|
+{
|
||
|
|
+ gcc_assert (opt_index < decoded_options_count);
|
||
|
|
+ unsigned int i;
|
||
|
|
+ for (i = opt_index; i < decoded_options_count - 1; i++)
|
||
|
|
+ {
|
||
|
|
+ decoded_options[i] = decoded_options[i + 1];
|
||
|
|
+ }
|
||
|
|
+ return decoded_options_count - 1;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+/* Handle the priority between fp-model, Ofast, and
|
||
|
|
+ ffast-math. */
|
||
|
|
+static unsigned int
|
||
|
|
+handle_fp_model_driver (struct cl_decoded_option *decoded_options,
|
||
|
|
+ unsigned int decoded_options_count,
|
||
|
|
+ unsigned int fp_model_index,
|
||
|
|
+ unsigned int lang_mask)
|
||
|
|
+{
|
||
|
|
+ struct cl_decoded_option fp_model_opt = decoded_options[fp_model_index];
|
||
|
|
+ enum fp_model model = (enum fp_model) fp_model_opt.value;
|
||
|
|
+ if (model == FP_MODEL_PRECISE || model == FP_MODEL_STRICT)
|
||
|
|
+ {
|
||
|
|
+ /* If found Ofast, override Ofast with O3. */
|
||
|
|
+ unsigned int Ofast_index;
|
||
|
|
+ Ofast_index = find_opt_idx (decoded_options, decoded_options_count,
|
||
|
|
+ 0, decoded_options_count, OPT_Ofast);
|
||
|
|
+ while (Ofast_index != decoded_options_count)
|
||
|
|
+ {
|
||
|
|
+ const char *tmp_argv = "-O3";
|
||
|
|
+ decode_cmdline_option (&tmp_argv, lang_mask,
|
||
|
|
+ &decoded_options[Ofast_index]);
|
||
|
|
+ warning (0, "'-Ofast' is degraded to '-O3' due to %qs",
|
||
|
|
+ fp_model_opt.orig_option_with_args_text);
|
||
|
|
+ Ofast_index = find_opt_idx (decoded_options, decoded_options_count,
|
||
|
|
+ 0, decoded_options_count, OPT_Ofast);
|
||
|
|
+ }
|
||
|
|
+ /* If found ffast-math before fp-model=precise/strict
|
||
|
|
+ it, cancel it. */
|
||
|
|
+ unsigned int ffast_math_index;
|
||
|
|
+ ffast_math_index
|
||
|
|
+ = find_opt_idx (decoded_options, decoded_options_count, 0,
|
||
|
|
+ fp_model_index, OPT_ffast_math);
|
||
|
|
+ if (ffast_math_index != fp_model_index)
|
||
|
|
+ {
|
||
|
|
+ decoded_options_count
|
||
|
|
+ = remove_option (decoded_options, decoded_options_count,
|
||
|
|
+ ffast_math_index);
|
||
|
|
+ warning (0, "'-ffast-math' before %qs is canceled",
|
||
|
|
+ fp_model_opt.orig_option_with_args_text);
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ if (model == FP_MODEL_FAST)
|
||
|
|
+ {
|
||
|
|
+ /* If found -fno-fast-math after fp-model=fast, cancel this one. */
|
||
|
|
+ unsigned int fno_fast_math_index;
|
||
|
|
+ fno_fast_math_index
|
||
|
|
+ = find_opt_idx (decoded_options, decoded_options_count, fp_model_index,
|
||
|
|
+ decoded_options_count, OPT_ffast_math);
|
||
|
|
+ if (fno_fast_math_index != decoded_options_count
|
||
|
|
+ && decoded_options[fno_fast_math_index].value == 0)
|
||
|
|
+ {
|
||
|
|
+ decoded_options_count
|
||
|
|
+ = remove_option (decoded_options, decoded_options_count,
|
||
|
|
+ fp_model_index);
|
||
|
|
+ warning (0, "'-fp-model=fast' before '-fno-fast-math' is canceled");
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ return decoded_options_count;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
/* Filter out options canceled by the ones after them. */
|
||
|
|
|
||
|
|
static void
|
||
|
|
prune_options (struct cl_decoded_option **decoded_options,
|
||
|
|
- unsigned int *decoded_options_count)
|
||
|
|
+ unsigned int *decoded_options_count,
|
||
|
|
+ unsigned int lang_mask)
|
||
|
|
{
|
||
|
|
unsigned int old_decoded_options_count = *decoded_options_count;
|
||
|
|
struct cl_decoded_option *old_decoded_options = *decoded_options;
|
||
|
|
@@ -1005,6 +1103,8 @@ prune_options (struct cl_decoded_option
|
||
|
|
unsigned int fdiagnostics_color_idx = 0;
|
||
|
|
|
||
|
|
/* Remove arguments which are negated by others after them. */
|
||
|
|
+
|
||
|
|
+ unsigned int fp_model_index = old_decoded_options_count;
|
||
|
|
new_decoded_options_count = 0;
|
||
|
|
for (i = 0; i < old_decoded_options_count; i++)
|
||
|
|
{
|
||
|
|
@@ -1028,6 +1128,34 @@ prune_options (struct cl_decoded_option
|
||
|
|
fdiagnostics_color_idx = i;
|
||
|
|
continue;
|
||
|
|
|
||
|
|
+ case OPT_fp_model_:
|
||
|
|
+ /* Only the last fp-model option will take effect. */
|
||
|
|
+ unsigned int next_fp_model_idx;
|
||
|
|
+ next_fp_model_idx = find_opt_idx (old_decoded_options,
|
||
|
|
+ old_decoded_options_count,
|
||
|
|
+ i + 1,
|
||
|
|
+ old_decoded_options_count,
|
||
|
|
+ OPT_fp_model_);
|
||
|
|
+ if (next_fp_model_idx != old_decoded_options_count)
|
||
|
|
+ {
|
||
|
|
+ /* Found more than one fp-model, cancel this one. */
|
||
|
|
+ if (old_decoded_options[i].value
|
||
|
|
+ != old_decoded_options[next_fp_model_idx].value)
|
||
|
|
+ {
|
||
|
|
+ warning (0, "%qs is overrided by %qs",
|
||
|
|
+ old_decoded_options[i].
|
||
|
|
+ orig_option_with_args_text,
|
||
|
|
+ old_decoded_options[next_fp_model_idx].
|
||
|
|
+ orig_option_with_args_text);
|
||
|
|
+ }
|
||
|
|
+ break;
|
||
|
|
+ }
|
||
|
|
+ else
|
||
|
|
+ {
|
||
|
|
+ /* Found the last fp-model option. */
|
||
|
|
+ fp_model_index = new_decoded_options_count;
|
||
|
|
+ }
|
||
|
|
+ /* FALLTHRU. */
|
||
|
|
default:
|
||
|
|
gcc_assert (opt_idx < cl_options_count);
|
||
|
|
option = &cl_options[opt_idx];
|
||
|
|
@@ -1067,6 +1195,14 @@ keep:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
+ if (fp_model_index < new_decoded_options_count)
|
||
|
|
+ {
|
||
|
|
+ new_decoded_options_count
|
||
|
|
+ = handle_fp_model_driver (new_decoded_options,
|
||
|
|
+ new_decoded_options_count,
|
||
|
|
+ fp_model_index,
|
||
|
|
+ lang_mask);
|
||
|
|
+ }
|
||
|
|
|
||
|
|
if (fdiagnostics_color_idx >= 1)
|
||
|
|
{
|