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

Reply via email to