On Wed, Aug 13, 2025 at 11:33 PM Uros Bizjak <ubiz...@gmail.com> wrote: > > On Thu, Aug 14, 2025 at 6:58 AM H.J. Lu <hjl.to...@gmail.com> wrote: > > > > 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); > > m80387 option is a target option just like e.g. mrecip, so it should > be processed in the same way. A new bool argument should not be > needed, everything you need should be available via *opts and > *opts_set.
It doesn't work because /* 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) && !(opts_set->x_target_flags & MASK_80387)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When MASK_80387 in opts_set and opts are cleared by target("80387") function attribute, MASK_80387 will be turned on again without target("general-regs-only") function attribute nor -mgeneral-regs-only. { if (((processor_alias_table[i].flags & PTA_NO_80387) != 0)) opts->x_target_flags &= ~MASK_80387; else opts->x_target_flags |= MASK_80387; } > Uros. > > > 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 > > -- H.J.