aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/config/i386/i386-options.c39
-rw-r--r--gcc/config/i386/i386.c4
-rw-r--r--gcc/config/i386/i386.h8
-rw-r--r--gcc/config/i386/i386.opt10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr94440-1.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/pr94440-2.c19
6 files changed, 95 insertions, 8 deletions
diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c
index 40714c8..70b5f09 100644
--- a/gcc/config/i386/i386-options.c
+++ b/gcc/config/i386/i386-options.c
@@ -1374,6 +1374,14 @@ ix86_valid_target_attribute_tree (tree fndecl, tree args,
/* Add any builtin functions with the new isa if any. */
ix86_add_new_builtins (opts->x_ix86_isa_flags, opts->x_ix86_isa_flags2);
+ enum excess_precision orig_ix86_excess_precision
+ = opts->x_ix86_excess_precision;
+ bool orig_ix86_unsafe_math_optimizations
+ = opts->x_ix86_unsafe_math_optimizations;
+ opts->x_ix86_excess_precision = opts->x_flag_excess_precision;
+ opts->x_ix86_unsafe_math_optimizations
+ = opts->x_flag_unsafe_math_optimizations;
+
/* Save the current options unless we are validating options for
#pragma. */
t = build_target_option_node (opts, opts_set);
@@ -1382,6 +1390,9 @@ ix86_valid_target_attribute_tree (tree fndecl, tree args,
opts->x_ix86_tune_string = orig_tune_string;
opts_set->x_ix86_fpmath = orig_fpmath_set;
opts_set->x_prefer_vector_width_type = orig_pvw_set;
+ opts->x_ix86_excess_precision = orig_ix86_excess_precision;
+ opts->x_ix86_unsafe_math_optimizations
+ = orig_ix86_unsafe_math_optimizations;
release_options_strings (option_strings);
}
@@ -3019,8 +3030,14 @@ ix86_option_override_internal (bool main_args_p,
/* Save the initial options in case the user does function specific
options. */
if (main_args_p)
- target_option_default_node = target_option_current_node
- = build_target_option_node (opts, opts_set);
+ {
+ opts->x_ix86_excess_precision
+ = opts->x_flag_excess_precision;
+ opts->x_ix86_unsafe_math_optimizations
+ = opts->x_flag_unsafe_math_optimizations;
+ target_option_default_node = target_option_current_node
+ = build_target_option_node (opts, opts_set);
+ }
if (opts->x_flag_cf_protection != CF_NONE)
opts->x_flag_cf_protection
@@ -3326,6 +3343,24 @@ ix86_set_current_function (tree fndecl)
else
TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
}
+ else if (flag_unsafe_math_optimizations
+ != TREE_TARGET_OPTION (new_tree)->x_ix86_unsafe_math_optimizations
+ || (flag_excess_precision
+ != TREE_TARGET_OPTION (new_tree)->x_ix86_excess_precision))
+ {
+ cl_target_option_restore (&global_options, &global_options_set,
+ TREE_TARGET_OPTION (new_tree));
+ ix86_excess_precision = flag_excess_precision;
+ ix86_unsafe_math_optimizations = flag_unsafe_math_optimizations;
+ DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_tree
+ = build_target_option_node (&global_options, &global_options_set);
+ if (TREE_TARGET_GLOBALS (new_tree))
+ restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
+ else if (new_tree == target_option_default_node)
+ restore_target_globals (&default_target_globals);
+ else
+ TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
+ }
ix86_previous_fndecl = fndecl;
static bool prev_no_caller_saved_registers;
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 3a57710..54b7e10 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -23001,7 +23001,7 @@ ix86_init_libfuncs (void)
apparently at random. */
static enum flt_eval_method
-ix86_excess_precision (enum excess_precision_type type)
+ix86_get_excess_precision (enum excess_precision_type type)
{
switch (type)
{
@@ -23527,7 +23527,7 @@ ix86_run_selftests (void)
#define TARGET_MD_ASM_ADJUST ix86_md_asm_adjust
#undef TARGET_C_EXCESS_PRECISION
-#define TARGET_C_EXCESS_PRECISION ix86_excess_precision
+#define TARGET_C_EXCESS_PRECISION ix86_get_excess_precision
#undef TARGET_PROMOTE_PROTOTYPES
#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
#undef TARGET_SETUP_INCOMING_VARARGS
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 5680fdc..d157d30 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -829,15 +829,15 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
SFmode, DFmode and XFmode) in the current excess precision
configuration. */
#define X87_ENABLE_ARITH(MODE) \
- (flag_unsafe_math_optimizations \
- || flag_excess_precision == EXCESS_PRECISION_FAST \
+ (ix86_unsafe_math_optimizations \
+ || ix86_excess_precision == EXCESS_PRECISION_FAST \
|| (MODE) == XFmode)
/* Likewise, whether to allow direct conversions from integer mode
IMODE (HImode, SImode or DImode) to MODE. */
#define X87_ENABLE_FLOAT(MODE, IMODE) \
- (flag_unsafe_math_optimizations \
- || flag_excess_precision == EXCESS_PRECISION_FAST \
+ (ix86_unsafe_math_optimizations \
+ || ix86_excess_precision == EXCESS_PRECISION_FAST \
|| (MODE) == XFmode \
|| ((MODE) == DFmode && (IMODE) == SImode) \
|| (IMODE) == HImode)
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 87e6021..e38baee 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -49,6 +49,16 @@ int recip_mask_explicit
TargetSave
int x_recip_mask_explicit
+;; A copy of flag_excess_precision as a target variable that should
+;; force a different DECL_FUNCTION_SPECIFIC_TARGET upon
+;; flag_excess_precision changes.
+TargetVariable
+enum excess_precision ix86_excess_precision = EXCESS_PRECISION_DEFAULT
+
+;; Similarly for flag_unsafe_math_optimizations.
+TargetVariable
+bool ix86_unsafe_math_optimizations = false
+
;; Definitions to add to the cl_target_option structure
;; -march= processor
TargetSave
diff --git a/gcc/testsuite/gcc.target/i386/pr94440-1.c b/gcc/testsuite/gcc.target/i386/pr94440-1.c
new file mode 100644
index 0000000..c18b16b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr94440-1.c
@@ -0,0 +1,23 @@
+/* PR target/94440 */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-mfpmath=sse,387 -msse2 -Ofast -fexcess-precision=standard -fno-graphite --param=scev-max-expr-size=0" } */
+
+int b;
+double c, d;
+
+void
+foo (void)
+{
+ int i;
+ for (i = 0; i < b; i++)
+ c += i;
+}
+
+int __attribute__((optimize(1)))
+main ()
+{
+ double a[9];
+ int i;
+ for (i = 0; i < 9; i++)
+ d += a[i];
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr94440-2.c b/gcc/testsuite/gcc.target/i386/pr94440-2.c
new file mode 100644
index 0000000..3ac78e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr94440-2.c
@@ -0,0 +1,19 @@
+/* PR target/94440 */
+/* { dg-do compile } */
+/* { dg-options "-O0 -msse2 -ffast-math" } */
+
+double a;
+int b;
+long double c;
+
+void
+foo (void)
+{
+ float d = (double)(long double)b;
+}
+
+__attribute__((optimize("O0"))) void
+bar (void)
+{
+ a = c;
+}