OSDN Git Service

2011-05-27 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.c
index c164c70..ae81d62 100644 (file)
@@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "sbitmap.h"
 #include "fibheap.h"
 #include "opts.h"
+#include "diagnostic.h"
 
 enum upper_128bits_state
 {
@@ -2083,6 +2084,11 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
   /* X86_TUNE_VECTORIZE_DOUBLE: Enable double precision vector
      instructions.  */
   ~m_ATOM,
+
+  /* X86_SOFTARE_PREFETCHING_BENEFICIAL: Enable software prefetching
+     at -O3.  For the moment, the prefetching seems badly tuned for Intel
+     chips.  */
+  m_K6_GEODE | m_AMD_MULTIPLE
 };
 
 /* Feature tests against the various architecture variations.  */
@@ -2115,8 +2121,6 @@ static const unsigned int x86_arch_always_fancy_math_387
   = m_PENT | m_ATOM | m_PPRO | m_AMD_MULTIPLE | m_PENT4
     | m_NOCONA | m_CORE2I7 | m_GENERIC;
 
-static enum stringop_alg stringop_alg = no_stringop;
-
 /* In case the average insn count for single function invocation is
    lower than this constant, emit fast (but longer) prologue and
    epilogue code.  */
@@ -2322,16 +2326,6 @@ struct ix86_frame
   bool save_regs_using_mov;
 };
 
-/* Code model option.  */
-enum cmodel ix86_cmodel;
-/* Asm dialect.  */
-enum asm_dialect ix86_asm_dialect = ASM_ATT;
-/* TLS dialects.  */
-enum tls_dialect ix86_tls_dialect = TLS_DIALECT_GNU;
-
-/* 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;
 
@@ -2344,9 +2338,6 @@ enum processor_type ix86_arch;
 /* true if sse prefetch instruction is not NOOP.  */
 int x86_prefetch_sse;
 
-/* ix86_regparm_string as a number */
-static int ix86_regparm;
-
 /* -mstackrealign option */
 static const char ix86_force_align_arg_pointer_string[]
   = "force_align_arg_pointer";
@@ -2375,21 +2366,10 @@ static unsigned int ix86_default_incoming_stack_boundary;
 /* Alignment for incoming stack boundary in bits.  */
 unsigned int ix86_incoming_stack_boundary;
 
-/* The abi used by target.  */
-enum calling_abi ix86_abi;
-
-/* Values 1-5: see jump.c */
-int ix86_branch_cost;
-
 /* Calling abi specific va_list type nodes.  */
 static GTY(()) tree sysv_va_list_type_node;
 static GTY(()) tree ms_va_list_type_node;
 
-/* Variables which are this size or smaller are put in the data/bss
-   or ldata/lbss sections.  */
-
-int ix86_section_threshold = 65536;
-
 /* Prefix built by ASM_GENERATE_INTERNAL_LABEL.  */
 char internal_label_prefix[16];
 int internal_label_prefix_len;
@@ -2447,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);
@@ -2683,7 +2663,7 @@ static bool
 ix86_handle_option (struct gcc_options *opts,
                    struct gcc_options *opts_set ATTRIBUTE_UNUSED,
                    const struct cl_decoded_option *decoded,
-                   location_t loc ATTRIBUTE_UNUSED)
+                   location_t loc)
 {
   size_t code = decoded->opt_index;
   int value = decoded->value;
@@ -3054,6 +3034,45 @@ ix86_handle_option (struct gcc_options *opts,
        }
       return true;
 
+  /* Comes from final.c -- no real reason to change it.  */
+#define MAX_CODE_ALIGN 16
+
+    case OPT_malign_loops_:
+      warning_at (loc, 0, "-malign-loops is obsolete, use -falign-loops");
+      if (value > MAX_CODE_ALIGN)
+       error_at (loc, "-malign-loops=%d is not between 0 and %d",
+                 value, MAX_CODE_ALIGN);
+      else
+       opts->x_align_loops = 1 << value;
+      return true;
+
+    case OPT_malign_jumps_:
+      warning_at (loc, 0, "-malign-jumps is obsolete, use -falign-jumps");
+      if (value > MAX_CODE_ALIGN)
+       error_at (loc, "-malign-jumps=%d is not between 0 and %d",
+                 value, MAX_CODE_ALIGN);
+      else
+       opts->x_align_jumps = 1 << value;
+      return true;
+
+    case OPT_malign_functions_:
+      warning_at (loc, 0,
+                 "-malign-functions is obsolete, use -falign-functions");
+      if (value > MAX_CODE_ALIGN)
+       error_at (loc, "-malign-functions=%d is not between 0 and %d",
+                 value, MAX_CODE_ALIGN);
+      else
+       opts->x_align_functions = 1 << value;
+      return true;
+
+    case OPT_mbranch_cost_:
+      if (value > 5)
+       {
+         error_at (loc, "-mbranch-cost=%d is not between 0 and 5", value);
+         opts->x_ix86_branch_cost = 5;
+       }
+      return true;
+
     default:
       return true;
     }
@@ -3064,7 +3083,7 @@ ix86_handle_option (struct gcc_options *opts,
 
 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
   {
@@ -3198,7 +3217,23 @@ ix86_target_string (int isa, int flags, const char *arch, const char *tune,
   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?  */
@@ -3257,27 +3292,6 @@ ix86_target_string (int isa, int flags, const char *arch, const char *tune,
   return ret;
 }
 
-/* Return TRUE if software prefetching is beneficial for the
-   given CPU. */
-
-static bool
-software_prefetching_beneficial_p (void)
-{
-  switch (ix86_tune)
-    {
-    case PROCESSOR_GEODE:
-    case PROCESSOR_K6:
-    case PROCESSOR_ATHLON:
-    case PROCESSOR_K8:
-    case PROCESSOR_AMDFAM10:
-    case PROCESSOR_BTVER1:
-      return true;
-
-    default:
-      return false;
-    }
-}
-
 /* Return true, if profiling code should be emitted before
    prologue. Otherwise it returns false.
    Note: For x86 with "hotfix" it is sorried.  */
@@ -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)
     {
@@ -3321,9 +3335,6 @@ ix86_option_override_internal (bool main_args_p)
   const char *suffix;
   const char *sw;
 
-  /* Comes from final.c -- no real reason to change it.  */
-#define MAX_CODE_ALIGN 16
-
   enum pta_flags
     {
       PTA_SSE = 1 << 0,
@@ -3546,27 +3557,11 @@ ix86_option_override_internal (bool main_args_p)
        }
     }
 
-  if (ix86_stringop_string)
-    {
-      if (!strcmp (ix86_stringop_string, "rep_byte"))
-       stringop_alg = rep_prefix_1_byte;
-      else if (!strcmp (ix86_stringop_string, "libcall"))
-       stringop_alg = libcall;
-      else if (!strcmp (ix86_stringop_string, "rep_4byte"))
-       stringop_alg = rep_prefix_4_byte;
-      else if (!strcmp (ix86_stringop_string, "rep_8byte")
-              && TARGET_64BIT)
-       /* rep; movq isn't available in 32-bit code.  */
-       stringop_alg = rep_prefix_8_byte;
-      else if (!strcmp (ix86_stringop_string, "byte_loop"))
-       stringop_alg = loop_1_byte;
-      else if (!strcmp (ix86_stringop_string, "loop"))
-       stringop_alg = loop;
-      else if (!strcmp (ix86_stringop_string, "unrolled_loop"))
-       stringop_alg = unrolled_loop;
-      else
-       error ("bad value (%s) for %sstringop-strategy=%s %s",
-              ix86_stringop_string, prefix, suffix, sw);
+  if (ix86_stringop_alg == rep_prefix_8_byte && !TARGET_64BIT)
+    {
+      /* rep; movq isn't available in 32-bit code.  */
+      error ("-mstringop-strategy=rep_8byte not supported for 32-bit code");
+      ix86_stringop_alg = no_stringop;
     }
 
   if (!ix86_arch_string)
@@ -3574,37 +3569,62 @@ ix86_option_override_internal (bool main_args_p)
   else
     ix86_arch_specified = 1;
 
-  /* Validate -mabi= value.  */
-  if (ix86_abi_string)
-    {
-      if (strcmp (ix86_abi_string, "sysv") == 0)
-       ix86_abi = SYSV_ABI;
-      else if (strcmp (ix86_abi_string, "ms") == 0)
-       ix86_abi = MS_ABI;
-      else
-       error ("unknown ABI (%s) for %sabi=%s %s",
-              ix86_abi_string, prefix, suffix, sw);
-    }
-  else
+  if (!global_options_set.x_ix86_abi)
     ix86_abi = DEFAULT_ABI;
 
-  if (ix86_cmodel_string != 0)
+  if (global_options_set.x_ix86_cmodel)
     {
-      if (!strcmp (ix86_cmodel_string, "small"))
-       ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
-      else if (!strcmp (ix86_cmodel_string, "medium"))
-       ix86_cmodel = flag_pic ? CM_MEDIUM_PIC : CM_MEDIUM;
-      else if (!strcmp (ix86_cmodel_string, "large"))
-       ix86_cmodel = flag_pic ? CM_LARGE_PIC : CM_LARGE;
-      else if (flag_pic)
-       error ("code model %s does not support PIC mode", ix86_cmodel_string);
-      else if (!strcmp (ix86_cmodel_string, "32"))
-       ix86_cmodel = CM_32;
-      else if (!strcmp (ix86_cmodel_string, "kernel") && !flag_pic)
-       ix86_cmodel = CM_KERNEL;
-      else
-       error ("bad value (%s) for %scmodel=%s %s",
-              ix86_cmodel_string, prefix, suffix, sw);
+      switch (ix86_cmodel)
+       {
+       case CM_SMALL:
+       case CM_SMALL_PIC:
+         if (flag_pic)
+           ix86_cmodel = CM_SMALL_PIC;
+         if (!TARGET_64BIT)
+           error ("code model %qs not supported in the %s bit mode",
+                  "small", "32");
+         break;
+
+       case CM_MEDIUM:
+       case CM_MEDIUM_PIC:
+         if (flag_pic)
+           ix86_cmodel = CM_MEDIUM_PIC;
+         if (!TARGET_64BIT)
+           error ("code model %qs not supported in the %s bit mode",
+                  "medium", "32");
+         break;
+
+       case CM_LARGE:
+       case CM_LARGE_PIC:
+         if (flag_pic)
+           ix86_cmodel = CM_LARGE_PIC;
+         if (!TARGET_64BIT)
+           error ("code model %qs not supported in the %s bit mode",
+                  "large", "32");
+         break;
+
+       case CM_32:
+         if (flag_pic)
+           error ("code model %s does not support PIC mode", "32");
+         if (TARGET_64BIT)
+           error ("code model %qs not supported in the %s bit mode",
+                  "32", "64");
+         break;
+
+       case CM_KERNEL:
+         if (flag_pic)
+           {
+             error ("code model %s does not support PIC mode", "kernel");
+             ix86_cmodel = CM_32;
+           }
+         if (!TARGET_64BIT)
+           error ("code model %qs not supported in the %s bit mode",
+                  "kernel", "32");
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
     }
   else
     {
@@ -3619,20 +3639,11 @@ ix86_option_override_internal (bool main_args_p)
       else
         ix86_cmodel = CM_32;
     }
-  if (ix86_asm_string != 0)
+  if (TARGET_MACHO && ix86_asm_dialect == ASM_INTEL)
     {
-      if (! TARGET_MACHO
-         && !strcmp (ix86_asm_string, "intel"))
-       ix86_asm_dialect = ASM_INTEL;
-      else if (!strcmp (ix86_asm_string, "att"))
-       ix86_asm_dialect = ASM_ATT;
-      else
-       error ("bad value (%s) for %sasm=%s %s",
-              ix86_asm_string, prefix, suffix, sw);
+      error ("-masm=intel not supported in this configuration");
+      ix86_asm_dialect = ASM_ATT;
     }
-  if ((TARGET_64BIT == 0) != (ix86_cmodel == CM_32))
-    error ("code model %qs not supported in the %s bit mode",
-          ix86_cmodel_string, TARGET_64BIT ? "64" : "32");
   if ((TARGET_64BIT != 0) != ((ix86_isa_flags & OPTION_MASK_ISA_64BIT) != 0))
     sorry ("%i-bit mode not compiled in",
           (ix86_isa_flags & OPTION_MASK_ISA_64BIT) ? 64 : 32);
@@ -3852,67 +3863,19 @@ ix86_option_override_internal (bool main_args_p)
   init_machine_status = ix86_init_machine_status;
 
   /* Validate -mregparm= value.  */
-  if (ix86_regparm_string)
+  if (global_options_set.x_ix86_regparm)
     {
       if (TARGET_64BIT)
-       warning (0, "%sregparm%s is ignored in 64-bit mode", prefix, suffix);
-      i = atoi (ix86_regparm_string);
-      if (i < 0 || i > REGPARM_MAX)
-       error ("%sregparm=%d%s is not between 0 and %d",
-              prefix, i, suffix, REGPARM_MAX);
-      else
-       ix86_regparm = i;
-    }
-  if (TARGET_64BIT)
-    ix86_regparm = REGPARM_MAX;
-
-  /* If the user has provided any of the -malign-* options,
-     warn and use that value only if -falign-* is not set.
-     Remove this code in GCC 3.2 or later.  */
-  if (ix86_align_loops_string)
-    {
-      warning (0, "%salign-loops%s is obsolete, use -falign-loops%s",
-              prefix, suffix, suffix);
-      if (align_loops == 0)
-       {
-         i = atoi (ix86_align_loops_string);
-         if (i < 0 || i > MAX_CODE_ALIGN)
-           error ("%salign-loops=%d%s is not between 0 and %d",
-                  prefix, i, suffix, MAX_CODE_ALIGN);
-         else
-           align_loops = 1 << i;
-       }
-    }
-
-  if (ix86_align_jumps_string)
-    {
-      warning (0, "%salign-jumps%s is obsolete, use -falign-jumps%s",
-              prefix, suffix, suffix);
-      if (align_jumps == 0)
-       {
-         i = atoi (ix86_align_jumps_string);
-         if (i < 0 || i > MAX_CODE_ALIGN)
-           error ("%salign-loops=%d%s is not between 0 and %d",
-                  prefix, i, suffix, MAX_CODE_ALIGN);
-         else
-           align_jumps = 1 << i;
-       }
-    }
-
-  if (ix86_align_funcs_string)
-    {
-      warning (0, "%salign-functions%s is obsolete, use -falign-functions%s",
-              prefix, suffix, suffix);
-      if (align_functions == 0)
+       warning (0, "-mregparm is ignored in 64-bit mode");
+      if (ix86_regparm > REGPARM_MAX)
        {
-         i = atoi (ix86_align_funcs_string);
-         if (i < 0 || i > MAX_CODE_ALIGN)
-           error ("%salign-loops=%d%s is not between 0 and %d",
-                  prefix, i, suffix, MAX_CODE_ALIGN);
-         else
-           align_functions = 1 << i;
+         error ("-mregparm=%d is not between 0 and %d",
+                ix86_regparm, REGPARM_MAX);
+         ix86_regparm = 0;
        }
     }
+  if (TARGET_64BIT)
+    ix86_regparm = REGPARM_MAX;
 
   /* Default align_* from the processor table.  */
   if (align_loops == 0)
@@ -3930,42 +3893,9 @@ ix86_option_override_internal (bool main_args_p)
       align_functions = processor_target_table[ix86_tune].align_func;
     }
 
-  /* Validate -mbranch-cost= value, or provide default.  */
-  ix86_branch_cost = ix86_cost->branch_cost;
-  if (ix86_branch_cost_string)
-    {
-      i = atoi (ix86_branch_cost_string);
-      if (i < 0 || i > 5)
-       error ("%sbranch-cost=%d%s is not between 0 and 5", prefix, i, suffix);
-      else
-       ix86_branch_cost = i;
-    }
-  if (ix86_section_threshold_string)
-    {
-      i = atoi (ix86_section_threshold_string);
-      if (i < 0)
-       error ("%slarge-data-threshold=%d%s is negative", prefix, i, suffix);
-      else
-       ix86_section_threshold = i;
-    }
-
-  if (ix86_tls_dialect_string)
-    {
-      if (strcmp (ix86_tls_dialect_string, "gnu") == 0)
-       ix86_tls_dialect = TLS_DIALECT_GNU;
-      else if (strcmp (ix86_tls_dialect_string, "gnu2") == 0)
-       ix86_tls_dialect = TLS_DIALECT_GNU2;
-      else
-       error ("bad value (%s) for %stls-dialect=%s %s",
-              ix86_tls_dialect_string, prefix, suffix, sw);
-    }
-
-  if (ix87_precision_string)
-    {
-      i = atoi (ix87_precision_string);
-      if (i != 32 && i != 64 && i != 80)
-       error ("pc%d is not valid precision setting (32, 64 or 80)", i);
-    }
+  /* Provide default for -mbranch-cost= value.  */
+  if (!global_options_set.x_ix86_branch_cost)
+    ix86_branch_cost = ix86_cost->branch_cost;
 
   if (TARGET_64BIT)
     {
@@ -4017,6 +3947,13 @@ ix86_option_override_internal (bool main_args_p)
   if (!TARGET_80387)
     target_flags |= MASK_NO_FANCY_MATH_387;
 
+  /* On 32bit targets, avoid moving DFmode values in
+     integer registers when optimizing for size.  */
+  if (TARGET_64BIT)
+    target_flags |= TARGET_INTEGER_DFMODE_MOVES;
+  else if (optimize_size)
+    target_flags &= ~TARGET_INTEGER_DFMODE_MOVES;
+
   /* Turn on MMX builtins for -msse.  */
   if (TARGET_SSE)
     {
@@ -4031,23 +3968,24 @@ ix86_option_override_internal (bool main_args_p)
   /* Validate -mpreferred-stack-boundary= value or default it to
      PREFERRED_STACK_BOUNDARY_DEFAULT.  */
   ix86_preferred_stack_boundary = PREFERRED_STACK_BOUNDARY_DEFAULT;
-  if (ix86_preferred_stack_boundary_string)
+  if (global_options_set.x_ix86_preferred_stack_boundary_arg)
     {
       int min = (TARGET_64BIT ? 4 : 2);
       int max = (TARGET_SEH ? 4 : 12);
 
-      i = atoi (ix86_preferred_stack_boundary_string);
-      if (i < min || i > max)
+      if (ix86_preferred_stack_boundary_arg < min
+         || ix86_preferred_stack_boundary_arg > max)
        {
          if (min == max)
-           error ("%spreferred-stack-boundary%s is not supported "
-                  "for this target", prefix, suffix);
+           error ("-mpreferred-stack-boundary is not supported "
+                  "for this target");
          else
-           error ("%spreferred-stack-boundary=%d%s is not between %d and %d",
-                  prefix, i, suffix, min, max);
+           error ("-mpreferred-stack-boundary=%d is not between %d and %d",
+                  ix86_preferred_stack_boundary_arg, min, max);
        }
       else
-       ix86_preferred_stack_boundary = (1 << i) * BITS_PER_UNIT;
+       ix86_preferred_stack_boundary
+         = (1 << ix86_preferred_stack_boundary_arg) * BITS_PER_UNIT;
     }
 
   /* Set the default value for -mstackrealign.  */
@@ -4059,15 +3997,16 @@ ix86_option_override_internal (bool main_args_p)
   /* Validate -mincoming-stack-boundary= value or default it to
      MIN_STACK_BOUNDARY/PREFERRED_STACK_BOUNDARY.  */
   ix86_incoming_stack_boundary = ix86_default_incoming_stack_boundary;
-  if (ix86_incoming_stack_boundary_string)
+  if (global_options_set.x_ix86_incoming_stack_boundary_arg)
     {
-      i = atoi (ix86_incoming_stack_boundary_string);
-      if (i < (TARGET_64BIT ? 4 : 2) || i > 12)
+      if (ix86_incoming_stack_boundary_arg < (TARGET_64BIT ? 4 : 2)
+         || ix86_incoming_stack_boundary_arg > 12)
        error ("-mincoming-stack-boundary=%d is not between %d and 12",
-              i, TARGET_64BIT ? 4 : 2);
+              ix86_incoming_stack_boundary_arg, TARGET_64BIT ? 4 : 2);
       else
        {
-         ix86_user_incoming_stack_boundary = (1 << i) * BITS_PER_UNIT;
+         ix86_user_incoming_stack_boundary
+           = (1 << ix86_incoming_stack_boundary_arg) * BITS_PER_UNIT;
          ix86_incoming_stack_boundary
            = ix86_user_incoming_stack_boundary;
        }
@@ -4078,61 +4017,44 @@ ix86_option_override_internal (bool main_args_p)
       && ! 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 (ix86_fpmath & FPMATH_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 (!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)
     target_flags &= ~MASK_FLOAT_RETURNS;
 
   /* Use external vectorized library in vectorizing intrinsics.  */
-  if (ix86_veclibabi_string)
-    {
-      if (strcmp (ix86_veclibabi_string, "svml") == 0)
+  if (global_options_set.x_ix86_veclibabi_type)
+    switch (ix86_veclibabi_type)
+      {
+      case ix86_veclibabi_type_svml:
        ix86_veclib_handler = ix86_veclibabi_svml;
-      else if (strcmp (ix86_veclibabi_string, "acml") == 0)
+       break;
+
+      case ix86_veclibabi_type_acml:
        ix86_veclib_handler = ix86_veclibabi_acml;
-      else
-       error ("unknown vectorization library ABI type (%s) for "
-              "%sveclibabi=%s %s", ix86_veclibabi_string,
-              prefix, suffix, sw);
-    }
+       break;
+
+      default:
+       gcc_unreachable ();
+      }
 
   if ((!USE_IX86_FRAME_POINTER
        || (x86_accumulate_outgoing_args & ix86_tune_mask))
@@ -4169,8 +4091,9 @@ ix86_option_override_internal (bool main_args_p)
     }
 
   /* For sane SSE instruction set generation we need fcomi instruction.
-     It is safe to enable all CMOVE instructions.  */
-  if (TARGET_SSE)
+     It is safe to enable all CMOVE instructions.  Also, RDRAND intrinsic
+     expands to a sequence that includes conditional move. */
+  if (TARGET_SSE || TARGET_RDRND)
     TARGET_CMOVE = 1;
 
   /* Figure out what ASM_GENERATE_INTERNAL_LABEL builds as a prefix.  */
@@ -4205,7 +4128,7 @@ ix86_option_override_internal (bool main_args_p)
   if (flag_prefetch_loop_arrays < 0
       && HAVE_prefetch
       && optimize >= 3
-      && software_prefetching_beneficial_p ())
+      && TARGET_SOFTWARE_PREFETCHING_BENEFICIAL)
     flag_prefetch_loop_arrays = 1;
 
   /* If using typedef char *va_list, signal that __builtin_va_start (&ap, 0)
@@ -4268,11 +4191,6 @@ ix86_option_override_internal (bool main_args_p)
 #endif
    }
 
-  /* 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 ();
-
   if (TARGET_AVX)
     {
       /* When not optimize for size, enable vzeroupper optimization for
@@ -4294,6 +4212,12 @@ ix86_option_override_internal (bool main_args_p)
       /* Disable vzeroupper pass if TARGET_AVX is disabled.  */
       target_flags &= ~MASK_VZEROUPPER;
     }
+
+  /* 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 ();
 }
 
 /* Return TRUE if VAL is passed in register with 256bit AVX modes.  */
@@ -4416,7 +4340,6 @@ ix86_function_specific_save (struct cl_target_option *ptr)
   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;
@@ -4428,7 +4351,6 @@ ix86_function_specific_save (struct cl_target_option *ptr)
   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);
 }
 
@@ -4445,7 +4367,6 @@ ix86_function_specific_restore (struct cl_target_option *ptr)
   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;
@@ -4479,7 +4400,7 @@ ix86_function_specific_print (FILE *file, int indent,
 {
   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, "",
@@ -4495,9 +4416,6 @@ ix86_function_specific_print (FILE *file, int indent,
            ? 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)
@@ -4513,13 +4431,15 @@ ix86_function_specific_print (FILE *file, int indent,
    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 }
 
@@ -4529,6 +4449,7 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[])
     ix86_opt_yes,
     ix86_opt_no,
     ix86_opt_str,
+    ix86_opt_enum,
     ix86_opt_isa
   };
 
@@ -4565,9 +4486,11 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[])
     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 */
@@ -4608,7 +4531,8 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[])
 
       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;
@@ -4664,7 +4588,9 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[])
          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;
@@ -4712,6 +4638,23 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[])
            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 ();
     }
@@ -4726,17 +4669,21 @@ ix86_valid_target_attribute_tree (tree args)
 {
   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
@@ -4747,7 +4694,7 @@ ix86_valid_target_attribute_tree (tree args)
       || target_flags != def->x_target_flags
       || option_strings[IX86_FUNCTION_SPECIFIC_ARCH]
       || option_strings[IX86_FUNCTION_SPECIFIC_TUNE]
-      || option_strings[IX86_FUNCTION_SPECIFIC_FPMATH])
+      || enum_opts_set.x_ix86_fpmath)
     {
       /* If we are using the default tune= or arch=, undo the string assigned,
         and use the default.  */
@@ -4762,10 +4709,13 @@ ix86_valid_target_attribute_tree (tree args)
        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);
@@ -4779,7 +4729,7 @@ ix86_valid_target_attribute_tree (tree args)
 
       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++)
@@ -4877,7 +4827,7 @@ ix86_can_inline_p (tree caller, tree callee)
       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)
@@ -8659,17 +8609,17 @@ standard_sse_constant_opcode (rtx insn, rtx x)
       switch (get_attr_mode (insn))
        {
        case MODE_V4SF:
-         return TARGET_AVX ? "vxorps\t%0, %0, %0" : "xorps\t%0, %0";
+         return "%vxorps\t%0, %d0";
        case MODE_V2DF:
          if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
-           return TARGET_AVX ? "vxorps\t%0, %0, %0" : "xorps\t%0, %0";
+           return "%vxorps\t%0, %d0";
          else
-           return TARGET_AVX ? "vxorpd\t%0, %0, %0" : "xorpd\t%0, %0";
+           return "%vxorpd\t%0, %d0";
        case MODE_TI:
          if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
-           return TARGET_AVX ? "vxorps\t%0, %0, %0" : "xorps\t%0, %0";
+           return "%vxorps\t%0, %d0";
          else
-           return TARGET_AVX ? "vpxor\t%0, %0, %0" : "pxor\t%0, %0";
+           return "%vpxor\t%0, %d0";
        case MODE_V8SF:
          return "vxorps\t%x0, %x0, %x0";
        case MODE_V4DF:
@@ -8686,7 +8636,7 @@ standard_sse_constant_opcode (rtx insn, rtx x)
          break;
        }
     case 2:
-      return TARGET_AVX ? "vpcmpeqd\t%0, %0, %0" : "pcmpeqd\t%0, %0";
+      return "%vpcmpeqd\t%0, %d0";
     default:
       break;
     }
@@ -8820,6 +8770,10 @@ ix86_code_end (void)
   rtx xops[2];
   int regno;
 
+#ifdef TARGET_SOLARIS
+  solaris_code_end ();
+#endif
+
   for (regno = AX_REG; regno <= SP_REG; regno++)
     {
       char name[32];
@@ -8832,7 +8786,7 @@ ix86_code_end (void)
 
       decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
                         get_identifier (name),
-                        build_function_type (void_type_node, void_list_node));
+                        build_function_type_list (void_type_node, NULL_TREE));
       DECL_RESULT (decl) = build_decl (BUILTINS_LOCATION, RESULT_DECL,
                                       NULL_TREE, void_type_node);
       TREE_PUBLIC (decl) = 1;
@@ -9080,9 +9034,10 @@ ix86_select_alt_pic_regnum (void)
   return INVALID_REGNUM;
 }
 
-/* Return 1 if we need to save REGNO.  */
-static int
-ix86_save_reg (unsigned int regno, int maybe_eh_return)
+/* Return TRUE if we need to save REGNO.  */
+
+static bool
+ix86_save_reg (unsigned int regno, bool maybe_eh_return)
 {
   if (pic_offset_table_rtx
       && regno == REAL_PIC_OFFSET_TABLE_REGNUM
@@ -9090,11 +9045,7 @@ ix86_save_reg (unsigned int regno, int maybe_eh_return)
          || crtl->profile
          || crtl->calls_eh_return
          || crtl->uses_const_pool))
-    {
-      if (ix86_select_alt_pic_regnum () != INVALID_REGNUM)
-       return 0;
-      return 1;
-    }
+    return ix86_select_alt_pic_regnum () == INVALID_REGNUM;
 
   if (crtl->calls_eh_return && maybe_eh_return)
     {
@@ -9105,12 +9056,12 @@ ix86_save_reg (unsigned int regno, int maybe_eh_return)
          if (test == INVALID_REGNUM)
            break;
          if (test == regno)
-           return 1;
+           return true;
        }
     }
 
   if (crtl->drap_reg && regno == REGNO (crtl->drap_reg))
-    return 1;
+    return true;
 
   return (df_regs_ever_live_p (regno)
          && !call_used_regs[regno]
@@ -10595,7 +10546,7 @@ ix86_expand_prologue (void)
 
   allocate = frame.stack_pointer_offset - m->fs.sp_offset;
 
-  if (flag_stack_usage)
+  if (flag_stack_usage_info)
     {
       /* We start to count from ARG_POINTER.  */
       HOST_WIDE_INT stack_size = frame.stack_pointer_offset;
@@ -10914,7 +10865,7 @@ ix86_emit_leave (void)
    First register is restored from CFA - CFA_OFFSET.  */
 static void
 ix86_emit_restore_regs_using_mov (HOST_WIDE_INT cfa_offset,
-                                 int maybe_eh_return)
+                                 bool maybe_eh_return)
 {
   struct machine_function *m = cfun->machine;
   unsigned int regno;
@@ -10953,7 +10904,7 @@ ix86_emit_restore_regs_using_mov (HOST_WIDE_INT cfa_offset,
    First register is restored from CFA - CFA_OFFSET.  */
 static void
 ix86_emit_restore_sse_regs_using_mov (HOST_WIDE_INT cfa_offset,
-                                     int maybe_eh_return)
+                                     bool maybe_eh_return)
 {
   unsigned int regno;
 
@@ -11572,7 +11523,7 @@ ix86_expand_split_stack_prologue (void)
     }
   call_insn = ix86_expand_call (NULL_RTX, gen_rtx_MEM (QImode, fn),
                                GEN_INT (UNITS_PER_WORD), constm1_rtx,
-                               NULL_RTX, 0);
+                               NULL_RTX, false);
   add_function_usage_to (call_insn, call_fusage);
 
   /* In order to make call/return prediction work right, we now need
@@ -12673,7 +12624,7 @@ legitimize_pic_address (rtx orig, rtx reg)
 /* Load the thread pointer.  If TO_REG is true, force it into a register.  */
 
 static rtx
-get_thread_pointer (int to_reg)
+get_thread_pointer (bool to_reg)
 {
   rtx tp, reg, insn;
 
@@ -12688,76 +12639,154 @@ get_thread_pointer (int to_reg)
   return reg;
 }
 
+/* Construct the SYMBOL_REF for the tls_get_addr function.  */
+
+static GTY(()) rtx ix86_tls_symbol;
+
+static rtx
+ix86_tls_get_addr (void)
+{
+  if (!ix86_tls_symbol)
+    {
+      const char *sym
+       = ((TARGET_ANY_GNU_TLS && !TARGET_64BIT)
+          ? "___tls_get_addr" : "__tls_get_addr");
+
+      ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, sym);
+    }
+
+  return ix86_tls_symbol;
+}
+
+/* Construct the SYMBOL_REF for the _TLS_MODULE_BASE_ symbol.  */
+
+static GTY(()) rtx ix86_tls_module_base_symbol;
+
+rtx
+ix86_tls_module_base (void)
+{
+  if (!ix86_tls_module_base_symbol)
+    {
+      ix86_tls_module_base_symbol
+       = gen_rtx_SYMBOL_REF (Pmode, "_TLS_MODULE_BASE_");
+
+      SYMBOL_REF_FLAGS (ix86_tls_module_base_symbol)
+       |= TLS_MODEL_GLOBAL_DYNAMIC << SYMBOL_FLAG_TLS_SHIFT;
+    }
+
+  return ix86_tls_module_base_symbol;
+}
+
 /* A subroutine of ix86_legitimize_address and ix86_expand_move.  FOR_MOV is
    false if we expect this to be used for a memory address and true if
    we expect to load the address into a register.  */
 
 static rtx
-legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
+legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
 {
-  rtx dest, base, off, pic, tp;
+  rtx dest, base, off;
+  rtx pic = NULL_RTX, tp = NULL_RTX;
   int type;
 
   switch (model)
     {
     case TLS_MODEL_GLOBAL_DYNAMIC:
       dest = gen_reg_rtx (Pmode);
-      tp = TARGET_GNU2_TLS ? get_thread_pointer (1) : 0;
 
-      if (TARGET_64BIT && ! TARGET_GNU2_TLS)
+      if (!TARGET_64BIT)
        {
-         rtx rax = gen_rtx_REG (Pmode, AX_REG), insns;
-
-         start_sequence ();
-         emit_call_insn (gen_tls_global_dynamic_64 (rax, x));
-         insns = get_insns ();
-         end_sequence ();
-
-         RTL_CONST_CALL_P (insns) = 1;
-         emit_libcall_block (insns, dest, rax, x);
+         if (flag_pic)
+           pic = pic_offset_table_rtx;
+         else
+           {
+             pic = gen_reg_rtx (Pmode);
+             emit_insn (gen_set_got (pic));
+           }
        }
-      else if (TARGET_64BIT && TARGET_GNU2_TLS)
-       emit_insn (gen_tls_global_dynamic_64 (dest, x));
-      else
-       emit_insn (gen_tls_global_dynamic_32 (dest, x));
 
       if (TARGET_GNU2_TLS)
        {
+         if (TARGET_64BIT)
+           emit_insn (gen_tls_dynamic_gnu2_64 (dest, x));
+         else
+           emit_insn (gen_tls_dynamic_gnu2_32 (dest, x, pic));
+
+         tp = get_thread_pointer (true);
          dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, tp, dest));
 
          set_unique_reg_note (get_last_insn (), REG_EQUIV, x);
        }
+      else
+       {
+         rtx caddr = ix86_tls_get_addr ();
+
+         if (TARGET_64BIT)
+           {
+             rtx rax = gen_rtx_REG (Pmode, AX_REG), insns;
+
+             start_sequence ();
+             emit_call_insn (gen_tls_global_dynamic_64 (rax, x, caddr));
+             insns = get_insns ();
+             end_sequence ();
+
+             RTL_CONST_CALL_P (insns) = 1;
+             emit_libcall_block (insns, dest, rax, x);
+           }
+         else
+           emit_insn (gen_tls_global_dynamic_32 (dest, x, pic, caddr));
+       }
       break;
 
     case TLS_MODEL_LOCAL_DYNAMIC:
       base = gen_reg_rtx (Pmode);
-      tp = TARGET_GNU2_TLS ? get_thread_pointer (1) : 0;
 
-      if (TARGET_64BIT && ! TARGET_GNU2_TLS)
+      if (!TARGET_64BIT)
        {
-         rtx rax = gen_rtx_REG (Pmode, AX_REG), insns, note;
-
-         start_sequence ();
-         emit_call_insn (gen_tls_local_dynamic_base_64 (rax));
-         insns = get_insns ();
-         end_sequence ();
-
-         note = gen_rtx_EXPR_LIST (VOIDmode, const0_rtx, NULL);
-         note = gen_rtx_EXPR_LIST (VOIDmode, ix86_tls_get_addr (), note);
-         RTL_CONST_CALL_P (insns) = 1;
-         emit_libcall_block (insns, base, rax, note);
+         if (flag_pic)
+           pic = pic_offset_table_rtx;
+         else
+           {
+             pic = gen_reg_rtx (Pmode);
+             emit_insn (gen_set_got (pic));
+           }
        }
-      else if (TARGET_64BIT && TARGET_GNU2_TLS)
-       emit_insn (gen_tls_local_dynamic_base_64 (base));
-      else
-       emit_insn (gen_tls_local_dynamic_base_32 (base));
 
       if (TARGET_GNU2_TLS)
        {
-         rtx x = ix86_tls_module_base ();
+         rtx tmp = ix86_tls_module_base ();
+
+         if (TARGET_64BIT)
+           emit_insn (gen_tls_dynamic_gnu2_64 (base, tmp));
+         else
+           emit_insn (gen_tls_dynamic_gnu2_32 (base, tmp, pic));
 
+         tp = get_thread_pointer (true);
          set_unique_reg_note (get_last_insn (), REG_EQUIV,
-                              gen_rtx_MINUS (Pmode, x, tp));
+                              gen_rtx_MINUS (Pmode, tmp, tp));
+       }
+      else
+       {
+         rtx caddr = ix86_tls_get_addr ();
+
+         if (TARGET_64BIT)
+           {
+             rtx rax = gen_rtx_REG (Pmode, AX_REG), insns, eqv;
+
+             start_sequence ();
+             emit_call_insn (gen_tls_local_dynamic_base_64 (rax, caddr));
+             insns = get_insns ();
+             end_sequence ();
+
+             /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
+                share the LD_BASE result with other LD model accesses.  */
+             eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+                                   UNSPEC_TLS_LD_BASE);
+
+             RTL_CONST_CALL_P (insns) = 1;
+             emit_libcall_block (insns, base, rax, eqv);
+           }
+         else
+           emit_insn (gen_tls_local_dynamic_base_32 (base, pic, caddr));
        }
 
       off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPOFF);
@@ -12771,7 +12800,6 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
 
          set_unique_reg_note (get_last_insn (), REG_EQUIV, x);
        }
-
       break;
 
     case TLS_MODEL_INITIAL_EXEC:
@@ -13890,6 +13918,7 @@ get_some_local_dynamic_name (void)
    d -- print duplicated register operand for AVX instruction.
    D -- print condition for SSE cmp instruction.
    P -- if PIC, print an @PLT suffix.
+   p -- print raw symbol name.
    X -- don't print any sort of PIC '@' suffix for a symbol.
    & -- print some in-use local-dynamic symbol name.
    H -- print a memory address offset by 8; used for sse high-parts
@@ -14095,6 +14124,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
        case 'x':
        case 'X':
        case 'P':
+       case 'p':
          break;
 
        case 's':
@@ -14494,7 +14524,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
          x = const0_rtx;
        }
 
-      if (code != 'P')
+      if (code != 'P' && code != 'p')
        {
          if (CONST_INT_P (x) || GET_CODE (x) == CONST_DOUBLE)
            {
@@ -15174,7 +15204,7 @@ emit_i387_cw_initialization (int mode)
    operand may be [SDX]Fmode.  */
 
 const char *
-output_fix_trunc (rtx insn, rtx *operands, int fisttp)
+output_fix_trunc (rtx insn, rtx *operands, bool fisttp)
 {
   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
   int dimode_p = GET_MODE (operands[0]) == DImode;
@@ -15239,7 +15269,7 @@ output_387_ffreep (rtx *operands ATTRIBUTE_UNUSED, int opno)
    should be used.  UNORDERED_P is true when fucom should be used.  */
 
 const char *
-output_fp_compare (rtx insn, rtx *operands, int eflags_p, int unordered_p)
+output_fp_compare (rtx insn, rtx *operands, bool eflags_p, bool unordered_p)
 {
   int stack_top_dies;
   rtx cmp_op0, cmp_op1;
@@ -17299,11 +17329,15 @@ ix86_match_ccmode (rtx insn, enum machine_mode req_mode)
       if (req_mode == CCZmode)
        return false;
       /* FALLTHRU */
+    case CCZmode:
+      break;
+
     case CCAmode:
     case CCCmode:
     case CCOmode:
     case CCSmode:
-    case CCZmode:
+      if (set_mode != req_mode)
+       return false;
       break;
 
     default:
@@ -20809,8 +20843,8 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
     algs = &cost->memset[TARGET_64BIT != 0];
   else
     algs = &cost->memcpy[TARGET_64BIT != 0];
-  if (stringop_alg != no_stringop && ALG_USABLE_P (stringop_alg))
-    return stringop_alg;
+  if (ix86_stringop_alg != no_stringop && ALG_USABLE_P (ix86_stringop_alg))
+    return ix86_stringop_alg;
   /* rep; movq or rep; movl is the smallest variant.  */
   else if (!optimize_for_speed)
     {
@@ -21935,7 +21969,7 @@ construct_plt_address (rtx symbol)
 rtx
 ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
                  rtx callarg2,
-                 rtx pop, int sibcall)
+                 rtx pop, bool sibcall)
 {
   rtx use = NULL, call;
 
@@ -22067,23 +22101,25 @@ ix86_split_call_vzeroupper (rtx insn, rtx vzeroupper)
 /* Output the assembly for a call instruction.  */
 
 const char *
-ix86_output_call_insn (rtx insn, rtx call_op, int addr_op)
+ix86_output_call_insn (rtx insn, rtx call_op)
 {
   bool direct_p = constant_call_address_operand (call_op, Pmode);
   bool seh_nop_p = false;
-
-  gcc_assert (addr_op == 0 || addr_op == 1);
+  const char *xasm;
 
   if (SIBLING_CALL_P (insn))
     {
       if (direct_p)
-       return addr_op ? "jmp\t%P1" : "jmp\t%P0";
+       xasm = "jmp\t%P0";
       /* SEH epilogue detection requires the indirect branch case
         to include REX.W.  */
       else if (TARGET_SEH)
-       return addr_op ? "rex.W jmp %A1" : "rex.W jmp %A0";
+       xasm = "rex.W jmp %A0";
       else
-       return addr_op ? "jmp\t%A1" : "jmp\t%A0";
+       xasm = "jmp\t%A0";
+
+      output_asm_insn (xasm, &call_op);
+      return "";
     }
 
   /* SEH unwinding can require an extra nop to be emitted in several
@@ -22117,19 +22153,16 @@ ix86_output_call_insn (rtx insn, rtx call_op, int addr_op)
     }
 
   if (direct_p)
-    {
-      if (seh_nop_p)
-       return addr_op ? "call\t%P1\n\tnop" : "call\t%P0\n\tnop";
-      else
-       return addr_op ? "call\t%P1" : "call\t%P0";
-    }
+    xasm = "call\t%P0";
   else
-    {
-      if (seh_nop_p)
-       return addr_op ? "call\t%A1\n\tnop" : "call\t%A0\n\tnop";
-      else
-       return addr_op ? "call\t%A1" : "call\t%A0";
-    }
+    xasm = "call\t%A0";
+
+  output_asm_insn (xasm, &call_op);
+
+  if (seh_nop_p)
+    return "nop";
+
+  return "";
 }
 \f
 /* Clear stack slot assignments remembered from previous functions.
@@ -22178,43 +22211,6 @@ assign_386_stack_local (enum machine_mode mode, enum ix86_stack_slot n)
   ix86_stack_locals = s;
   return s->rtl;
 }
-
-/* Construct the SYMBOL_REF for the tls_get_addr function.  */
-
-static GTY(()) rtx ix86_tls_symbol;
-rtx
-ix86_tls_get_addr (void)
-{
-
-  if (!ix86_tls_symbol)
-    {
-      ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode,
-                                           (TARGET_ANY_GNU_TLS
-                                            && !TARGET_64BIT)
-                                           ? "___tls_get_addr"
-                                           : "__tls_get_addr");
-    }
-
-  return ix86_tls_symbol;
-}
-
-/* Construct the SYMBOL_REF for the _TLS_MODULE_BASE_ symbol.  */
-
-static GTY(()) rtx ix86_tls_module_base_symbol;
-rtx
-ix86_tls_module_base (void)
-{
-
-  if (!ix86_tls_module_base_symbol)
-    {
-      ix86_tls_module_base_symbol = gen_rtx_SYMBOL_REF (Pmode,
-                                                       "_TLS_MODULE_BASE_");
-      SYMBOL_REF_FLAGS (ix86_tls_module_base_symbol)
-       |= TLS_MODEL_GLOBAL_DYNAMIC << SYMBOL_FLAG_TLS_SHIFT;
-    }
-
-  return ix86_tls_module_base_symbol;
-}
 \f
 /* Calculate the length of the memory address in the instruction
    encoding.  Does not include the one-byte modrm, opcode, or prefix.  */
@@ -22338,7 +22334,7 @@ memory_address_length (rtx addr)
 /* Compute default value for "length_immediate" attribute.  When SHORTFORM
    is set, expect that insn have 8bit immediate alternative.  */
 int
-ix86_attr_length_immediate_default (rtx insn, int shortform)
+ix86_attr_length_immediate_default (rtx insn, bool shortform)
 {
   int len = 0;
   int i;
@@ -22448,8 +22444,7 @@ ix86_attr_length_address_default (rtx insn)
    2 or 3 byte VEX prefix and 1 opcode byte.  */
 
 int
-ix86_attr_length_vex_default (rtx insn, int has_0f_opcode,
-                             int has_vex_w)
+ix86_attr_length_vex_default (rtx insn, bool has_0f_opcode, bool has_vex_w)
 {
   int i;
 
@@ -22516,10 +22511,10 @@ ix86_issue_rate (void)
     }
 }
 
-/* A subroutine of ix86_adjust_cost -- return true iff INSN reads flags set
+/* A subroutine of ix86_adjust_cost -- return TRUE iff INSN reads flags set
    by DEP_INSN and nothing set by DEP_INSN.  */
 
-static int
+static bool
 ix86_flags_dependent (rtx insn, rtx dep_insn, enum attr_type insn_type)
 {
   rtx set, set2;
@@ -22529,7 +22524,7 @@ ix86_flags_dependent (rtx insn, rtx dep_insn, enum attr_type insn_type)
       && insn_type != TYPE_ICMOV
       && insn_type != TYPE_FCMOV
       && insn_type != TYPE_IBR)
-    return 0;
+    return false;
 
   if ((set = single_set (dep_insn)) != 0)
     {
@@ -22545,20 +22540,20 @@ ix86_flags_dependent (rtx insn, rtx dep_insn, enum attr_type insn_type)
       set2 = SET_DEST (XVECEXP (PATTERN (dep_insn), 0, 0));
     }
   else
-    return 0;
+    return false;
 
   if (!REG_P (set) || REGNO (set) != FLAGS_REG)
-    return 0;
+    return false;
 
   /* This test is true if the dependent insn reads the flags but
      not any other potentially set register.  */
   if (!reg_overlap_mentioned_p (set, PATTERN (insn)))
-    return 0;
+    return false;
 
   if (set2 && reg_overlap_mentioned_p (set2, PATTERN (insn)))
-    return 0;
+    return false;
 
-  return 1;
+  return true;
 }
 
 /* Return true iff USE_INSN has a memory address with operands set by
@@ -23919,6 +23914,7 @@ enum ix86_builtins
   IX86_BUILTIN_CLFLUSH,
   IX86_BUILTIN_MFENCE,
   IX86_BUILTIN_LFENCE,
+  IX86_BUILTIN_PAUSE,
 
   IX86_BUILTIN_BSRSI,
   IX86_BUILTIN_BSRDI,
@@ -24671,6 +24667,7 @@ static const struct builtin_description bdesc_special_args[] =
 {
   { ~OPTION_MASK_ISA_64BIT, CODE_FOR_rdtsc, "__builtin_ia32_rdtsc", IX86_BUILTIN_RDTSC, UNKNOWN, (int) UINT64_FTYPE_VOID },
   { ~OPTION_MASK_ISA_64BIT, CODE_FOR_rdtscp, "__builtin_ia32_rdtscp", IX86_BUILTIN_RDTSCP, UNKNOWN, (int) UINT64_FTYPE_PUNSIGNED },
+  { ~OPTION_MASK_ISA_64BIT, CODE_FOR_pause, "__builtin_ia32_pause", IX86_BUILTIN_PAUSE, UNKNOWN, (int) VOID_FTYPE_VOID },
 
   /* MMX */
   { OPTION_MASK_ISA_MMX, CODE_FOR_mmx_emms, "__builtin_ia32_emms", IX86_BUILTIN_EMMS, UNKNOWN, (int) VOID_FTYPE_VOID },
@@ -27410,7 +27407,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
       && !(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);
@@ -27622,6 +27619,12 @@ rdrand_step:
       op0 = gen_reg_rtx (mode0);
       emit_insn (GEN_FCN (icode) (op0));
 
+      arg0 = CALL_EXPR_ARG (exp, 0);
+      op1 = expand_normal (arg0);
+      if (!address_operand (op1, VOIDmode))
+       op1 = copy_addr_to_reg (op1);
+      emit_move_insn (gen_rtx_MEM (mode0, op1), op0);
+
       op1 = gen_reg_rtx (SImode);
       emit_move_insn (op1, CONST1_RTX (SImode));
 
@@ -27636,17 +27639,13 @@ rdrand_step:
       else
        op2 = gen_rtx_SUBREG (SImode, op0, 0);
 
+      if (target == 0)
+       target = gen_reg_rtx (SImode);
+
       pat = gen_rtx_GEU (VOIDmode, gen_rtx_REG (CCCmode, FLAGS_REG),
                         const0_rtx);
-      emit_insn (gen_rtx_SET (VOIDmode, op1,
+      emit_insn (gen_rtx_SET (VOIDmode, target,
                              gen_rtx_IF_THEN_ELSE (SImode, pat, op2, op1)));
-      emit_move_insn (target, op1);
-
-      arg0 = CALL_EXPR_ARG (exp, 0);
-      op1 = expand_normal (arg0);
-      if (!address_operand (op1, VOIDmode))
-       op1 = copy_addr_to_reg (op1);
-      emit_move_insn (gen_rtx_MEM (mode0, op1), op0);
       return target;
 
     default:
@@ -28520,7 +28519,7 @@ ix86_preferred_reload_class (rtx x, reg_class_t regclass)
         zero above.  We only want to wind up preferring 80387 registers if
         we plan on doing computation with them.  */
       if (TARGET_80387
-         && standard_80387_constant_p (x))
+         && standard_80387_constant_p (x) > 0)
        {
          /* Limit class to non-sse.  */
          if (regclass == FLOAT_SSE_REGS)
@@ -28971,7 +28970,8 @@ ix86_register_move_cost (enum machine_mode mode, reg_class_t class1_i,
   return 2;
 }
 
-/* Return 1 if hard register REGNO can hold a value of machine-mode MODE.  */
+/* Return TRUE if hard register REGNO can hold a value of machine-mode
+   MODE.  */
 
 bool
 ix86_hard_regno_mode_ok (int regno, enum machine_mode mode)
@@ -28982,7 +28982,7 @@ ix86_hard_regno_mode_ok (int regno, enum machine_mode mode)
   if (GET_MODE_CLASS (mode) == MODE_CC
       || GET_MODE_CLASS (mode) == MODE_RANDOM
       || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
-    return 0;
+    return false;
   if (FP_REGNO_P (regno))
     return VALID_FP_MODE_P (mode);
   if (SSE_REGNO_P (regno))
@@ -29012,26 +29012,26 @@ ix86_hard_regno_mode_ok (int regno, enum machine_mode mode)
       /* Take care for QImode values - they can be in non-QI regs,
         but then they do cause partial register stalls.  */
       if (regno <= BX_REG || TARGET_64BIT)
-       return 1;
+       return true;
       if (!TARGET_PARTIAL_REG_STALL)
-       return 1;
-      return reload_in_progress || reload_completed;
+       return true;
+      return !can_create_pseudo_p ();
     }
   /* We handle both integer and floats in the general purpose registers.  */
   else if (VALID_INT_MODE_P (mode))
-    return 1;
+    return true;
   else if (VALID_FP_MODE_P (mode))
-    return 1;
+    return true;
   else if (VALID_DFP_MODE_P (mode))
-    return 1;
+    return true;
   /* Lots of MMX code casts 8 byte vector modes to DImode.  If we then go
      on to use that value in smaller contexts, this can easily force a
      pseudo to be allocated to GENERAL_REGS.  Since this is no worse than
      supporting DImode, allow it.  */
   else if (VALID_MMX_REG_MODE_3DNOW (mode) || VALID_MMX_REG_MODE (mode))
-    return 1;
+    return true;
 
-  return 0;
+  return false;
 }
 
 /* A subroutine of ix86_modes_tieable_p.  Return true if MODE is a
@@ -30440,6 +30440,10 @@ ix86_reorg (void)
      with old MDEP_REORGS that are not CFG based.  Recompute it now.  */
   compute_bb_for_insn ();
 
+  /* Run the vzeroupper optimization if needed.  */
+  if (TARGET_VZEROUPPER)
+    move_or_delete_vzeroupper ();
+
   if (optimize && optimize_function_for_speed_p (cfun))
     {
       if (TARGET_PAD_SHORT_FUNCTION)
@@ -30451,10 +30455,6 @@ ix86_reorg (void)
        ix86_avoid_jump_mispredicts ();
 #endif
     }
-
-  /* Run the vzeroupper optimization if needed.  */
-  if (TARGET_VZEROUPPER)
-    move_or_delete_vzeroupper ();
 }
 
 /* Return nonzero when QImode register that must be represented via REX prefix
@@ -32160,9 +32160,10 @@ void ix86_emit_swsqrtsf (rtx res, rtx a, enum machine_mode mode,
                          gen_rtx_MULT (mode, e2, e3)));
 }
 
+#ifdef TARGET_SOLARIS
 /* Solaris implementation of TARGET_ASM_NAMED_SECTION.  */
 
-static void ATTRIBUTE_UNUSED
+static void
 i386_solaris_elf_named_section (const char *name, unsigned int flags,
                                tree decl)
 {
@@ -32176,8 +32177,18 @@ i386_solaris_elf_named_section (const char *name, unsigned int flags,
               flags & SECTION_WRITE ? "aw" : "a");
       return;
     }
+
+#ifndef USE_GAS
+  if (HAVE_COMDAT_GROUP && flags & SECTION_LINKONCE)
+    {
+      solaris_elf_asm_comdat_section (name, flags, decl);
+      return;
+    }
+#endif
+
   default_elf_asm_named_section (name, flags, decl);
 }
+#endif /* TARGET_SOLARIS */
 
 /* Return the mangling of TYPE if it is an extended fundamental type.  */
 
@@ -35130,32 +35141,38 @@ has_dispatch (rtx insn, int action)
 static enum machine_mode
 ix86_preferred_simd_mode (enum machine_mode mode)
 {
-  /* Disable double precision vectorizer if needed.  */
-  if (mode == DFmode && !TARGET_VECTORIZE_DOUBLE)
-    return word_mode;
-
-  if (!TARGET_AVX && !TARGET_SSE)
+  if (!TARGET_SSE)
     return word_mode;
 
   switch (mode)
     {
-    case SFmode:
-      return (TARGET_AVX && !flag_prefer_avx128) ? V8SFmode : V4SFmode;
-    case DFmode:
-      return (TARGET_AVX && !flag_prefer_avx128) ? V4DFmode : V2DFmode;
-    case DImode:
-      return V2DImode;
-    case SImode:
-      return V4SImode;
-    case HImode:
-      return V8HImode;
     case QImode:
       return V16QImode;
+    case HImode:
+      return V8HImode;
+    case SImode:
+      return V4SImode;
+    case DImode:
+      return V2DImode;
 
-    default:;
-    }
+    case SFmode:
+      if (TARGET_AVX && !flag_prefer_avx128)
+       return V8SFmode;
+      else
+       return V4SFmode;
+
+    case DFmode:
+      if (!TARGET_VECTORIZE_DOUBLE)
+       return word_mode;
+      else if (TARGET_AVX && !flag_prefer_avx128)
+       return V4DFmode;
+      else if (TARGET_SSE2)
+       return V2DFmode;
+      /* FALLTHRU */
 
-  return word_mode;
+    default:
+      return word_mode;
+    }
 }
 
 /* If AVX is enabled then try vectorizing with both 256bit and 128bit
@@ -35164,7 +35181,7 @@ ix86_preferred_simd_mode (enum machine_mode mode)
 static unsigned int
 ix86_autovectorize_vector_sizes (void)
 {
-  return TARGET_AVX ? 32 | 16 : 0;
+  return (TARGET_AVX && !flag_prefer_avx128) ? 32 | 16 : 0;
 }
 
 /* Initialize the GCC target structure.  */