This patch continues cleaning up x86 option handling to use .opt
features, by cleaning up the -mfpmath= handling.

This is somewhat complicated because of these options being generated
by attributes.  I exposed a new interface from opts-common.c to be
used to convert a string to an enum value as if it were an argument to
a given option, for use from such attribute handlers.

The patch is intended to preserve the existing logic for handling of
these options and attributes.  This includes that -mfpmath=387 is
considered OK in the presence of -mno-80387 (also spelt -msoft-float),
although it might seem more appropriate for an options such as
-mfpmath=soft to be used in the soft-float case, and that if SSE is
enabled for 32-bit, then any use of the target attribute on a function
will enable -mfpmath=sse+387 for that function if there is no explicit
-mfpmath= option or attribute, even if the SSE enabling was from the
command line and the attribute on the function doesn't relate to SSE
at all.

Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  Will
commit to trunk in the absence of target maintainer objections.

2011-05-15  Joseph Myers  <jos...@codesourcery.com>

        * opts-common.c (opt_enum_arg_to_value): New.
        * opts.h (opt_enum_arg_to_value): Declare.
        * config/i386/i386.opt (fpmath): Remove.
        (mfpmath=): Use Enum, Init and Save.
        (fpmath_unit): New Enum and EnumValue entries.
        * config/i386/i386-c.c (ix86_pragma_target_parse): Update field
        name for function fpmath state.
        * config/i386/i386-opts.h (enum fpmath_unit): Move from i386.h.
        * config/i386/i386.c: Include diagnostic.h.
        (ix86_fpmath, IX86_FUNCTION_SPECIFIC_FPMATH): Remove.
        (ix86_target_string): Take enum fpmath_unit value instead of
        string.
        (ix86_debug_options): Update call to ix86_target_string.
        (ix86_option_override_internal): Don't process fpmath strings
        here.
        (x86_function_specific_save, ix86_function_specific_restore):
        Don't handle fpmath state specially.
        (ix86_function_specific_print): Pass fpmath state to
        ix86_target_string instead of printing in this function.
        (ix86_valid_target_attribute_inner_p): Take gcc_options pointer.
        Handle enum attributes.
        (IX86_ATTR_ENUM, ix86_opt_enum): New.
        (ix86_valid_target_attribute_tree): Update option_strings
        handling.  Handle fpmath as enum option.
        (ix86_can_inline_p): Update field names for function fpmath state.
        (ix86_expand_builtin): Update call to ix86_target_string.
        * config/i386/i386.h (enum fpmath_unit): Move to i386-opts.h.
        (ix86_fpmath): Remove.
        * config/i386/t-i386 (i386.o): Update dependencies.

Index: gcc/opts-common.c
===================================================================
--- gcc/opts-common.c   (revision 173728)
+++ gcc/opts-common.c   (working copy)
@@ -212,6 +212,22 @@ enum_arg_to_value (const struct cl_enum_
   return false;
 }
 
+/* Look up ARG in the enum used by option OPT_INDEX for language
+   LANG_MASK, returning true and storing the value in *VALUE if found,
+   and returning false without modifying *VALUE if not found.  */
+
+bool
+opt_enum_arg_to_value (size_t opt_index, const char *arg, int *value,
+                      unsigned int lang_mask)
+{
+  const struct cl_option *option = &cl_options[opt_index];
+
+  gcc_assert (option->var_type == CLVC_ENUM);
+
+  return enum_arg_to_value (cl_enums[option->var_enum].values, arg,
+                           value, lang_mask);
+}
+
 /* Look of VALUE in ENUM_ARGS for language LANG_MASK and store the
    corresponding string in *ARGP, returning true if the found string
    was marked as canonical, false otherwise.  If VALUE is not found
Index: gcc/opts.h
===================================================================
--- gcc/opts.h  (revision 173728)
+++ gcc/opts.h  (working copy)
@@ -395,4 +395,6 @@ extern void default_options_optimization
 extern void set_struct_debug_option (struct gcc_options *opts,
                                     location_t loc,
                                     const char *value);
+extern bool opt_enum_arg_to_value (size_t opt_index, const char *arg,
+                                  int *value, unsigned int lang_mask);
 #endif
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h      (revision 173728)
+++ gcc/config/i386/i386.h      (working copy)
@@ -2029,14 +2029,6 @@ enum processor_type
 extern enum processor_type ix86_tune;
 extern enum processor_type ix86_arch;
 
-enum fpmath_unit
-{
-  FPMATH_387 = 1,
-  FPMATH_SSE = 2
-};
-
-extern enum fpmath_unit ix86_fpmath;
-
 /* Size of the RED_ZONE area.  */
 #define RED_ZONE_SIZE 128
 /* Reserved area of the red zone for temporaries.  */
Index: gcc/config/i386/i386-opts.h
===================================================================
--- gcc/config/i386/i386-opts.h (revision 173728)
+++ gcc/config/i386/i386-opts.h (working copy)
@@ -47,6 +47,12 @@ enum calling_abi
   MS_ABI = 1
 };
 
+enum fpmath_unit
+{
+  FPMATH_387 = 1,
+  FPMATH_SSE = 2
+};
+
 enum tls_dialect
 {
   TLS_DIALECT_GNU,
Index: gcc/config/i386/i386-c.c
===================================================================
--- gcc/config/i386/i386-c.c    (revision 173728)
+++ gcc/config/i386/i386-c.c    (working copy)
@@ -340,14 +340,14 @@ ix86_pragma_target_parse (tree args, tre
   ix86_target_macros_internal (prev_isa & diff_isa,
                               prev_arch,
                               prev_tune,
-                              (enum fpmath_unit) prev_opt->fpmath,
+                              (enum fpmath_unit) prev_opt->x_ix86_fpmath,
                               cpp_undef);
 
   /* Define all of the macros for new options that were just turned on.  */
   ix86_target_macros_internal (cur_isa & diff_isa,
                               cur_arch,
                               cur_tune,
-                              (enum fpmath_unit) cur_opt->fpmath,
+                              (enum fpmath_unit) cur_opt->x_ix86_fpmath,
                               cpp_define);
 
   return true;
Index: gcc/config/i386/i386.opt
===================================================================
--- gcc/config/i386/i386.opt    (revision 173728)
+++ gcc/config/i386/i386.opt    (working copy)
@@ -40,10 +40,6 @@ unsigned char arch
 TargetSave
 unsigned char tune
 
-;; -mfpath=
-TargetSave
-unsigned char fpmath
-
 ;; CPU schedule model
 TargetSave
 unsigned char schedule
@@ -170,9 +166,34 @@ Target Report Mask(FLOAT_RETURNS) Save
 Return values of functions in FPU registers
 
 mfpmath=
-Target RejectNegative Joined Var(ix86_fpmath_string)
+Target RejectNegative Joined Var(ix86_fpmath) Enum(fpmath_unit) 
Init(FPMATH_387) Save
 Generate floating point mathematics using given instruction set
 
+Enum
+Name(fpmath_unit) Type(enum fpmath_unit)
+Valid arguments to -mfpmath=:
+
+EnumValue
+Enum(fpmath_unit) String(387) Value(FPMATH_387)
+
+EnumValue
+Enum(fpmath_unit) String(sse) Value(FPMATH_SSE)
+
+EnumValue
+Enum(fpmath_unit) String(387,sse) Value({(enum fpmath_unit) (FPMATH_SSE | 
FPMATH_387)})
+
+EnumValue
+Enum(fpmath_unit) String(387+sse) Value({(enum fpmath_unit) (FPMATH_SSE | 
FPMATH_387)})
+
+EnumValue
+Enum(fpmath_unit) String(sse,387) Value({(enum fpmath_unit) (FPMATH_SSE | 
FPMATH_387)})
+
+EnumValue
+Enum(fpmath_unit) String(sse+387) Value({(enum fpmath_unit) (FPMATH_SSE | 
FPMATH_387)})
+
+EnumValue
+Enum(fpmath_unit) String(both) Value({(enum fpmath_unit) (FPMATH_SSE | 
FPMATH_387)})
+
 mhard-float
 Target RejectNegative Mask(80387) MaskExists Save
 Use hardware fp
Index: gcc/config/i386/t-i386
===================================================================
--- gcc/config/i386/t-i386      (revision 173728)
+++ gcc/config/i386/t-i386      (working copy)
@@ -24,7 +24,7 @@ i386.o: $(CONFIG_H) $(SYSTEM_H) coretype
   $(GGC_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h $(CGRAPH_H) \
   $(TREE_GIMPLE_H) $(DWARF2_H) $(DF_H) tm-constrs.h $(PARAMS_H) \
   i386-builtin-types.inc debug.h dwarf2out.h sbitmap.h $(FIBHEAP_H) \
-  $(OPTS_H)
+  $(OPTS_H) $(DIAGNOSTIC_H)
 
 i386-c.o: $(srcdir)/config/i386/i386-c.c \
   $(srcdir)/config/i386/i386-protos.h $(CONFIG_H) $(SYSTEM_H) coretypes.h \
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c      (revision 173728)
+++ gcc/config/i386/i386.c      (working copy)
@@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.  
 #include "sbitmap.h"
 #include "fibheap.h"
 #include "opts.h"
+#include "diagnostic.h"
 
 enum upper_128bits_state
 {
@@ -2325,9 +2326,6 @@ struct ix86_frame
   bool save_regs_using_mov;
 };
 
-/* Which unit we are generating floating point math for.  */
-enum fpmath_unit ix86_fpmath;
-
 /* Which cpu are we scheduling for.  */
 enum attr_cpu ix86_schedule;
 
@@ -2429,19 +2427,19 @@ enum ix86_function_specific_strings
 {
   IX86_FUNCTION_SPECIFIC_ARCH,
   IX86_FUNCTION_SPECIFIC_TUNE,
-  IX86_FUNCTION_SPECIFIC_FPMATH,
   IX86_FUNCTION_SPECIFIC_MAX
 };
 
 static char *ix86_target_string (int, int, const char *, const char *,
-                                const char *, bool);
+                                enum fpmath_unit, bool);
 static void ix86_debug_options (void) ATTRIBUTE_UNUSED;
 static void ix86_function_specific_save (struct cl_target_option *);
 static void ix86_function_specific_restore (struct cl_target_option *);
 static void ix86_function_specific_print (FILE *, int,
                                          struct cl_target_option *);
 static bool ix86_valid_target_attribute_p (tree, tree, tree, int);
-static bool ix86_valid_target_attribute_inner_p (tree, char *[]);
+static bool ix86_valid_target_attribute_inner_p (tree, char *[],
+                                                struct gcc_options *);
 static bool ix86_can_inline_p (tree, tree);
 static void ix86_set_current_function (tree);
 static unsigned int ix86_minimum_incoming_stack_boundary (bool);
@@ -3085,7 +3083,7 @@ ix86_handle_option (struct gcc_options *
 
 static char *
 ix86_target_string (int isa, int flags, const char *arch, const char *tune,
-                   const char *fpmath, bool add_nl_p)
+                   enum fpmath_unit fpmath, bool add_nl_p)
 {
   struct ix86_target_opts
   {
@@ -3219,7 +3217,23 @@ ix86_target_string (int isa, int flags, 
   if (fpmath)
     {
       opts[num][0] = "-mfpmath=";
-      opts[num++][1] = fpmath;
+      switch ((int) fpmath)
+       {
+       case FPMATH_387:
+         opts[num++][1] = "387";
+         break;
+
+       case FPMATH_SSE:
+         opts[num++][1] = "sse";
+         break;
+
+       case FPMATH_387 | FPMATH_SSE:
+         opts[num++][1] = "sse+387";
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
     }
 
   /* Any options?  */
@@ -3294,7 +3308,7 @@ ix86_debug_options (void)
 {
   char *opts = ix86_target_string (ix86_isa_flags, target_flags,
                                   ix86_arch_string, ix86_tune_string,
-                                  ix86_fpmath_string, true);
+                                  ix86_fpmath, true);
 
   if (opts)
     {
@@ -3996,44 +4010,24 @@ ix86_option_override_internal (bool main
       && ! TARGET_SSE)
     error ("%ssseregparm%s used without SSE enabled", prefix, suffix);
 
-  ix86_fpmath = TARGET_FPMATH_DEFAULT;
-  if (ix86_fpmath_string != 0)
+  if (global_options_set.x_ix86_fpmath)
     {
-      if (! strcmp (ix86_fpmath_string, "387"))
-       ix86_fpmath = FPMATH_387;
-      else if (! strcmp (ix86_fpmath_string, "sse"))
-       {
-         if (!TARGET_SSE)
-           {
-             warning (0, "SSE instruction set disabled, using 387 
arithmetics");
-             ix86_fpmath = FPMATH_387;
-           }
-         else
-           ix86_fpmath = FPMATH_SSE;
-       }
-      else if (! strcmp (ix86_fpmath_string, "387,sse")
-              || ! strcmp (ix86_fpmath_string, "387+sse")
-              || ! strcmp (ix86_fpmath_string, "sse,387")
-              || ! strcmp (ix86_fpmath_string, "sse+387")
-              || ! strcmp (ix86_fpmath_string, "both"))
+      if (ix86_fpmath & FPMATH_SSE)
        {
          if (!TARGET_SSE)
            {
              warning (0, "SSE instruction set disabled, using 387 
arithmetics");
              ix86_fpmath = FPMATH_387;
            }
-         else if (!TARGET_80387)
+         else if ((ix86_fpmath & FPMATH_387) && !TARGET_80387)
            {
              warning (0, "387 instruction set disabled, using SSE 
arithmetics");
              ix86_fpmath = FPMATH_SSE;
            }
-         else
-           ix86_fpmath = (enum fpmath_unit) (FPMATH_SSE | FPMATH_387);
        }
-      else
-       error ("bad value (%s) for %sfpmath=%s %s",
-              ix86_fpmath_string, prefix, suffix, sw);
     }
+  else
+    ix86_fpmath = TARGET_FPMATH_DEFAULT;
 
   /* If the i387 is disabled, then do not return values in it. */
   if (!TARGET_80387)
@@ -4337,7 +4331,6 @@ ix86_function_specific_save (struct cl_t
   ptr->arch = ix86_arch;
   ptr->schedule = ix86_schedule;
   ptr->tune = ix86_tune;
-  ptr->fpmath = ix86_fpmath;
   ptr->branch_cost = ix86_branch_cost;
   ptr->tune_defaulted = ix86_tune_defaulted;
   ptr->arch_specified = ix86_arch_specified;
@@ -4349,7 +4342,6 @@ ix86_function_specific_save (struct cl_t
   gcc_assert (ptr->arch == ix86_arch);
   gcc_assert (ptr->schedule == ix86_schedule);
   gcc_assert (ptr->tune == ix86_tune);
-  gcc_assert (ptr->fpmath == ix86_fpmath);
   gcc_assert (ptr->branch_cost == ix86_branch_cost);
 }
 
@@ -4366,7 +4358,6 @@ ix86_function_specific_restore (struct c
   ix86_arch = (enum processor_type) ptr->arch;
   ix86_schedule = (enum attr_cpu) ptr->schedule;
   ix86_tune = (enum processor_type) ptr->tune;
-  ix86_fpmath = (enum fpmath_unit) ptr->fpmath;
   ix86_branch_cost = ptr->branch_cost;
   ix86_tune_defaulted = ptr->tune_defaulted;
   ix86_arch_specified = ptr->arch_specified;
@@ -4400,7 +4391,7 @@ ix86_function_specific_print (FILE *file
 {
   char *target_string
     = ix86_target_string (ptr->x_ix86_isa_flags, ptr->x_target_flags,
-                         NULL, NULL, NULL, false);
+                         NULL, NULL, ptr->x_ix86_fpmath, false);
 
   fprintf (file, "%*sarch = %d (%s)\n",
           indent, "",
@@ -4416,9 +4407,6 @@ ix86_function_specific_print (FILE *file
            ? cpu_names[ptr->tune]
            : "<unknown>"));
 
-  fprintf (file, "%*sfpmath = %d%s%s\n", indent, "", ptr->fpmath,
-          (ptr->fpmath & FPMATH_387) ? ", 387" : "",
-          (ptr->fpmath & FPMATH_SSE) ? ", sse" : "");
   fprintf (file, "%*sbranch_cost = %d\n", indent, "", ptr->branch_cost);
 
   if (target_string)
@@ -4434,13 +4422,15 @@ ix86_function_specific_print (FILE *file
    over the list.  */
 
 static bool
-ix86_valid_target_attribute_inner_p (tree args, char *p_strings[])
+ix86_valid_target_attribute_inner_p (tree args, char *p_strings[],
+                                    struct gcc_options *enum_opts_set)
 {
   char *next_optstr;
   bool ret = true;
 
 #define IX86_ATTR_ISA(S,O)   { S, sizeof (S)-1, ix86_opt_isa, O, 0 }
 #define IX86_ATTR_STR(S,O)   { S, sizeof (S)-1, ix86_opt_str, O, 0 }
+#define IX86_ATTR_ENUM(S,O)  { S, sizeof (S)-1, ix86_opt_enum, O, 0 }
 #define IX86_ATTR_YES(S,O,M) { S, sizeof (S)-1, ix86_opt_yes, O, M }
 #define IX86_ATTR_NO(S,O,M)  { S, sizeof (S)-1, ix86_opt_no,  O, M }
 
@@ -4450,6 +4440,7 @@ ix86_valid_target_attribute_inner_p (tre
     ix86_opt_yes,
     ix86_opt_no,
     ix86_opt_str,
+    ix86_opt_enum,
     ix86_opt_isa
   };
 
@@ -4486,9 +4477,11 @@ ix86_valid_target_attribute_inner_p (tre
     IX86_ATTR_ISA ("rdrnd",    OPT_mrdrnd),
     IX86_ATTR_ISA ("f16c",     OPT_mf16c),
 
+    /* enum options */
+    IX86_ATTR_ENUM ("fpmath=", OPT_mfpmath_),
+
     /* string options */
     IX86_ATTR_STR ("arch=",    IX86_FUNCTION_SPECIFIC_ARCH),
-    IX86_ATTR_STR ("fpmath=",  IX86_FUNCTION_SPECIFIC_FPMATH),
     IX86_ATTR_STR ("tune=",    IX86_FUNCTION_SPECIFIC_TUNE),
 
     /* flag options */
@@ -4529,7 +4522,8 @@ ix86_valid_target_attribute_inner_p (tre
 
       for (; args; args = TREE_CHAIN (args))
        if (TREE_VALUE (args)
-           && !ix86_valid_target_attribute_inner_p (TREE_VALUE (args), 
p_strings))
+           && !ix86_valid_target_attribute_inner_p (TREE_VALUE (args),
+                                                    p_strings, enum_opts_set))
          ret = false;
 
       return ret;
@@ -4585,7 +4579,9 @@ ix86_valid_target_attribute_inner_p (tre
          type = attrs[i].type;
          opt_len = attrs[i].len;
          if (ch == attrs[i].string[0]
-             && ((type != ix86_opt_str) ? len == opt_len : len > opt_len)
+             && ((type != ix86_opt_str && type != ix86_opt_enum)
+                 ? len == opt_len
+                 : len > opt_len)
              && memcmp (p, attrs[i].string, opt_len) == 0)
            {
              opt = attrs[i].opt;
@@ -4633,6 +4629,23 @@ ix86_valid_target_attribute_inner_p (tre
            p_strings[opt] = xstrdup (p + opt_len);
        }
 
+      else if (type == ix86_opt_enum)
+       {
+         bool arg_ok;
+         int value;
+
+         arg_ok = opt_enum_arg_to_value (opt, p + opt_len, &value, CL_TARGET);
+         if (arg_ok)
+           set_option (&global_options, enum_opts_set, opt, value,
+                       p + opt_len, DK_UNSPECIFIED, input_location,
+                       global_dc);
+         else
+           {
+             error ("attribute(target(\"%s\")) is unknown", orig_p);
+             ret = false;
+           }
+       }
+
       else
        gcc_unreachable ();
     }
@@ -4647,17 +4660,21 @@ ix86_valid_target_attribute_tree (tree a
 {
   const char *orig_arch_string = ix86_arch_string;
   const char *orig_tune_string = ix86_tune_string;
-  const char *orig_fpmath_string = ix86_fpmath_string;
+  enum fpmath_unit orig_fpmath_set = global_options_set.x_ix86_fpmath;
   int orig_tune_defaulted = ix86_tune_defaulted;
   int orig_arch_specified = ix86_arch_specified;
-  char *option_strings[IX86_FUNCTION_SPECIFIC_MAX] = { NULL, NULL, NULL };
+  char *option_strings[IX86_FUNCTION_SPECIFIC_MAX] = { NULL, NULL };
   tree t = NULL_TREE;
   int i;
   struct cl_target_option *def
     = TREE_TARGET_OPTION (target_option_default_node);
+  struct gcc_options enum_opts_set;
+
+  memset (&enum_opts_set, 0, sizeof (enum_opts_set));
 
   /* Process each of the options on the chain.  */
-  if (! ix86_valid_target_attribute_inner_p (args, option_strings))
+  if (! ix86_valid_target_attribute_inner_p (args, option_strings,
+                                            &enum_opts_set))
     return NULL_TREE;
 
   /* If the changed options are different from the default, rerun
@@ -4668,7 +4685,7 @@ ix86_valid_target_attribute_tree (tree a
       || target_flags != def->x_target_flags
       || option_strings[IX86_FUNCTION_SPECIFIC_ARCH]
       || option_strings[IX86_FUNCTION_SPECIFIC_TUNE]
-      || option_strings[IX86_FUNCTION_SPECIFIC_FPMATH])
+      || ix86_fpmath != def->x_ix86_fpmath)
     {
       /* If we are using the default tune= or arch=, undo the string assigned,
         and use the default.  */
@@ -4683,10 +4700,13 @@ ix86_valid_target_attribute_tree (tree a
        ix86_tune_string = NULL;
 
       /* If fpmath= is not set, and we now have sse2 on 32-bit, use it.  */
-      if (option_strings[IX86_FUNCTION_SPECIFIC_FPMATH])
-       ix86_fpmath_string = option_strings[IX86_FUNCTION_SPECIFIC_FPMATH];
+      if (enum_opts_set.x_ix86_fpmath)
+       global_options_set.x_ix86_fpmath = (enum fpmath_unit) 1;
       else if (!TARGET_64BIT && TARGET_SSE)
-       ix86_fpmath_string = "sse,387";
+       {
+         ix86_fpmath = (enum fpmath_unit) (FPMATH_SSE | FPMATH_387);
+         global_options_set.x_ix86_fpmath = (enum fpmath_unit) 1;
+       }
 
       /* Do any overrides, such as arch=xxx, or tune=xxx support.  */
       ix86_option_override_internal (false);
@@ -4700,7 +4720,7 @@ ix86_valid_target_attribute_tree (tree a
 
       ix86_arch_string = orig_arch_string;
       ix86_tune_string = orig_tune_string;
-      ix86_fpmath_string = orig_fpmath_string;
+      global_options_set.x_ix86_fpmath = orig_fpmath_set;
 
       /* Free up memory allocated to hold the strings */
       for (i = 0; i < IX86_FUNCTION_SPECIFIC_MAX; i++)
@@ -4798,7 +4818,7 @@ ix86_can_inline_p (tree caller, tree cal
       else if (caller_opts->tune != callee_opts->tune)
        ret = false;
 
-      else if (caller_opts->fpmath != callee_opts->fpmath)
+      else if (caller_opts->x_ix86_fpmath != callee_opts->x_ix86_fpmath)
        ret = false;
 
       else if (caller_opts->branch_cost != callee_opts->branch_cost)
@@ -27375,7 +27395,7 @@ ix86_expand_builtin (tree exp, rtx targe
       && !(ix86_builtins_isa[fcode].isa & ix86_isa_flags))
     {
       char *opts = ix86_target_string (ix86_builtins_isa[fcode].isa, 0, NULL,
-                                      NULL, NULL, false);
+                                      NULL, (enum fpmath_unit) 0, false);
 
       if (!opts)
        error ("%qE needs unknown isa option", fndecl);


-- 
Joseph S. Myers
jos...@codesourcery.com

Reply via email to