diff options
-rw-r--r-- | gcc/config/i386/i386-options.c | 39 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 4 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 8 | ||||
-rw-r--r-- | gcc/config/i386/i386.opt | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr94440-1.c | 23 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr94440-2.c | 19 |
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; +} |