Add target("80387") attribute to enable and disable x87 instructions in a function.
gcc/ PR target/121541 * config/i386/i386-options.cc (ix86_valid_target_attribute_inner_p): Add a bool argument to return if x87 is disabled by target("no-80387") attribute. Add and handle target("80387") attribute. (ix86_valid_target_attribute_tree): Get the x87 info from ix86_valid_target_attribute_inner_p and pass the info to ix86_option_override_internal. (ix86_option_override_internal): Add a bool argument to indicate if x87 should be disabled. Don't enable x87 if it should be disabled. (ix86_option_override): Pass false to ix86_option_override_internal. * doc/extend.texi: Document target("80387") function attribute. gcc/testsuite/ PR target/121541 * gcc.target/i386/pr121541-1a.c: New test. * gcc.target/i386/pr121541-1b.c: Likewise. * gcc.target/i386/pr121541-2.c: Likewise. * gcc.target/i386/pr121541-3.c: Likewise. * gcc.target/i386/pr121541-4.c: Likewise. * gcc.target/i386/pr121541-5a.c: Likewise. * gcc.target/i386/pr121541-5b.c: Likewise. Signed-off-by: H.J. Lu <hjl.to...@gmail.com> --- gcc/config/i386/i386-options.cc | 42 +++++++++++++++------ gcc/doc/extend.texi | 5 +++ gcc/testsuite/gcc.target/i386/pr121541-1a.c | 11 ++++++ gcc/testsuite/gcc.target/i386/pr121541-1b.c | 6 +++ gcc/testsuite/gcc.target/i386/pr121541-2.c | 11 ++++++ gcc/testsuite/gcc.target/i386/pr121541-3.c | 11 ++++++ gcc/testsuite/gcc.target/i386/pr121541-4.c | 11 ++++++ gcc/testsuite/gcc.target/i386/pr121541-5a.c | 11 ++++++ gcc/testsuite/gcc.target/i386/pr121541-5b.c | 6 +++ 9 files changed, 102 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr121541-1a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr121541-1b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr121541-2.c create mode 100644 gcc/testsuite/gcc.target/i386/pr121541-3.c create mode 100644 gcc/testsuite/gcc.target/i386/pr121541-4.c create mode 100644 gcc/testsuite/gcc.target/i386/pr121541-5a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr121541-5b.c diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc index 09a35ef6298..30c10bed6bc 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -825,7 +825,8 @@ STATIC_ASSERT (ARRAY_SIZE (processor_cost_table) == PROCESSOR_max); static bool ix86_option_override_internal (bool main_args_p, struct gcc_options *opts, - struct gcc_options *opts_set); + struct gcc_options *opts_set, + bool disable_80387); static void set_ix86_tune_features (struct gcc_options *opts, enum processor_type ix86_tune, bool dump); @@ -988,7 +989,8 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[], struct gcc_options *opts, struct gcc_options *opts_set, struct gcc_options *enum_opts_set, - bool target_clone_attr) + bool target_clone_attr, + bool &disable_80387) { char *next_optstr; bool ret = true; @@ -1172,6 +1174,10 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[], OPT_mrecip, MASK_RECIP), + IX86_ATTR_YES ("80387", + OPT_m80387, + MASK_80387), + IX86_ATTR_IX86_YES ("general-regs-only", OPT_mgeneral_regs_only, OPTION_MASK_GENERAL_REGS_ONLY), @@ -1193,7 +1199,8 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[], && !ix86_valid_target_attribute_inner_p (fndecl, TREE_VALUE (args), p_strings, opts, opts_set, enum_opts_set, - target_clone_attr)) + target_clone_attr, + disable_80387)) ret = false; return ret; @@ -1287,7 +1294,11 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[], if (opt_set_p) opts->x_target_flags |= mask; else - opts->x_target_flags &= ~mask; + { + if (mask == MASK_80387) + disable_80387 = true; + opts->x_target_flags &= ~mask; + } } else if (type == ix86_opt_ix86_yes || type == ix86_opt_ix86_no) @@ -1417,9 +1428,11 @@ ix86_valid_target_attribute_tree (tree fndecl, tree args, memset (&enum_opts_set, 0, sizeof (enum_opts_set)); /* Process each of the options on the chain. */ + bool disable_80387 = false; if (!ix86_valid_target_attribute_inner_p (fndecl, args, option_strings, opts, opts_set, &enum_opts_set, - target_clone_attr)) + target_clone_attr, + disable_80387)) return error_mark_node; /* If the changed options are different from the default, rerun @@ -1459,7 +1472,8 @@ ix86_valid_target_attribute_tree (tree fndecl, tree args, opts_set->x_prefer_vector_width_type = (enum prefer_vector_width) 1; /* Do any overrides, such as arch=xxx, or tune=xxx support. */ - bool r = ix86_option_override_internal (false, opts, opts_set); + bool r = ix86_option_override_internal (false, opts, opts_set, + disable_80387); if (!r) { release_options_strings (option_strings); @@ -1993,7 +2007,8 @@ ix86_init_machine_status (void) static bool ix86_option_override_internal (bool main_args_p, struct gcc_options *opts, - struct gcc_options *opts_set) + struct gcc_options *opts_set, + bool disable_80387) { unsigned int i; unsigned HOST_WIDE_INT ix86_arch_mask; @@ -2371,10 +2386,12 @@ ix86_option_override_internal (bool main_args_p, & (PTA_PREFETCH_SSE | PTA_SSE)) != 0) ix86_prefetch_sse = true; - /* Don't enable x87 instructions if only general registers are - allowed by target("general-regs-only") function attribute or - -mgeneral-regs-only. */ - if (!(opts->x_ix86_target_flags & OPTION_MASK_GENERAL_REGS_ONLY) + /* Don't enable x87 instructions if x87 instructions are disabled + by target("no-80387") function attribute, or only general + registers are allowed by target("general-regs-only") function + attribute or -mgeneral-regs-only. */ + if (!disable_80387 + && !(opts->x_ix86_target_flags & OPTION_MASK_GENERAL_REGS_ONLY) && !(opts_set->x_target_flags & MASK_80387)) { if (((processor_alias_table[i].flags & PTA_NO_80387) != 0)) @@ -3179,7 +3196,8 @@ ix86_option_override_internal (bool main_args_p, void ix86_option_override (void) { - ix86_option_override_internal (true, &global_options, &global_options_set); + ix86_option_override_internal (true, &global_options, + &global_options_set, false); } /* Remember the last target of ix86_set_current_function. */ diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 224d6197d63..e2771d7e36a 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -6798,6 +6798,11 @@ Enable/disable the generation of RCPSS, RCPPS, RSQRTSS and RSQRTPS instructions followed an additional Newton-Raphson step instead of doing a floating-point division. +@cindex @code{target("80387")} function attribute, x86 +@item 80387 +@itemx no-80387 +Generate code containing 80387 instructions for floating point. + @cindex @code{target("general-regs-only")} function attribute, x86 @item general-regs-only Generate code which uses only the general registers. diff --git a/gcc/testsuite/gcc.target/i386/pr121541-1a.c b/gcc/testsuite/gcc.target/i386/pr121541-1a.c new file mode 100644 index 00000000000..83884a7b15c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr121541-1a.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -march=x86-64" } */ + +extern long double d; + +__attribute__ ((target("no-80387"))) +void +func1 (void) +{ + d *= 3; /* { dg-error "x87 register return with x87 disabled" } */ +} diff --git a/gcc/testsuite/gcc.target/i386/pr121541-1b.c b/gcc/testsuite/gcc.target/i386/pr121541-1b.c new file mode 100644 index 00000000000..f440b14ca71 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr121541-1b.c @@ -0,0 +1,6 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2" } */ + +#include "pr121541-1a.c" + +/* { dg-final { scan-assembler "call\[\\t \]+_?__mulxf3" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr121541-2.c b/gcc/testsuite/gcc.target/i386/pr121541-2.c new file mode 100644 index 00000000000..281341e9bb9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr121541-2.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-80387" } */ + +extern long double d; + +__attribute__ ((target("80387"))) +void +func1 (void) +{ + d *= 3; +} diff --git a/gcc/testsuite/gcc.target/i386/pr121541-3.c b/gcc/testsuite/gcc.target/i386/pr121541-3.c new file mode 100644 index 00000000000..380fab2aad9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr121541-3.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mgeneral-regs-only" } */ + +extern long double d; + +__attribute__ ((target("80387"))) +void +func1 (void) +{ + d *= 3; +} diff --git a/gcc/testsuite/gcc.target/i386/pr121541-4.c b/gcc/testsuite/gcc.target/i386/pr121541-4.c new file mode 100644 index 00000000000..1f4381a52b0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr121541-4.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern long double d; + +__attribute__ ((target("general-regs-only","80387"))) +void +func1 (void) +{ + d *= 3; +} diff --git a/gcc/testsuite/gcc.target/i386/pr121541-5a.c b/gcc/testsuite/gcc.target/i386/pr121541-5a.c new file mode 100644 index 00000000000..e6137e22e98 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr121541-5a.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -march=x86-64" } */ + +extern long double d; + +__attribute__ ((target("80387","general-regs-only"))) +void +func1 (void) +{ + d *= 3; /* { dg-error "x87 register return with x87 disabled" } */ +} diff --git a/gcc/testsuite/gcc.target/i386/pr121541-5b.c b/gcc/testsuite/gcc.target/i386/pr121541-5b.c new file mode 100644 index 00000000000..b61a7fe6a3f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr121541-5b.c @@ -0,0 +1,6 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2" } */ + +#include "pr121541-5a.c" + +/* { dg-final { scan-assembler "call\[\\t \]+_?__mulxf3" } } */ -- 2.50.1