OSDN Git Service

2011-05-27 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.c
index a66a0c4..ae81d62 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines used for code generation on IA-32.
    Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -56,26 +56,31 @@ along with GCC; see the file COPYING3.  If not see
 #include "debug.h"
 #include "dwarf2out.h"
 #include "sched-int.h"
+#include "sbitmap.h"
+#include "fibheap.h"
+#include "opts.h"
+#include "diagnostic.h"
 
 enum upper_128bits_state
 {
-  unknown = 0,         /* Unknown.  */
-  unused,              /* Not used or not referenced.  */
-  used                 /* Used or referenced.  */
+  unknown = 0,
+  unused,
+  used
 };
 
 typedef struct block_info_def
 {
-  /* State of the upper 128bits of any AVX registers at exit.  */
+  /* State of the upper 128bits of AVX registers at exit.  */
   enum upper_128bits_state state;
-  /* If the upper 128bits of any AVX registers are referenced.  */
-  enum upper_128bits_state referenced;
-  /* Number of vzerouppers in this block.  */
-  unsigned int count;
+  /* TRUE if state of the upper 128bits of AVX registers is unchanged
+     in this block.  */
+  bool unchanged;
   /* TRUE if block has been processed.  */
   bool processed;
-  /* TRUE if block has been rescanned.  */
-  bool rescanned;
+  /* TRUE if block has been scanned.  */
+  bool scanned;
+  /* Previous state of the upper 128bits of AVX registers at entry.  */
+  enum upper_128bits_state prev;
 } *block_info;
 
 #define BLOCK_INFO(B)   ((block_info) (B)->aux)
@@ -116,8 +121,7 @@ check_avx256_stores (rtx dest, const_rtx set, void *data)
    in basic block BB.  Delete it if upper 128bit AVX registers are
    unused.  If it isn't deleted, move it to just before a jump insn.
    
-   UPPER_128BITS_LIVE is TRUE if the upper 128bits of any AVX registers
-   are live at entry.  */
+   STATE is state of the upper 128bits of AVX registers at entry.  */
 
 static void
 move_or_delete_vzeroupper_2 (basic_block bb,
@@ -127,13 +131,34 @@ move_or_delete_vzeroupper_2 (basic_block bb,
   rtx vzeroupper_insn = NULL_RTX;
   rtx pat;
   int avx256;
-  enum upper_128bits_state referenced = BLOCK_INFO (bb)->referenced;
-  int count = BLOCK_INFO (bb)->count;
+  bool unchanged;
+
+  if (BLOCK_INFO (bb)->unchanged)
+    {
+      if (dump_file)
+       fprintf (dump_file, " [bb %i] unchanged: upper 128bits: %d\n",
+                bb->index, state);
+
+      BLOCK_INFO (bb)->state = state;
+      return;
+    }
+
+  if (BLOCK_INFO (bb)->scanned && BLOCK_INFO (bb)->prev == state)
+    {
+      if (dump_file)
+       fprintf (dump_file, " [bb %i] scanned: upper 128bits: %d\n",
+                bb->index, BLOCK_INFO (bb)->state);
+      return;
+    }
+
+  BLOCK_INFO (bb)->prev = state;
 
   if (dump_file)
-    fprintf (dump_file, " BB [%i] entry: upper 128bits: %d\n",
+    fprintf (dump_file, " [bb %i] entry: upper 128bits: %d\n",
             bb->index, state);
 
+  unchanged = true;
+
   /* BB_END changes when it is deleted.  */
   bb_end = BB_END (bb);
   insn = BB_HEAD (bb);
@@ -187,28 +212,25 @@ move_or_delete_vzeroupper_2 (basic_block bb,
              && XINT (XVECEXP (pat, 0, 0), 1) == UNSPECV_VZEROALL)
            {
              state = unused;
+             unchanged = false;
 
              /* Delete pending vzeroupper insertion.  */
              if (vzeroupper_insn)
                {
-                 count--;
                  delete_insn (vzeroupper_insn);
                  vzeroupper_insn = NULL_RTX;
                }
            }
-         else if (state != used && referenced != unused)
+         else if (state != used)
            {
-             /* No need to call note_stores if the upper 128bits of
-                AVX registers are never referenced.  */
              note_stores (pat, check_avx256_stores, &state);
              if (state == used)
-               referenced = used;
+               unchanged = false;
            }
          continue;
        }
 
       /* Process vzeroupper intrinsic.  */
-      count++;
       avx256 = INTVAL (XVECEXP (pat, 0, 0));
 
       if (state == unused)
@@ -217,7 +239,10 @@ move_or_delete_vzeroupper_2 (basic_block bb,
             256bit AVX register.  We only need to check if callee
             returns 256bit AVX register.  */
          if (avx256 == callee_return_avx256)
-           state = used;
+           {
+             state = used;
+             unchanged = false;
+           }
 
          /* Remove unnecessary vzeroupper since upper 128bits are
             cleared.  */
@@ -226,7 +251,6 @@ move_or_delete_vzeroupper_2 (basic_block bb,
              fprintf (dump_file, "Delete redundant vzeroupper:\n");
              print_rtl_single (dump_file, insn);
            }
-         count--;
          delete_insn (insn);
        }
       else
@@ -246,122 +270,88 @@ move_or_delete_vzeroupper_2 (basic_block bb,
                  fprintf (dump_file, "Delete callee pass vzeroupper:\n");
                  print_rtl_single (dump_file, insn);
                }
-             count--;
              delete_insn (insn);
            }
          else
-           vzeroupper_insn = insn;
+           {
+             vzeroupper_insn = insn;
+             unchanged = false;
+           }
        }
     }
 
   BLOCK_INFO (bb)->state = state;
-
-  if (BLOCK_INFO (bb)->referenced == unknown)
-    {
-      /* The upper 128bits of AVX registers are never referenced if
-        REFERENCED isn't updated.  */
-      if (referenced == unknown)
-       referenced = unused;
-      BLOCK_INFO (bb)->referenced = referenced;
-      BLOCK_INFO (bb)->count = count;
-    }
+  BLOCK_INFO (bb)->unchanged = unchanged;
+  BLOCK_INFO (bb)->scanned = true;
 
   if (dump_file)
-    fprintf (dump_file, " BB [%i] exit: upper 128bits: %d\n",
-            bb->index, state);
+    fprintf (dump_file, " [bb %i] exit: %s: upper 128bits: %d\n",
+            bb->index, unchanged ? "unchanged" : "changed",
+            state);
 }
 
 /* Helper function for move_or_delete_vzeroupper.  Process vzeroupper
-   in BLOCK and its predecessor blocks recursively.  */
+   in BLOCK and check its predecessor blocks.  Treat UNKNOWN state
+   as USED if UNKNOWN_IS_UNUSED is true.  Return TRUE if the exit
+   state is changed.  */
 
-static void
-move_or_delete_vzeroupper_1 (basic_block block)
+static bool
+move_or_delete_vzeroupper_1 (basic_block block, bool unknown_is_unused)
 {
   edge e;
   edge_iterator ei;
-  enum upper_128bits_state state;
+  enum upper_128bits_state state, old_state, new_state;
+  bool seen_unknown;
 
   if (dump_file)
-    fprintf (dump_file, " Process BB [%i]: status: %d\n",
+    fprintf (dump_file, " Process [bb %i]: status: %d\n",
             block->index, BLOCK_INFO (block)->processed);
 
   if (BLOCK_INFO (block)->processed)
-    return;
-
-  BLOCK_INFO (block)->processed = true;
+    return false;
 
-  state = unknown;
+  state = unused;
 
-  /* Process all predecessor edges of this block.  */
+  /* Check all predecessor edges of this block.  */
+  seen_unknown = false;
   FOR_EACH_EDGE (e, ei, block->preds)
     {
       if (e->src == block)
        continue;
-      move_or_delete_vzeroupper_1 (e->src);
       switch (BLOCK_INFO (e->src)->state)
        {
        case unknown:
-         if (state == unused)
-           state = unknown;
+         if (!unknown_is_unused)
+           seen_unknown = true;
+       case unused:
          break;
        case used:
          state = used;
-         break;
-       case unused:
-         break;
+         goto done;
        }
     }
 
-  /* If state of any predecessor edges is unknown, we need to rescan.  */
-  if (state == unknown)
-    cfun->machine->rescan_vzeroupper_p = 1;
+  if (seen_unknown)
+    state = unknown;
 
-  /* Process this block.  */
+done:
+  old_state = BLOCK_INFO (block)->state;
   move_or_delete_vzeroupper_2 (block, state);
-}
-
-/* Helper function for move_or_delete_vzeroupper.  Rescan vzeroupper
-   in BLOCK and its predecessor blocks recursively.  */
+  new_state = BLOCK_INFO (block)->state;
 
-static void
-rescan_move_or_delete_vzeroupper (basic_block block)
-{
-  edge e;
-  edge_iterator ei;
-  enum upper_128bits_state state;
-
-  if (dump_file)
-    fprintf (dump_file, " Rescan BB [%i]: status: %d\n",
-            block->index, BLOCK_INFO (block)->rescanned);
+  if (state != unknown || new_state == used)
+    BLOCK_INFO (block)->processed = true;
 
-  if (BLOCK_INFO (block)->rescanned)
-    return;
-
-  BLOCK_INFO (block)->rescanned = true;
-
-  state = unused;
-
-  /* Rescan all predecessor edges of this block.  */
-  FOR_EACH_EDGE (e, ei, block->preds)
+  /* Need to rescan if the upper 128bits of AVX registers are changed
+     to USED at exit.  */
+  if (new_state != old_state)
     {
-      if (e->src == block)
-       continue;
-      rescan_move_or_delete_vzeroupper (e->src);
-      /* For rescan, UKKNOWN state is treated as UNUSED.  */
-      if (BLOCK_INFO (e->src)->state == used)
-       state = used;
-    }
-
-  /* Rescan this block only if there are vzerouppers or the upper
-     128bits of AVX registers are referenced.  */
-  if (BLOCK_INFO (block)->count == 0
-      && (state == used || BLOCK_INFO (block)->referenced != used))
-    {
-      if (state == used)
-       BLOCK_INFO (block)->state = state;
+      if (new_state == used)
+       cfun->machine->rescan_vzeroupper_p = 1;
+      return true;
     }
   else
-    move_or_delete_vzeroupper_2 (block, state);
+    return false;
 }
 
 /* Go through the instruction stream looking for vzeroupper.  Delete
@@ -374,14 +364,18 @@ move_or_delete_vzeroupper (void)
   edge e;
   edge_iterator ei;
   basic_block bb;
-  unsigned int count = 0;
+  fibheap_t worklist, pending, fibheap_swap;
+  sbitmap visited, in_worklist, in_pending, sbitmap_swap;
+  int *bb_order;
+  int *rc_order;
+  int i;
 
   /* Set up block info for each basic block.  */
   alloc_aux_for_blocks (sizeof (struct block_info_def));
 
-  /* Process successor blocks of all entry points.  */
+  /* Process outgoing edges of entry point.  */
   if (dump_file)
-    fprintf (dump_file, "Process all entry points\n");
+    fprintf (dump_file, "Process outgoing edges of entry point\n");
 
   FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
     {
@@ -389,29 +383,108 @@ move_or_delete_vzeroupper (void)
                                   cfun->machine->caller_pass_avx256_p
                                   ? used : unused);
       BLOCK_INFO (e->dest)->processed = true;
-      BLOCK_INFO (e->dest)->rescanned = true;
     }
 
-  /* Process all basic blocks.  */
+  /* Compute reverse completion order of depth first search of the CFG
+     so that the data-flow runs faster.  */
+  rc_order = XNEWVEC (int, n_basic_blocks - NUM_FIXED_BLOCKS);
+  bb_order = XNEWVEC (int, last_basic_block);
+  pre_and_rev_post_order_compute (NULL, rc_order, false);
+  for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; i++)
+    bb_order[rc_order[i]] = i;
+  free (rc_order);
+
+  worklist = fibheap_new ();
+  pending = fibheap_new ();
+  visited = sbitmap_alloc (last_basic_block);
+  in_worklist = sbitmap_alloc (last_basic_block);
+  in_pending = sbitmap_alloc (last_basic_block);
+  sbitmap_zero (in_worklist);
+
+  /* Don't check outgoing edges of entry point.  */
+  sbitmap_ones (in_pending);
+  FOR_EACH_BB (bb)
+    if (BLOCK_INFO (bb)->processed)
+      RESET_BIT (in_pending, bb->index);
+    else
+      {
+       move_or_delete_vzeroupper_1 (bb, false);
+       fibheap_insert (pending, bb_order[bb->index], bb);
+      }
+
   if (dump_file)
-    fprintf (dump_file, "Process all basic blocks\n");
+    fprintf (dump_file, "Check remaining basic blocks\n");
 
-  FOR_EACH_BB (bb)
+  while (!fibheap_empty (pending))
     {
-      move_or_delete_vzeroupper_1 (bb);
-      count += BLOCK_INFO (bb)->count;
-    }
+      fibheap_swap = pending;
+      pending = worklist;
+      worklist = fibheap_swap;
+      sbitmap_swap = in_pending;
+      in_pending = in_worklist;
+      in_worklist = sbitmap_swap;
 
-  /* Rescan all basic blocks if needed.  */
-  if (count && cfun->machine->rescan_vzeroupper_p)
-    {
-      if (dump_file)
-       fprintf (dump_file, "Rescan all basic blocks\n");
+      sbitmap_zero (visited);
+
+      cfun->machine->rescan_vzeroupper_p = 0;
 
-      FOR_EACH_BB (bb)
-       rescan_move_or_delete_vzeroupper (bb);
+      while (!fibheap_empty (worklist))
+       {
+         bb = (basic_block) fibheap_extract_min (worklist);
+         RESET_BIT (in_worklist, bb->index);
+         gcc_assert (!TEST_BIT (visited, bb->index));
+         if (!TEST_BIT (visited, bb->index))
+           {
+             edge_iterator ei;
+
+             SET_BIT (visited, bb->index);
+
+             if (move_or_delete_vzeroupper_1 (bb, false))
+               FOR_EACH_EDGE (e, ei, bb->succs)
+                 {
+                   if (e->dest == EXIT_BLOCK_PTR
+                       || BLOCK_INFO (e->dest)->processed)
+                     continue;
+
+                   if (TEST_BIT (visited, e->dest->index))
+                     {
+                       if (!TEST_BIT (in_pending, e->dest->index))
+                         {
+                           /* Send E->DEST to next round.  */
+                           SET_BIT (in_pending, e->dest->index);
+                           fibheap_insert (pending,
+                                           bb_order[e->dest->index],
+                                           e->dest);
+                         }
+                     }
+                   else if (!TEST_BIT (in_worklist, e->dest->index))
+                     {
+                       /* Add E->DEST to current round.  */
+                       SET_BIT (in_worklist, e->dest->index);
+                       fibheap_insert (worklist, bb_order[e->dest->index],
+                                       e->dest);
+                     }
+                 }
+           }
+       }
+
+      if (!cfun->machine->rescan_vzeroupper_p)
+       break;
     }
 
+  free (bb_order);
+  fibheap_delete (worklist);
+  fibheap_delete (pending);
+  sbitmap_free (visited);
+  sbitmap_free (in_worklist);
+  sbitmap_free (in_pending);
+
+  if (dump_file)
+    fprintf (dump_file, "Process remaining basic blocks\n");
+
+  FOR_EACH_BB (bb)
+    move_or_delete_vzeroupper_1 (bb, true);
+
   free_aux_for_blocks ();
 }
 
@@ -1265,6 +1338,88 @@ struct processor_costs bdver1_cost = {
   1,                                   /* cond_not_taken_branch_cost.  */
 };
 
+struct processor_costs btver1_cost = {
+  COSTS_N_INSNS (1),                   /* cost of an add instruction */
+  COSTS_N_INSNS (2),                   /* cost of a lea instruction */
+  COSTS_N_INSNS (1),                   /* variable shift costs */
+  COSTS_N_INSNS (1),                   /* constant shift costs */
+  {COSTS_N_INSNS (3),                  /* cost of starting multiply for QI */
+   COSTS_N_INSNS (4),                  /*                               HI */
+   COSTS_N_INSNS (3),                  /*                               SI */
+   COSTS_N_INSNS (4),                  /*                               DI */
+   COSTS_N_INSNS (5)},                 /*                            other */
+  0,                                   /* cost of multiply per each bit set */
+  {COSTS_N_INSNS (19),                 /* cost of a divide/mod for QI */
+   COSTS_N_INSNS (35),                 /*                          HI */
+   COSTS_N_INSNS (51),                 /*                          SI */
+   COSTS_N_INSNS (83),                 /*                          DI */
+   COSTS_N_INSNS (83)},                        /*                          other */
+  COSTS_N_INSNS (1),                   /* cost of movsx */
+  COSTS_N_INSNS (1),                   /* cost of movzx */
+  8,                                   /* "large" insn */
+  9,                                   /* MOVE_RATIO */
+  4,                                /* cost for loading QImode using movzbl */
+  {3, 4, 3},                           /* cost of loading integer registers
+                                          in QImode, HImode and SImode.
+                                          Relative to reg-reg move (2).  */
+  {3, 4, 3},                           /* cost of storing integer registers */
+  4,                                   /* cost of reg,reg fld/fst */
+  {4, 4, 12},                          /* cost of loading fp registers
+                                          in SFmode, DFmode and XFmode */
+  {6, 6, 8},                           /* cost of storing fp registers
+                                          in SFmode, DFmode and XFmode */
+  2,                                   /* cost of moving MMX register */
+  {3, 3},                              /* cost of loading MMX registers
+                                          in SImode and DImode */
+  {4, 4},                              /* cost of storing MMX registers
+                                          in SImode and DImode */
+  2,                                   /* cost of moving SSE register */
+  {4, 4, 3},                           /* cost of loading SSE registers
+                                          in SImode, DImode and TImode */
+  {4, 4, 5},                           /* cost of storing SSE registers
+                                          in SImode, DImode and TImode */
+  3,                                   /* MMX or SSE register to integer */
+                                       /* On K8:
+                                          MOVD reg64, xmmreg Double FSTORE 4
+                                          MOVD reg32, xmmreg Double FSTORE 4
+                                          On AMDFAM10:
+                                          MOVD reg64, xmmreg Double FADD 3
+                                                              1/1  1/1
+                                           MOVD reg32, xmmreg Double FADD 3
+                                                              1/1  1/1 */
+  32,                                  /* size of l1 cache.  */
+  512,                                 /* size of l2 cache.  */
+  64,                                  /* size of prefetch block */
+  100,                                 /* number of parallel prefetches */
+  2,                                   /* Branch cost */
+  COSTS_N_INSNS (4),                   /* cost of FADD and FSUB insns.  */
+  COSTS_N_INSNS (4),                   /* cost of FMUL instruction.  */
+  COSTS_N_INSNS (19),                  /* cost of FDIV instruction.  */
+  COSTS_N_INSNS (2),                   /* cost of FABS instruction.  */
+  COSTS_N_INSNS (2),                   /* cost of FCHS instruction.  */
+  COSTS_N_INSNS (35),                  /* cost of FSQRT instruction.  */
+
+  /* BTVER1 has optimized REP instruction for medium sized blocks, but for
+     very small blocks it is better to use loop. For large blocks, libcall can
+     do nontemporary accesses and beat inline considerably.  */
+  {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+   {libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+  {{libcall, {{8, loop}, {24, unrolled_loop},
+             {2048, rep_prefix_4_byte}, {-1, libcall}}},
+   {libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+  4,                                   /* scalar_stmt_cost.  */
+  2,                                   /* scalar load_cost.  */
+  2,                                   /* scalar_store_cost.  */
+  6,                                   /* vec_stmt_cost.  */
+  0,                                   /* vec_to_scalar_cost.  */
+  2,                                   /* scalar_to_vec_cost.  */
+  2,                                   /* vec_align_load_cost.  */
+  2,                                   /* vec_unalign_load_cost.  */
+  2,                                   /* vec_store_cost.  */
+  2,                                   /* cond_taken_branch_cost.  */
+  1,                                   /* cond_not_taken_branch_cost.  */
+};
+
 static const
 struct processor_costs pentium4_cost = {
   COSTS_N_INSNS (1),                   /* cost of an add instruction */
@@ -1410,79 +1565,6 @@ struct processor_costs nocona_cost = {
 };
 
 static const
-struct processor_costs core2_cost = {
-  COSTS_N_INSNS (1),                   /* cost of an add instruction */
-  COSTS_N_INSNS (1) + 1,               /* cost of a lea instruction */
-  COSTS_N_INSNS (1),                   /* variable shift costs */
-  COSTS_N_INSNS (1),                   /* constant shift costs */
-  {COSTS_N_INSNS (3),                  /* cost of starting multiply for QI */
-   COSTS_N_INSNS (3),                  /*                               HI */
-   COSTS_N_INSNS (3),                  /*                               SI */
-   COSTS_N_INSNS (3),                  /*                               DI */
-   COSTS_N_INSNS (3)},                 /*                            other */
-  0,                                   /* cost of multiply per each bit set */
-  {COSTS_N_INSNS (22),                 /* cost of a divide/mod for QI */
-   COSTS_N_INSNS (22),                 /*                          HI */
-   COSTS_N_INSNS (22),                 /*                          SI */
-   COSTS_N_INSNS (22),                 /*                          DI */
-   COSTS_N_INSNS (22)},                        /*                          other */
-  COSTS_N_INSNS (1),                   /* cost of movsx */
-  COSTS_N_INSNS (1),                   /* cost of movzx */
-  8,                                   /* "large" insn */
-  16,                                  /* MOVE_RATIO */
-  2,                                /* cost for loading QImode using movzbl */
-  {6, 6, 6},                           /* cost of loading integer registers
-                                          in QImode, HImode and SImode.
-                                          Relative to reg-reg move (2).  */
-  {4, 4, 4},                           /* cost of storing integer registers */
-  2,                                   /* cost of reg,reg fld/fst */
-  {6, 6, 6},                           /* cost of loading fp registers
-                                          in SFmode, DFmode and XFmode */
-  {4, 4, 4},                           /* cost of storing fp registers
-                                          in SFmode, DFmode and XFmode */
-  2,                                   /* cost of moving MMX register */
-  {6, 6},                              /* cost of loading MMX registers
-                                          in SImode and DImode */
-  {4, 4},                              /* cost of storing MMX registers
-                                          in SImode and DImode */
-  2,                                   /* cost of moving SSE register */
-  {6, 6, 6},                           /* cost of loading SSE registers
-                                          in SImode, DImode and TImode */
-  {4, 4, 4},                           /* cost of storing SSE registers
-                                          in SImode, DImode and TImode */
-  2,                                   /* MMX or SSE register to integer */
-  32,                                  /* size of l1 cache.  */
-  2048,                                        /* size of l2 cache.  */
-  128,                                 /* size of prefetch block */
-  8,                                   /* number of parallel prefetches */
-  3,                                   /* Branch cost */
-  COSTS_N_INSNS (3),                   /* cost of FADD and FSUB insns.  */
-  COSTS_N_INSNS (5),                   /* cost of FMUL instruction.  */
-  COSTS_N_INSNS (32),                  /* cost of FDIV instruction.  */
-  COSTS_N_INSNS (1),                   /* cost of FABS instruction.  */
-  COSTS_N_INSNS (1),                   /* cost of FCHS instruction.  */
-  COSTS_N_INSNS (58),                  /* cost of FSQRT instruction.  */
-  {{libcall, {{11, loop}, {-1, rep_prefix_4_byte}}},
-   {libcall, {{32, loop}, {64, rep_prefix_4_byte},
-             {8192, rep_prefix_8_byte}, {-1, libcall}}}},
-  {{libcall, {{8, loop}, {15, unrolled_loop},
-             {2048, rep_prefix_4_byte}, {-1, libcall}}},
-   {libcall, {{24, loop}, {32, unrolled_loop},
-             {8192, rep_prefix_8_byte}, {-1, libcall}}}},
-  1,                                   /* scalar_stmt_cost.  */
-  1,                                   /* scalar load_cost.  */
-  1,                                   /* scalar_store_cost.  */
-  1,                                   /* vec_stmt_cost.  */
-  1,                                   /* vec_to_scalar_cost.  */
-  1,                                   /* scalar_to_vec_cost.  */
-  1,                                   /* vec_align_load_cost.  */
-  2,                                   /* vec_unalign_load_cost.  */
-  1,                                   /* vec_store_cost.  */
-  3,                                   /* cond_taken_branch_cost.  */
-  1,                                   /* cond_not_taken_branch_cost.  */
-};
-
-static const
 struct processor_costs atom_cost = {
   COSTS_N_INSNS (1),                   /* cost of an add instruction */
   COSTS_N_INSNS (1) + 1,               /* cost of a lea instruction */
@@ -1713,9 +1795,14 @@ const struct processor_costs *ix86_cost = &pentium_cost;
 #define m_PPRO (1<<PROCESSOR_PENTIUMPRO)
 #define m_PENT4  (1<<PROCESSOR_PENTIUM4)
 #define m_NOCONA  (1<<PROCESSOR_NOCONA)
-#define m_CORE2  (1<<PROCESSOR_CORE2)
+#define m_CORE2_32  (1<<PROCESSOR_CORE2_32)
+#define m_CORE2_64  (1<<PROCESSOR_CORE2_64)
 #define m_COREI7_32  (1<<PROCESSOR_COREI7_32)
 #define m_COREI7_64  (1<<PROCESSOR_COREI7_64)
+#define m_COREI7  (m_COREI7_32 | m_COREI7_64)
+#define m_CORE2I7_32  (m_CORE2_32 | m_COREI7_32)
+#define m_CORE2I7_64  (m_CORE2_64 | m_COREI7_64)
+#define m_CORE2I7  (m_CORE2I7_32 | m_CORE2I7_64)
 #define m_ATOM  (1<<PROCESSOR_ATOM)
 
 #define m_GEODE  (1<<PROCESSOR_GEODE)
@@ -1726,10 +1813,11 @@ const struct processor_costs *ix86_cost = &pentium_cost;
 #define m_ATHLON_K8  (m_K8 | m_ATHLON)
 #define m_AMDFAM10  (1<<PROCESSOR_AMDFAM10)
 #define m_BDVER1  (1<<PROCESSOR_BDVER1)
-#define m_AMD_MULTIPLE  (m_K8 | m_ATHLON | m_AMDFAM10 | m_BDVER1)
+#define m_BTVER1  (1<<PROCESSOR_BTVER1)
+#define m_AMD_MULTIPLE  (m_K8 | m_ATHLON | m_AMDFAM10 | m_BDVER1 | m_BTVER1)
 
-#define m_GENERIC32 (1<<PROCESSOR_GENERIC32 | m_COREI7_32)
-#define m_GENERIC64 (1<<PROCESSOR_GENERIC64 | m_COREI7_64)
+#define m_GENERIC32 (1<<PROCESSOR_GENERIC32)
+#define m_GENERIC64 (1<<PROCESSOR_GENERIC64)
 
 /* Generic instruction choice should be common subset of supported CPUs
    (PPro/PENT4/NOCONA/CORE2/Athlon/K8).  */
@@ -1745,21 +1833,22 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
      negatively, so enabling for Generic64 seems like good code size
      tradeoff.  We can't enable it for 32bit generic because it does not
      work well with PPro base chips.  */
-  m_386 | m_K6_GEODE | m_AMD_MULTIPLE | m_CORE2 | m_GENERIC64,
+  m_386 | m_K6_GEODE | m_AMD_MULTIPLE | m_CORE2I7_64 | m_GENERIC64,
 
   /* X86_TUNE_PUSH_MEMORY */
   m_386 | m_K6_GEODE | m_AMD_MULTIPLE | m_PENT4
-  | m_NOCONA | m_CORE2 | m_GENERIC,
+  | m_NOCONA | m_CORE2I7 | m_GENERIC,
 
   /* X86_TUNE_ZERO_EXTEND_WITH_AND */
   m_486 | m_PENT,
 
   /* X86_TUNE_UNROLL_STRLEN */
   m_486 | m_PENT | m_ATOM | m_PPRO | m_AMD_MULTIPLE | m_K6
-  | m_CORE2 | m_GENERIC,
+  | m_CORE2I7 | m_GENERIC,
 
   /* X86_TUNE_DEEP_BRANCH_PREDICTION */
-  m_ATOM | m_PPRO | m_K6_GEODE | m_AMD_MULTIPLE | m_PENT4 | m_GENERIC,
+  m_ATOM | m_PPRO | m_K6_GEODE | m_AMD_MULTIPLE | m_PENT4
+  | m_CORE2I7 | m_GENERIC,
 
   /* X86_TUNE_BRANCH_PREDICTION_HINTS: Branch hints were put in P4 based
      on simulation result. But after P4 was made, no performance benefit
@@ -1771,13 +1860,13 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
   ~m_386,
 
   /* X86_TUNE_USE_SAHF */
-  m_ATOM | m_PPRO | m_K6_GEODE | m_K8 | m_AMDFAM10 | m_BDVER1 | m_PENT4
-  | m_NOCONA | m_CORE2 | m_GENERIC,
+  m_ATOM | m_PPRO | m_K6_GEODE | m_K8 | m_AMDFAM10 | m_BDVER1 | m_BTVER1
+  | m_PENT4 | m_NOCONA | m_CORE2I7 | m_GENERIC,
 
   /* X86_TUNE_MOVX: Enable to zero extend integer registers to avoid
      partial dependencies.  */
   m_AMD_MULTIPLE | m_ATOM | m_PPRO | m_PENT4 | m_NOCONA
-  | m_CORE2 | m_GENERIC | m_GEODE /* m_386 | m_K6 */,
+  | m_CORE2I7 | m_GENERIC | m_GEODE /* m_386 | m_K6 */,
 
   /* X86_TUNE_PARTIAL_REG_STALL: We probably ought to watch for partial
      register stalls on Generic32 compilation setting as well.  However
@@ -1790,19 +1879,19 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
   m_PPRO,
 
   /* X86_TUNE_PARTIAL_FLAG_REG_STALL */
-  m_CORE2 | m_GENERIC,
+  m_CORE2I7 | m_GENERIC,
 
   /* X86_TUNE_USE_HIMODE_FIOP */
   m_386 | m_486 | m_K6_GEODE,
 
   /* X86_TUNE_USE_SIMODE_FIOP */
-  ~(m_PPRO | m_AMD_MULTIPLE | m_PENT | m_ATOM | m_CORE2 | m_GENERIC),
+  ~(m_PPRO | m_AMD_MULTIPLE | m_PENT | m_ATOM | m_CORE2I7 | m_GENERIC),
 
   /* X86_TUNE_USE_MOV0 */
   m_K6,
 
   /* X86_TUNE_USE_CLTD */
-  ~(m_PENT | m_ATOM | m_K6 | m_CORE2 | m_GENERIC),
+  ~(m_PENT | m_ATOM | m_K6 | m_CORE2I7 | m_GENERIC),
 
   /* X86_TUNE_USE_XCHGB: Use xchgb %rh,%rl instead of rolw/rorw $8,rx.  */
   m_PENT4,
@@ -1818,7 +1907,7 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
 
   /* X86_TUNE_PROMOTE_QIMODE */
   m_K6_GEODE | m_PENT | m_ATOM | m_386 | m_486 | m_AMD_MULTIPLE
-  | m_CORE2 | m_GENERIC /* | m_PENT4 ? */,
+  | m_CORE2I7 | m_GENERIC /* | m_PENT4 ? */,
 
   /* X86_TUNE_FAST_PREFIX */
   ~(m_PENT | m_486 | m_386),
@@ -1859,11 +1948,11 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
 
   /* X86_TUNE_INTEGER_DFMODE_MOVES: Enable if integer moves are preferred
      for DFmode copies */
-  ~(m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2
+  ~(m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2I7
     | m_GENERIC | m_GEODE),
 
   /* X86_TUNE_PARTIAL_REG_DEPENDENCY */
-  m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC,
+  m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_CORE2I7 | m_GENERIC,
 
   /* X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY: In the Generic model we have a
      conflict here in between PPro/Pentium4 based chips that thread 128bit
@@ -1874,14 +1963,14 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
      shows that disabling this option on P4 brings over 20% SPECfp regression,
      while enabling it on K8 brings roughly 2.4% regression that can be partly
      masked by careful scheduling of moves.  */
-  m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 | m_GENERIC
+  m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2I7 | m_GENERIC
   | m_AMDFAM10 | m_BDVER1,
 
   /* X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL */
-  m_AMDFAM10 | m_BDVER1,
+  m_AMDFAM10 | m_BDVER1 | m_BTVER1 | m_COREI7,
 
   /* X86_TUNE_SSE_UNALIGNED_STORE_OPTIMAL */
-  m_BDVER1,
+  m_BDVER1 | m_COREI7,
 
   /* X86_TUNE_SSE_PACKED_SINGLE_INSN_OPTIMAL */
   m_BDVER1,
@@ -1899,13 +1988,13 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
   m_PPRO | m_PENT4 | m_NOCONA,
 
   /* X86_TUNE_MEMORY_MISMATCH_STALL */
-  m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_CORE2 | m_GENERIC,
+  m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_CORE2I7 | m_GENERIC,
 
   /* X86_TUNE_PROLOGUE_USING_MOVE */
-  m_ATHLON_K8 | m_ATOM | m_PPRO | m_CORE2 | m_GENERIC,
+  m_ATHLON_K8 | m_ATOM | m_PPRO | m_CORE2I7 | m_GENERIC,
 
   /* X86_TUNE_EPILOGUE_USING_MOVE */
-  m_ATHLON_K8 | m_ATOM | m_PPRO | m_CORE2 | m_GENERIC,
+  m_ATHLON_K8 | m_ATOM | m_PPRO | m_CORE2I7 | m_GENERIC,
 
   /* X86_TUNE_SHIFT1 */
   ~m_486,
@@ -1921,34 +2010,34 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
 
   /* X86_TUNE_FOUR_JUMP_LIMIT: Some CPU cores are not able to predict more
      than 4 branch instructions in the 16 byte window.  */
-  m_ATOM | m_PPRO | m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_CORE2
+  m_ATOM | m_PPRO | m_AMD_MULTIPLE | m_PENT4 | m_NOCONA | m_CORE2I7
   | m_GENERIC,
 
   /* X86_TUNE_SCHEDULE */
-  m_PPRO | m_AMD_MULTIPLE | m_K6_GEODE | m_PENT | m_ATOM | m_CORE2
+  m_PPRO | m_AMD_MULTIPLE | m_K6_GEODE | m_PENT | m_ATOM | m_CORE2I7
   | m_GENERIC,
 
   /* X86_TUNE_USE_BT */
-  m_AMD_MULTIPLE | m_ATOM | m_CORE2 | m_GENERIC,
+  m_AMD_MULTIPLE | m_ATOM | m_CORE2I7 | m_GENERIC,
 
   /* X86_TUNE_USE_INCDEC */
-  ~(m_PENT4 | m_NOCONA | m_GENERIC | m_ATOM),
+  ~(m_PENT4 | m_NOCONA | m_CORE2I7 | m_GENERIC | m_ATOM),
 
   /* X86_TUNE_PAD_RETURNS */
-  m_AMD_MULTIPLE | m_CORE2 | m_GENERIC,
+  m_AMD_MULTIPLE | m_CORE2I7 | m_GENERIC,
 
   /* X86_TUNE_PAD_SHORT_FUNCTION: Pad short funtion.  */
   m_ATOM,
 
   /* X86_TUNE_EXT_80387_CONSTANTS */
   m_K6_GEODE | m_ATHLON_K8 | m_ATOM | m_PENT4 | m_NOCONA | m_PPRO
-  | m_CORE2 | m_GENERIC,
+  | m_CORE2I7 | m_GENERIC,
 
   /* X86_TUNE_SHORTEN_X87_SSE */
   ~m_K8,
 
   /* X86_TUNE_AVOID_VECTOR_DECODE */
-  m_K8 | m_GENERIC64,
+  m_K8 | m_CORE2I7_64 | m_GENERIC64,
 
   /* X86_TUNE_PROMOTE_HIMODE_IMUL: Modern CPUs have same latency for HImode
      and SImode multiply, but 386 and 486 do HImode multiply faster.  */
@@ -1956,11 +2045,11 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
 
   /* X86_TUNE_SLOW_IMUL_IMM32_MEM: Imul of 32-bit constant and memory is
      vector path on AMD machines.  */
-  m_K8 | m_GENERIC64 | m_AMDFAM10 | m_BDVER1,
+  m_K8 | m_CORE2I7_64 | m_GENERIC64 | m_AMDFAM10 | m_BDVER1 | m_BTVER1,
 
   /* X86_TUNE_SLOW_IMUL_IMM8: Imul of 8-bit constant is vector path on AMD
      machines.  */
-  m_K8 | m_GENERIC64 | m_AMDFAM10 | m_BDVER1,
+  m_K8 | m_CORE2I7_64 | m_GENERIC64 | m_AMDFAM10 | m_BDVER1 | m_BTVER1,
 
   /* X86_TUNE_MOVE_M1_VIA_OR: On pentiums, it is faster to load -1 via OR
      than a MOV.  */
@@ -1977,7 +2066,7 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
 
   /* X86_TUNE_USE_VECTOR_FP_CONVERTS: Prefer vector packed SSE conversion
      from FP to FP. */
-  m_AMDFAM10 | m_GENERIC,
+  m_AMDFAM10 | m_CORE2I7 | m_GENERIC,
 
   /* X86_TUNE_USE_VECTOR_CONVERTS: Prefer vector packed SSE conversion
      from integer to FP. */
@@ -1986,7 +2075,7 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
   /* X86_TUNE_FUSE_CMP_AND_BRANCH: Fuse a compare or test instruction
      with a subsequent conditional jump instruction into a single
      compare-and-branch uop.  */
-  m_CORE2 | m_BDVER1,
+  m_BDVER1,
 
   /* X86_TUNE_OPT_AGU: Optimize for Address Generation Unit. This flag
      will impact LEA instruction selection. */
@@ -1995,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.  */
@@ -2020,14 +2114,12 @@ static unsigned int initial_ix86_arch_features[X86_ARCH_LAST] = {
 };
 
 static const unsigned int x86_accumulate_outgoing_args
-  = m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2
+  = m_AMD_MULTIPLE | m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2I7
     | m_GENERIC;
 
 static const unsigned int x86_arch_always_fancy_math_387
   = m_PENT | m_ATOM | m_PPRO | m_AMD_MULTIPLE | m_PENT4
-    | m_NOCONA | m_CORE2 | m_GENERIC;
-
-static enum stringop_alg stringop_alg = no_stringop;
+    | m_NOCONA | m_CORE2I7 | m_GENERIC;
 
 /* In case the average insn count for single function invocation is
    lower than this constant, emit fast (but longer) prologue and
@@ -2234,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;
 
@@ -2256,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";
@@ -2287,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;
@@ -2359,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);
@@ -2393,10 +2461,6 @@ static enum calling_abi ix86_function_abi (const_tree);
 static int ix86_tune_defaulted;
 static int ix86_arch_specified;
 
-/* A mask of ix86_isa_flags that includes bit X if X
-   was set or cleared on the command line.  */
-static int ix86_isa_flags_explicit;
-
 /* Define a set of ISAs which are available when a given ISA is
    enabled.  MMX and SSE ISAs are handled separately.  */
 
@@ -2540,7 +2604,10 @@ static const struct ptt processor_target_table[PROCESSOR_max] =
   {&pentium4_cost, 0, 0, 0, 0, 0},
   {&k8_cost, 16, 7, 16, 7, 16},
   {&nocona_cost, 0, 0, 0, 0, 0},
-  {&core2_cost, 16, 10, 16, 10, 16},
+  /* Core 2 32-bit.  */
+  {&generic32_cost, 16, 10, 16, 10, 16},
+  /* Core 2 64-bit.  */
+  {&generic64_cost, 16, 10, 16, 10, 16},
   /* Core i7 32-bit.  */
   {&generic32_cost, 16, 10, 16, 10, 16},
   /* Core i7 64-bit.  */
@@ -2549,6 +2616,7 @@ static const struct ptt processor_target_table[PROCESSOR_max] =
   {&generic64_cost, 16, 10, 16, 10, 16},
   {&amdfam10_cost, 32, 24, 32, 7, 32},
   {&bdver1_cost, 32, 24, 32, 7, 32},
+  {&btver1_cost, 32, 24, 32, 7, 32},
   {&atom_cost, 16, 7, 16, 7, 16}
 };
 
@@ -2577,7 +2645,8 @@ static const char *const cpu_names[TARGET_CPU_DEFAULT_max] =
   "athlon-4",
   "k8",
   "amdfam10",
-  "bdver1"
+  "bdver1",
+  "btver1"
 };
 \f
 /* Return true if a red-zone is in use.  */
@@ -2591,33 +2660,39 @@ ix86_using_red_zone (void)
 /* Implement TARGET_HANDLE_OPTION.  */
 
 static bool
-ix86_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED, int value)
+ix86_handle_option (struct gcc_options *opts,
+                   struct gcc_options *opts_set ATTRIBUTE_UNUSED,
+                   const struct cl_decoded_option *decoded,
+                   location_t loc)
 {
+  size_t code = decoded->opt_index;
+  int value = decoded->value;
+
   switch (code)
     {
     case OPT_mmmx:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_MMX_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_MMX_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_MMX_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_MMX_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_MMX_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_MMX_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_MMX_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_MMX_UNSET;
        }
       return true;
 
     case OPT_m3dnow:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_3DNOW_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_3DNOW_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_3DNOW_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_3DNOW_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_3DNOW_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_3DNOW_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_3DNOW_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_3DNOW_UNSET;
        }
       return true;
 
@@ -2627,335 +2702,374 @@ ix86_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED, int value)
     case OPT_msse:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_SSE_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_SSE_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSE_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE_UNSET;
        }
       return true;
 
     case OPT_msse2:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_SSE2_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE2_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE2_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE2_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_SSE2_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE2_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSE2_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE2_UNSET;
        }
       return true;
 
     case OPT_msse3:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_SSE3_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE3_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE3_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE3_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_SSE3_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE3_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSE3_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE3_UNSET;
        }
       return true;
 
     case OPT_mssse3:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_SSSE3_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSSE3_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSSE3_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSSE3_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_SSSE3_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSSE3_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSSE3_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSSE3_UNSET;
        }
       return true;
 
     case OPT_msse4_1:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_SSE4_1_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_1_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE4_1_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_1_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_SSE4_1_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_1_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSE4_1_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_1_UNSET;
        }
       return true;
 
     case OPT_msse4_2:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_SSE4_2_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_2_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE4_2_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_2_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_SSE4_2_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_2_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSE4_2_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_2_UNSET;
        }
       return true;
 
     case OPT_mavx:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_AVX_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_AVX_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_AVX_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX_UNSET;
        }
       return true;
 
     case OPT_mfma:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_FMA_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_FMA_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_FMA_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_FMA_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_FMA_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_FMA_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_FMA_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_FMA_UNSET;
        }
       return true;
 
     case OPT_msse4:
-      ix86_isa_flags |= OPTION_MASK_ISA_SSE4_SET;
-      ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_SET;
+      opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE4_SET;
+      opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_SET;
       return true;
 
     case OPT_mno_sse4:
-      ix86_isa_flags &= ~OPTION_MASK_ISA_SSE4_UNSET;
-      ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_UNSET;
+      opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSE4_UNSET;
+      opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4_UNSET;
       return true;
 
     case OPT_msse4a:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_SSE4A_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4A_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE4A_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4A_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_SSE4A_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4A_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SSE4A_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SSE4A_UNSET;
        }
       return true;
 
     case OPT_mfma4:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_FMA4_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_FMA4_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_FMA4_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_FMA4_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_FMA4_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_FMA4_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_FMA4_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_FMA4_UNSET;
        }
       return true;
 
    case OPT_mxop:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_XOP_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_XOP_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_XOP_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_XOP_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_XOP_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_XOP_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_XOP_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_XOP_UNSET;
        }
       return true;
 
    case OPT_mlwp:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_LWP_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_LWP_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_LWP_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_LWP_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_LWP_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_LWP_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_LWP_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_LWP_UNSET;
        }
       return true;
 
     case OPT_mabm:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_ABM_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_ABM_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_ABM_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_ABM_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_ABM_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_ABM_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_ABM_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_ABM_UNSET;
        }
       return true;
 
     case OPT_mbmi:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_BMI_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_BMI_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_BMI_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_BMI_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_BMI_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_BMI_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_BMI_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_BMI_UNSET;
        }
       return true;
 
     case OPT_mtbm:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_TBM_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_TBM_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_TBM_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_TBM_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_TBM_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_TBM_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_TBM_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_TBM_UNSET;
        }
       return true;
 
     case OPT_mpopcnt:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_POPCNT_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_POPCNT_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_POPCNT_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_POPCNT_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_POPCNT_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_POPCNT_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_POPCNT_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_POPCNT_UNSET;
        }
       return true;
 
     case OPT_msahf:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_SAHF_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SAHF_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SAHF_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SAHF_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_SAHF_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_SAHF_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_SAHF_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_SAHF_UNSET;
        }
       return true;
 
     case OPT_mcx16:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_CX16_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_CX16_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_CX16_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_CX16_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_CX16_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_CX16_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_CX16_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_CX16_UNSET;
        }
       return true;
 
     case OPT_mmovbe:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_MOVBE_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_MOVBE_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_MOVBE_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_MOVBE_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_MOVBE_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_MOVBE_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_MOVBE_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_MOVBE_UNSET;
        }
       return true;
 
     case OPT_mcrc32:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_CRC32_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_CRC32_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_CRC32_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_CRC32_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_CRC32_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_CRC32_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_CRC32_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_CRC32_UNSET;
        }
       return true;
 
     case OPT_maes:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_AES_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_AES_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AES_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AES_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_AES_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_AES_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_AES_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AES_UNSET;
        }
       return true;
 
     case OPT_mpclmul:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_PCLMUL_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_PCLMUL_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_PCLMUL_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_PCLMUL_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_PCLMUL_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_PCLMUL_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_PCLMUL_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_PCLMUL_UNSET;
        }
       return true;
 
     case OPT_mfsgsbase:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_FSGSBASE_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_FSGSBASE_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_FSGSBASE_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_FSGSBASE_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_FSGSBASE_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_FSGSBASE_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_FSGSBASE_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_FSGSBASE_UNSET;
        }
       return true;
 
     case OPT_mrdrnd:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_RDRND_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_RDRND_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_RDRND_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_RDRND_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_RDRND_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_RDRND_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_RDRND_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_RDRND_UNSET;
        }
       return true;
 
     case OPT_mf16c:
       if (value)
        {
-         ix86_isa_flags |= OPTION_MASK_ISA_F16C_SET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_F16C_SET;
+         opts->x_ix86_isa_flags |= OPTION_MASK_ISA_F16C_SET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_F16C_SET;
        }
       else
        {
-         ix86_isa_flags &= ~OPTION_MASK_ISA_F16C_UNSET;
-         ix86_isa_flags_explicit |= OPTION_MASK_ISA_F16C_UNSET;
+         opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_F16C_UNSET;
+         opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_F16C_UNSET;
+       }
+      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;
 
@@ -2969,7 +3083,7 @@ ix86_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED, int value)
 
 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
   {
@@ -3035,6 +3149,8 @@ ix86_target_string (int isa, int flags, const char *arch, const char *tune,
     { "-mvect8-ret-in-mem",            MASK_VECT8_RETURNS },
     { "-m8bit-idiv",                   MASK_USE_8BIT_IDIV },
     { "-mvzeroupper",                  MASK_VZEROUPPER },
+    { "-mavx256-split-unaligned-load", MASK_AVX256_SPLIT_UNALIGNED_LOAD},
+    { "-mavx256-split-unaligned-store",        MASK_AVX256_SPLIT_UNALIGNED_STORE},
   };
 
   const char *opts[ARRAY_SIZE (isa_opts) + ARRAY_SIZE (flag_opts) + 6][2];
@@ -3101,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?  */
@@ -3160,26 +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:
-      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.  */
@@ -3196,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)
     {
@@ -3223,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,
@@ -3296,12 +3405,16 @@ ix86_option_override_internal (bool main_args_p)
       {"nocona", PROCESSOR_NOCONA, CPU_NONE,
        PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
        | PTA_CX16 | PTA_NO_SAHF},
-      {"core2", PROCESSOR_CORE2, CPU_CORE2,
+      {"core2", PROCESSOR_CORE2_64, CPU_CORE2,
        PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
        | PTA_SSSE3 | PTA_CX16},
-      {"corei7", PROCESSOR_COREI7_64, CPU_GENERIC64,
-       PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
-       | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_CX16},
+      {"corei7", PROCESSOR_COREI7_64, CPU_COREI7,
+       PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+       | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_CX16},
+      {"corei7-avx", PROCESSOR_COREI7_64, CPU_COREI7,
+       PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+       | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AVX
+       | PTA_CX16 | PTA_POPCNT | PTA_AES | PTA_PCLMUL},
       {"atom", PROCESSOR_ATOM, CPU_ATOM,
        PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
        | PTA_SSSE3 | PTA_CX16 | PTA_MOVBE},
@@ -3350,10 +3463,13 @@ ix86_option_override_internal (bool main_args_p)
        PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
        | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM},
       {"bdver1", PROCESSOR_BDVER1, CPU_BDVER1,
-       PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
-       | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM
-       | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES
-       | PTA_PCLMUL | PTA_AVX | PTA_FMA4 | PTA_XOP | PTA_LWP},
+       PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+       | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
+       | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4
+       | PTA_XOP | PTA_LWP},
+      {"btver1", PROCESSOR_BTVER1, CPU_GENERIC64,
+        PTA_64BIT | PTA_MMX |  PTA_SSE  | PTA_SSE2 | PTA_SSE3
+        | PTA_SSSE3 | PTA_SSE4A |PTA_ABM | PTA_CX16},
       {"generic32", PROCESSOR_GENERIC32, CPU_PENTIUMPRO,
        0 /* flags are only used for -march switch.  */ },
       {"generic64", PROCESSOR_GENERIC64, CPU_GENERIC64,
@@ -3441,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)
@@ -3469,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
     {
@@ -3514,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);
@@ -3676,9 +3792,12 @@ ix86_option_override_internal (bool main_args_p)
                ix86_schedule = CPU_PENTIUMPRO;
                break;
 
+             case PROCESSOR_CORE2_64:
+               ix86_tune = PROCESSOR_CORE2_32;
+               break;
+
              case PROCESSOR_COREI7_64:
                ix86_tune = PROCESSOR_COREI7_32;
-               ix86_schedule = CPU_PENTIUMPRO;
                break;
 
              default:
@@ -3744,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)
+       warning (0, "-mregparm is ignored in 64-bit mode");
+      if (ix86_regparm > REGPARM_MAX)
        {
-         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)
-       {
-         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)
@@ -3822,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)
     {
@@ -3909,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)
     {
@@ -3923,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.  */
@@ -3951,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;
        }
@@ -3970,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 (!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)
     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))
@@ -4061,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.  */
@@ -4097,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)
@@ -4160,25 +4191,33 @@ 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
-        TARGET_AVX with -fexpensive-optimizations.  */
-      if (!optimize_size
-         && flag_expensive_optimizations
-         && !(target_flags_explicit & MASK_VZEROUPPER))
-       target_flags |= MASK_VZEROUPPER;
+        TARGET_AVX with -fexpensive-optimizations and split 32-byte
+        AVX unaligned load/store.  */
+      if (!optimize_size)
+       {
+         if (flag_expensive_optimizations
+             && !(target_flags_explicit & MASK_VZEROUPPER))
+           target_flags |= MASK_VZEROUPPER;
+         if (!(target_flags_explicit & MASK_AVX256_SPLIT_UNALIGNED_LOAD))
+           target_flags |= MASK_AVX256_SPLIT_UNALIGNED_LOAD;
+         if (!(target_flags_explicit & MASK_AVX256_SPLIT_UNALIGNED_STORE))
+           target_flags |= MASK_AVX256_SPLIT_UNALIGNED_STORE;
+       }
     }
   else 
     {
       /* 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.  */
@@ -4241,8 +4280,8 @@ ix86_conditional_register_usage (void)
   if (j != INVALID_REGNUM)
     fixed_regs[j] = call_used_regs[j] = 1;
 
-  /* The MS_ABI changes the set of call-used registers.  */
-  if (TARGET_64BIT && ix86_cfun_abi () == MS_ABI)
+  /* The 64-bit MS_ABI changes the set of call-used registers.  */
+  if (TARGET_64BIT_MS_ABI)
     {
       call_used_regs[SI_REG] = 0;
       call_used_regs[DI_REG] = 0;
@@ -4301,11 +4340,10 @@ 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;
-  ptr->ix86_isa_flags_explicit = ix86_isa_flags_explicit;
+  ptr->x_ix86_isa_flags_explicit = ix86_isa_flags_explicit;
   ptr->ix86_target_flags_explicit = target_flags_explicit;
 
   /* The fields are char but the variables are not; make sure the
@@ -4313,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);
 }
 
@@ -4330,11 +4367,10 @@ 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;
-  ix86_isa_flags_explicit = ptr->ix86_isa_flags_explicit;
+  ix86_isa_flags_explicit = ptr->x_ix86_isa_flags_explicit;
   target_flags_explicit = ptr->ix86_target_flags_explicit;
 
   /* Recreate the arch feature tests if the arch changed */
@@ -4364,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, "",
@@ -4380,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)
@@ -4398,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 }
 
@@ -4414,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
   };
 
@@ -4450,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 */
@@ -4493,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;
@@ -4549,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;
@@ -4567,7 +4608,13 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[])
        }
 
       else if (type == ix86_opt_isa)
-       ix86_handle_option (opt, p, opt_set_p);
+       {
+         struct cl_decoded_option decoded;
+
+         generate_option (opt, NULL, opt_set_p, CL_TARGET, &decoded);
+         ix86_handle_option (&global_options, &global_options_set,
+                             &decoded, input_location);
+       }
 
       else if (type == ix86_opt_yes || type == ix86_opt_no)
        {
@@ -4591,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 ();
     }
@@ -4605,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
@@ -4626,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.  */
@@ -4641,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);
@@ -4658,12 +4729,11 @@ 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++)
-       if (option_strings[i])
-         free (option_strings[i]);
+       free (option_strings[i]);
     }
 
   return t;
@@ -4757,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)
@@ -5191,7 +5261,7 @@ ix86_handle_cconv_attribute (tree *node, tree name,
       return NULL_TREE;
     }
 
-  /* Can combine regparm with all attributes but fastcall.  */
+  /* Can combine regparm with all attributes but fastcall, and thiscall.  */
   if (is_attribute_p ("regparm", name))
     {
       tree cst;
@@ -5315,6 +5385,56 @@ ix86_handle_cconv_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
+/* This function determines from TYPE the calling-convention.  */
+
+unsigned int
+ix86_get_callcvt (const_tree type)
+{
+  unsigned int ret = 0;
+  bool is_stdarg;
+  tree attrs;
+
+  if (TARGET_64BIT)
+    return IX86_CALLCVT_CDECL;
+
+  attrs = TYPE_ATTRIBUTES (type);
+  if (attrs != NULL_TREE)
+    {
+      if (lookup_attribute ("cdecl", attrs))
+       ret |= IX86_CALLCVT_CDECL;
+      else if (lookup_attribute ("stdcall", attrs))
+       ret |= IX86_CALLCVT_STDCALL;
+      else if (lookup_attribute ("fastcall", attrs))
+       ret |= IX86_CALLCVT_FASTCALL;
+      else if (lookup_attribute ("thiscall", attrs))
+       ret |= IX86_CALLCVT_THISCALL;
+
+      /* Regparam isn't allowed for thiscall and fastcall.  */
+      if ((ret & (IX86_CALLCVT_THISCALL | IX86_CALLCVT_FASTCALL)) == 0)
+       {
+         if (lookup_attribute ("regparm", attrs))
+           ret |= IX86_CALLCVT_REGPARM;
+         if (lookup_attribute ("sseregparm", attrs))
+           ret |= IX86_CALLCVT_SSEREGPARM;
+       }
+
+      if (IX86_BASE_CALLCVT(ret) != 0)
+       return ret;
+    }
+
+  is_stdarg = stdarg_p (type);
+  if (TARGET_RTD && !is_stdarg)
+    return IX86_CALLCVT_STDCALL | ret;
+
+  if (ret != 0
+      || is_stdarg
+      || TREE_CODE (type) != METHOD_TYPE
+      || ix86_function_type_abi (type) != MS_ABI)
+    return IX86_CALLCVT_CDECL | ret;
+
+  return IX86_CALLCVT_THISCALL;
+}
+
 /* Return 0 if the attributes for two types are incompatible, 1 if they
    are compatible, and 2 if they are nearly compatible (which causes a
    warning to be generated).  */
@@ -5322,33 +5442,18 @@ ix86_handle_cconv_attribute (tree *node, tree name,
 static int
 ix86_comp_type_attributes (const_tree type1, const_tree type2)
 {
-  /* Check for mismatch of non-default calling convention.  */
-  const char *const rtdstr = TARGET_RTD ? "cdecl" : "stdcall";
+  unsigned int ccvt1, ccvt2;
 
   if (TREE_CODE (type1) != FUNCTION_TYPE
       && TREE_CODE (type1) != METHOD_TYPE)
     return 1;
 
-  /* Check for mismatched fastcall/regparm types.  */
-  if ((!lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type1))
-       != !lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type2)))
-      || (ix86_function_regparm (type1, NULL)
-         != ix86_function_regparm (type2, NULL)))
+  ccvt1 = ix86_get_callcvt (type1);
+  ccvt2 = ix86_get_callcvt (type2);
+  if (ccvt1 != ccvt2)
     return 0;
-
-  /* Check for mismatched sseregparm types.  */
-  if (!lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type1))
-      != !lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type2)))
-    return 0;
-
-  /* Check for mismatched thiscall types.  */
-  if (!lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type1))
-      != !lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type2)))
-    return 0;
-
-  /* Check for mismatched return types (cdecl vs stdcall).  */
-  if (!lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type1))
-      != !lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type2)))
+  if (ix86_function_regparm (type1, NULL)
+      != ix86_function_regparm (type2, NULL))
     return 0;
 
   return 1;
@@ -5363,23 +5468,26 @@ ix86_function_regparm (const_tree type, const_tree decl)
 {
   tree attr;
   int regparm;
+  unsigned int ccvt;
 
   if (TARGET_64BIT)
     return (ix86_function_type_abi (type) == SYSV_ABI
            ? X86_64_REGPARM_MAX : X86_64_MS_REGPARM_MAX);
-
+  ccvt = ix86_get_callcvt (type);
   regparm = ix86_regparm;
-  attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
-  if (attr)
+
+  if ((ccvt & IX86_CALLCVT_REGPARM) != 0)
     {
-      regparm = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
-      return regparm;
+      attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
+      if (attr)
+       {
+         regparm = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
+         return regparm;
+       }
     }
-
-  if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
+  else if ((ccvt & IX86_CALLCVT_FASTCALL) != 0)
     return 2;
-
-  if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type)))
+  else if ((ccvt & IX86_CALLCVT_THISCALL) != 0)
     return 1;
 
   /* Use register calling convention for local functions when possible.  */
@@ -5390,7 +5498,7 @@ ix86_function_regparm (const_tree type, const_tree decl)
     {
       /* FIXME: remove this CONST_CAST when cgraph.[ch] is constified.  */
       struct cgraph_local_info *i = cgraph_local_info (CONST_CAST_TREE (decl));
-      if (i && i->local)
+      if (i && i->local && i->can_change_signature)
        {
          int local_regparm, globals = 0, regno;
 
@@ -5467,7 +5575,7 @@ ix86_function_sseregparm (const_tree type, const_tree decl, bool warn)
     {
       /* FIXME: remove this CONST_CAST when cgraph.[ch] is constified.  */
       struct cgraph_local_info *i = cgraph_local_info (CONST_CAST_TREE(decl));
-      if (i && i->local)
+      if (i && i->local && i->can_change_signature)
        return TARGET_SSE2 ? 2 : 1;
     }
 
@@ -5490,6 +5598,26 @@ ix86_eax_live_at_start_p (void)
   return REGNO_REG_SET_P (df_get_live_out (ENTRY_BLOCK_PTR), 0);
 }
 
+static bool
+ix86_keep_aggregate_return_pointer (tree fntype)
+{
+  tree attr;
+
+  if (!TARGET_64BIT)
+    {
+      attr = lookup_attribute ("callee_pop_aggregate_return",
+                              TYPE_ATTRIBUTES (fntype));
+      if (attr)
+       return (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))) == 0);
+
+      /* For 32-bit MS-ABI the default is to keep aggregate
+         return pointer.  */
+      if (ix86_function_type_abi (fntype) == MS_ABI)
+       return true;
+    }
+  return KEEP_AGGREGATE_RETURN_POINTER != 0;
+}
+
 /* Value is the number of bytes of arguments automatically
    popped when returning from a subroutine call.
    FUNDECL is the declaration node of the function (as a tree),
@@ -5510,31 +5638,22 @@ ix86_eax_live_at_start_p (void)
 static int
 ix86_return_pops_args (tree fundecl, tree funtype, int size)
 {
-  int rtd;
+  unsigned int ccvt;
 
   /* None of the 64-bit ABIs pop arguments.  */
   if (TARGET_64BIT)
     return 0;
 
-  rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE);
-
-  /* Cdecl functions override -mrtd, and never pop the stack.  */
-  if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype)))
-    {
-      /* Stdcall and fastcall functions will pop the stack if not
-         variable args.  */
-      if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))
-         || lookup_attribute ("fastcall", TYPE_ATTRIBUTES (funtype))
-          || lookup_attribute ("thiscall", TYPE_ATTRIBUTES (funtype)))
-       rtd = 1;
+  ccvt = ix86_get_callcvt (funtype);
 
-      if (rtd && ! stdarg_p (funtype))
-       return size;
-    }
+  if ((ccvt & (IX86_CALLCVT_STDCALL | IX86_CALLCVT_FASTCALL
+              | IX86_CALLCVT_THISCALL)) != 0
+      && ! stdarg_p (funtype))
+    return size;
 
   /* Lose any fake structure return argument if it is passed on the stack.  */
   if (aggregate_value_p (TREE_TYPE (funtype), fundecl)
-      && !KEEP_AGGREGATE_RETURN_POINTER)
+      && !ix86_keep_aggregate_return_pointer (funtype))
     {
       int nregs = ix86_function_regparm (funtype, fundecl);
       if (nregs == 0)
@@ -5623,7 +5742,7 @@ ix86_reg_parm_stack_space (const_tree fndecl)
     call_abi = ix86_function_abi (fndecl);
   else
     call_abi = ix86_function_type_abi (fndecl);
-  if (call_abi == MS_ABI)
+  if (TARGET_64BIT && call_abi == MS_ABI)
     return 32;
   return 0;
 }
@@ -5633,7 +5752,7 @@ ix86_reg_parm_stack_space (const_tree fndecl)
 enum calling_abi
 ix86_function_type_abi (const_tree fntype)
 {
-  if (TARGET_64BIT && fntype != NULL)
+  if (fntype != NULL_TREE && TYPE_ATTRIBUTES (fntype) != NULL_TREE)
     {
       enum calling_abi abi = ix86_abi;
       if (abi == SYSV_ABI)
@@ -5675,7 +5794,7 @@ ix86_function_abi (const_tree fndecl)
 enum calling_abi
 ix86_cfun_abi (void)
 {
-  if (! cfun || ! TARGET_64BIT)
+  if (! cfun)
     return ix86_abi;
   return cfun->machine->call_abi;
 }
@@ -5738,9 +5857,9 @@ ix86_call_abi_override (const_tree fndecl)
     cfun->machine->call_abi = ix86_function_type_abi (TREE_TYPE (fndecl));
 }
 
-/* MS and SYSV ABI have different set of call used registers.  Avoid expensive
-   re-initialization of init_regs each time we switch function context since
-   this is needed only during RTL expansion.  */
+/* 64-bit MS and SYSV ABI have different set of call used registers.  Avoid
+   expensive re-initialization of init_regs each time we switch function context
+   since this is needed only during RTL expansion.  */
 static void
 ix86_maybe_switch_abi (void)
 {
@@ -5806,7 +5925,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum,  /* Argument info to initialize */
 
   /* Set up the number of registers to use for passing arguments.  */
 
-  if (cum->call_abi == MS_ABI && !ACCUMULATE_OUTGOING_ARGS)
+  if (TARGET_64BIT && cum->call_abi == MS_ABI && !ACCUMULATE_OUTGOING_ARGS)
     sorry ("ms_abi attribute requires -maccumulate-outgoing-args "
           "or subtarget optimization implying it");
   cum->nregs = ix86_regparm;
@@ -5838,7 +5957,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum,  /* Argument info to initialize */
      va_start so for local functions maybe_vaarg can be made aggressive
      helping K&R code.
      FIXME: once typesytem is fixed, we won't need this code anymore.  */
-  if (i && i->local)
+  if (i && i->local && i->can_change_signature)
     fntype = TREE_TYPE (fndecl);
   cum->maybe_vaarg = (fntype
                      ? (!prototype_p (fntype) || stdarg_p (fntype))
@@ -5863,12 +5982,13 @@ init_cumulative_args (CUMULATIVE_ARGS *cum,  /* Argument info to initialize */
         else look for regparm information.  */
       if (fntype)
        {
-         if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (fntype)))
+         unsigned int ccvt = ix86_get_callcvt (fntype);
+         if ((ccvt & IX86_CALLCVT_THISCALL) != 0)
            {
              cum->nregs = 1;
              cum->fastcall = 1; /* Same first register as in fastcall.  */
            }
-         else if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
+         else if ((ccvt & IX86_CALLCVT_FASTCALL) != 0)
            {
              cum->nregs = 2;
              cum->fastcall = 1;
@@ -8054,7 +8174,7 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
     case V4DFmode:
     case V4DImode:
       /* Unnamed 256bit vector mode parameters are passed on stack.  */
-      if (ix86_cfun_abi () == SYSV_ABI)
+      if (!TARGET_64BIT_MS_ABI)
        {
          container = NULL;
          break;
@@ -8489,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:
@@ -8516,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;
     }
@@ -8650,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];
@@ -8662,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;
@@ -8910,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
@@ -8920,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)
     {
@@ -8935,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]
@@ -8970,7 +9091,7 @@ ix86_nsaved_sseregs (void)
   int nregs = 0;
   int regno;
 
-  if (ix86_cfun_abi () != MS_ABI)
+  if (!TARGET_64BIT_MS_ABI)
     return 0;
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
     if (SSE_REGNO_P (regno) && ix86_save_reg (regno, true))
@@ -9082,9 +9203,9 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
   stack_alignment_needed = crtl->stack_alignment_needed / BITS_PER_UNIT;
   preferred_alignment = crtl->preferred_stack_boundary / BITS_PER_UNIT;
 
-  /* MS ABI seem to require stack alignment to be always 16 except for function
-     prologues and leaf.  */
-  if ((ix86_cfun_abi () == MS_ABI && preferred_alignment < 16)
+  /* 64-bit MS ABI seem to require stack alignment to be always 16 except for
+     function prologues and leaf.  */
+  if ((TARGET_64BIT_MS_ABI && preferred_alignment < 16)
       && (!current_function_is_leaf || cfun->calls_alloca != 0
           || ix86_current_function_calls_tls_descriptor))
     {
@@ -9113,7 +9234,7 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
            && cfun->machine->use_fast_prologue_epilogue_nregs != frame->nregs)
     {
       int count = frame->nregs;
-      struct cgraph_node *node = cgraph_node (current_function_decl);
+      struct cgraph_node *node = cgraph_get_node (current_function_decl);
 
       cfun->machine->use_fast_prologue_epilogue_nregs = count;
 
@@ -9191,7 +9312,13 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
   offset += frame->va_arg_size;
 
   /* Align start of frame for local function.  */
-  offset = (offset + stack_alignment_needed - 1) & -stack_alignment_needed;
+  if (stack_realign_fp
+      || offset != frame->sse_reg_save_offset
+      || size != 0
+      || !current_function_is_leaf
+      || cfun->calls_alloca
+      || ix86_current_function_calls_tls_descriptor)
+    offset = (offset + stack_alignment_needed - 1) & -stack_alignment_needed;
 
   /* Frame pointer points here.  */
   frame->frame_pointer_offset = offset;
@@ -9648,14 +9775,13 @@ find_drap_reg (void)
 
       /* Reuse static chain register if it isn't used for parameter
          passing.  */
-      if (ix86_function_regparm (TREE_TYPE (decl), decl) <= 2
-         && !lookup_attribute ("fastcall",
-                               TYPE_ATTRIBUTES (TREE_TYPE (decl)))
-         && !lookup_attribute ("thiscall",
-                               TYPE_ATTRIBUTES (TREE_TYPE (decl))))
-       return CX_REG;
-      else
-       return DI_REG;
+      if (ix86_function_regparm (TREE_TYPE (decl), decl) <= 2)
+       {
+         unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (decl));
+         if ((ccvt & (IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL)) == 0)
+           return CX_REG;
+       }
+      return DI_REG;
     }
 }
 
@@ -9859,7 +9985,7 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size)
      probe that many bytes past the specified size to maintain a protection
      area at the botton of the stack.  */
   const int dope = 4 * UNITS_PER_WORD;
-  rtx size_rtx = GEN_INT (size);
+  rtx size_rtx = GEN_INT (size), last;
 
   /* See if we have a constant small number of probes to generate.  If so,
      that's the easy case.  The run-time loop is made up of 11 insns in the
@@ -9899,9 +10025,9 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size)
       emit_stack_probe (stack_pointer_rtx);
 
       /* Adjust back to account for the additional first interval.  */
-      emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
-                             plus_constant (stack_pointer_rtx,
-                                            PROBE_INTERVAL + dope)));
+      last = emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+                                    plus_constant (stack_pointer_rtx,
+                                                   PROBE_INTERVAL + dope)));
     }
 
   /* Otherwise, do the same as above, but in a loop.  Note that we must be
@@ -9962,15 +10088,33 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size)
        }
 
       /* Adjust back to account for the additional first interval.  */
-      emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
-                             plus_constant (stack_pointer_rtx,
-                                            PROBE_INTERVAL + dope)));
+      last = emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+                                    plus_constant (stack_pointer_rtx,
+                                                   PROBE_INTERVAL + dope)));
 
       release_scratch_register_on_entry (&sr);
     }
 
   gcc_assert (cfun->machine->fs.cfa_reg != stack_pointer_rtx);
-  cfun->machine->fs.sp_offset += size;
+
+  /* Even if the stack pointer isn't the CFA register, we need to correctly
+     describe the adjustments made to it, in particular differentiate the
+     frame-related ones from the frame-unrelated ones.  */
+  if (size > 0)
+    {
+      rtx expr = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (2));
+      XVECEXP (expr, 0, 0)
+       = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+                      plus_constant (stack_pointer_rtx, -size));
+      XVECEXP (expr, 0, 1)
+       = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+                      plus_constant (stack_pointer_rtx,
+                                     PROBE_INTERVAL + dope + size));
+      add_reg_note (last, REG_FRAME_RELATED_EXPR, expr);
+      RTX_FRAME_RELATED_P (last) = 1;
+
+      cfun->machine->fs.sp_offset += size;
+    }
 
   /* Make sure nothing is scheduled before we are done.  */
   emit_insn (gen_blockage ());
@@ -10402,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;
@@ -10426,8 +10570,8 @@ ix86_expand_prologue (void)
     }
 
   /* The stack has already been decremented by the instruction calling us
-     so we need to probe unconditionally to preserve the protection area.  */
-  if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
+     so probe if the size is non-negative to preserve the protection area.  */
+  if (allocate >= 0 && flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
     {
       /* We expect the registers to be saved when probes are used.  */
       gcc_assert (int_registers_saved);
@@ -10721,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;
@@ -10760,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;
 
@@ -11379,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
@@ -11725,8 +11869,8 @@ darwin_local_data_pic (rtx disp)
 /* Determine if a given RTX is a valid constant.  We already know this
    satisfies CONSTANT_P.  */
 
-bool
-legitimate_constant_p (rtx x)
+static bool
+ix86_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
 {
   switch (GET_CODE (x))
     {
@@ -11812,7 +11956,7 @@ legitimate_constant_p (rtx x)
    is checked above.  */
 
 static bool
-ix86_cannot_force_const_mem (rtx x)
+ix86_cannot_force_const_mem (enum machine_mode mode, rtx x)
 {
   /* We can always put integral constants and vectors in memory.  */
   switch (GET_CODE (x))
@@ -11825,7 +11969,7 @@ ix86_cannot_force_const_mem (rtx x)
     default:
       break;
     }
-  return !legitimate_constant_p (x);
+  return !ix86_legitimate_constant_p (mode, x);
 }
 
 
@@ -12163,7 +12307,8 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
            /* Displacement is an invalid pic construct.  */
            return false;
 #if TARGET_MACHO
-         else if (MACHO_DYNAMIC_NO_PIC_P && !legitimate_constant_p (disp))
+         else if (MACHO_DYNAMIC_NO_PIC_P
+                  && !ix86_legitimate_constant_p (Pmode, disp))
            /* displacment must be referenced via non_lazy_pointer */
            return false;
 #endif
@@ -12193,9 +12338,9 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
       else if (GET_CODE (disp) != LABEL_REF
               && !CONST_INT_P (disp)
               && (GET_CODE (disp) != CONST
-                  || !legitimate_constant_p (disp))
+                  || !ix86_legitimate_constant_p (Pmode, disp))
               && (GET_CODE (disp) != SYMBOL_REF
-                  || !legitimate_constant_p (disp)))
+                  || !ix86_legitimate_constant_p (Pmode, disp)))
        /* Displacement is not constant.  */
        return false;
       else if (TARGET_64BIT
@@ -12479,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;
 
@@ -12494,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);
@@ -12577,12 +12800,22 @@ 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:
       if (TARGET_64BIT)
        {
+         if (TARGET_SUN_TLS)
+           {
+             /* The Sun linker took the AMD64 TLS spec literally
+                and can only handle %rax as destination of the
+                initial executable code sequence.  */
+
+             dest = gen_reg_rtx (Pmode);
+             emit_insn (gen_tls_initial_exec_64_sun (dest, x));
+             return dest;
+           }
+
          pic = NULL;
          type = UNSPEC_GOTNTPOFF;
        }
@@ -13232,7 +13465,11 @@ ix86_delegitimize_address (rtx x)
        return ix86_delegitimize_tls_address (orig_x);
       x = XVECEXP (XEXP (x, 0), 0, 0);
       if (GET_MODE (orig_x) != Pmode)
-       return simplify_gen_subreg (GET_MODE (orig_x), x, Pmode, 0);
+       {
+         x = simplify_gen_subreg (GET_MODE (orig_x), x, Pmode, 0);
+         if (x == NULL_RTX)
+           return orig_x;
+       }
       return x;
     }
 
@@ -13301,7 +13538,11 @@ ix86_delegitimize_address (rtx x)
        return orig_x;
     }
   if (GET_MODE (orig_x) != Pmode && MEM_P (orig_x))
-    return simplify_gen_subreg (GET_MODE (orig_x), result, Pmode, 0);
+    {
+      result = simplify_gen_subreg (GET_MODE (orig_x), result, Pmode, 0);
+      if (result == NULL_RTX)
+       return orig_x;
+    }
   return result;
 }
 
@@ -13677,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
@@ -13882,6 +14124,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
        case 'x':
        case 'X':
        case 'P':
+       case 'p':
          break;
 
        case 's':
@@ -14248,17 +14491,21 @@ ix86_print_operand (FILE *file, rtx x, int code)
        fprintf (file, "0x%08x", (unsigned int) l);
     }
 
-  /* These float cases don't actually occur as immediate operands.  */
   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
     {
-      char dstr[30];
+      REAL_VALUE_TYPE r;
+      long l[2];
 
-      real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (x), sizeof (dstr), 0, 1);
-      fputs (dstr, file);
+      REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+      REAL_VALUE_TO_TARGET_DOUBLE (r, l);
+
+      if (ASSEMBLER_DIALECT == ASM_ATT)
+       putc ('$', file);
+      fprintf (file, "0x%lx%08lx", l[1] & 0xffffffff, l[0] & 0xffffffff);
     }
 
-  else if (GET_CODE (x) == CONST_DOUBLE
-          && GET_MODE (x) == XFmode)
+  /* These float cases don't actually occur as immediate operands.  */
+  else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == XFmode)
     {
       char dstr[30];
 
@@ -14277,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)
            {
@@ -14957,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;
@@ -15022,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;
@@ -15427,6 +15674,57 @@ ix86_expand_vector_move (enum machine_mode mode, rtx operands[])
   emit_insn (gen_rtx_SET (VOIDmode, op0, op1));
 }
 
+/* Split 32-byte AVX unaligned load and store if needed.  */
+
+static void
+ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1)
+{
+  rtx m;
+  rtx (*extract) (rtx, rtx, rtx);
+  rtx (*move_unaligned) (rtx, rtx);
+  enum machine_mode mode;
+
+  switch (GET_MODE (op0))
+    {
+    default:
+      gcc_unreachable ();
+    case V32QImode:
+      extract = gen_avx_vextractf128v32qi;
+      move_unaligned = gen_avx_movdqu256;
+      mode = V16QImode;
+      break;
+    case V8SFmode:
+      extract = gen_avx_vextractf128v8sf;
+      move_unaligned = gen_avx_movups256;
+      mode = V4SFmode;
+      break;
+    case V4DFmode:
+      extract = gen_avx_vextractf128v4df;
+      move_unaligned = gen_avx_movupd256;
+      mode = V2DFmode;
+      break;
+    }
+
+  if (MEM_P (op1) && TARGET_AVX256_SPLIT_UNALIGNED_LOAD)
+    {
+      rtx r = gen_reg_rtx (mode);
+      m = adjust_address (op1, mode, 0);
+      emit_move_insn (r, m);
+      m = adjust_address (op1, mode, 16);
+      r = gen_rtx_VEC_CONCAT (GET_MODE (op0), r, m);
+      emit_move_insn (op0, r);
+    }
+  else if (MEM_P (op0) && TARGET_AVX256_SPLIT_UNALIGNED_STORE)
+    {
+      m = adjust_address (op0, mode, 0);
+      emit_insn (extract (m, op1, const0_rtx));
+      m = adjust_address (op0, mode, 16);
+      emit_insn (extract (m, op1, const1_rtx));
+    }
+  else
+    emit_insn (move_unaligned (op0, op1));
+}
+
 /* Implement the movmisalign patterns for SSE.  Non-SSE modes go
    straight to ix86_expand_vector_move.  */
 /* Code generation for scalar reg-reg moves of single and double precision data:
@@ -15501,17 +15799,17 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
                {
                  op0 = gen_lowpart (V4SFmode, op0);
                  op1 = gen_lowpart (V4SFmode, op1);
-                 emit_insn (gen_avx_movups (op0, op1));
+                 emit_insn (gen_sse_movups (op0, op1));
                  return;
                }
              op0 = gen_lowpart (V16QImode, op0);
              op1 = gen_lowpart (V16QImode, op1);
-             emit_insn (gen_avx_movdqu (op0, op1));
+             emit_insn (gen_sse2_movdqu (op0, op1));
              break;
            case 32:
              op0 = gen_lowpart (V32QImode, op0);
              op1 = gen_lowpart (V32QImode, op1);
-             emit_insn (gen_avx_movdqu256 (op0, op1));
+             ix86_avx256_split_vector_move_misalign (op0, op1);
              break;
            default:
              gcc_unreachable ();
@@ -15524,23 +15822,23 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
          switch (mode)
            {
            case V4SFmode:
-             emit_insn (gen_avx_movups (op0, op1));
+             emit_insn (gen_sse_movups (op0, op1));
              break;
            case V8SFmode:
-             emit_insn (gen_avx_movups256 (op0, op1));
+             ix86_avx256_split_vector_move_misalign (op0, op1);
              break;
            case V2DFmode:
              if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
                {
                  op0 = gen_lowpart (V4SFmode, op0);
                  op1 = gen_lowpart (V4SFmode, op1);
-                 emit_insn (gen_avx_movups (op0, op1));
+                 emit_insn (gen_sse_movups (op0, op1));
                  return;
                }
-             emit_insn (gen_avx_movupd (op0, op1));
+             emit_insn (gen_sse2_movupd (op0, op1));
              break;
            case V4DFmode:
-             emit_insn (gen_avx_movupd256 (op0, op1));
+             ix86_avx256_split_vector_move_misalign (op0, op1);
              break;
            default:
              gcc_unreachable ();
@@ -15967,7 +16265,7 @@ ix86_expand_unary_operator (enum rtx_code code, enum machine_mode mode,
 }
 
 /* Split 32bit/64bit divmod with 8bit unsigned divmod if dividend and
-   divisor are within the the range [0-255].  */
+   divisor are within the range [0-255].  */
 
 void
 ix86_split_idivmod (enum machine_mode mode, rtx operands[],
@@ -16001,7 +16299,7 @@ ix86_split_idivmod (enum machine_mode mode, rtx operands[],
 
   scratch = gen_reg_rtx (mode);
 
-  /* Use 8bit unsigned divimod if dividend and divisor are within the
+  /* Use 8bit unsigned divimod if dividend and divisor are within
      the range [0-255].  */
   emit_move_insn (scratch, operands[2]);
   scratch = expand_simple_binop (mode, IOR, scratch, operands[3],
@@ -17031,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:
@@ -18832,91 +19134,87 @@ void
 ix86_expand_sse_unpack (rtx operands[2], bool unsigned_p, bool high_p)
 {
   enum machine_mode imode = GET_MODE (operands[1]);
-  rtx (*unpack)(rtx, rtx, rtx);
-  rtx se, dest;
+  rtx tmp, dest;
 
-  switch (imode)
+  if (TARGET_SSE4_1)
     {
-    case V16QImode:
-      if (high_p)
-        unpack = gen_vec_interleave_highv16qi;
-      else
-        unpack = gen_vec_interleave_lowv16qi;
-      break;
-    case V8HImode:
-      if (high_p)
-        unpack = gen_vec_interleave_highv8hi;
-      else
-        unpack = gen_vec_interleave_lowv8hi;
-      break;
-    case V4SImode:
+      rtx (*unpack)(rtx, rtx);
+
+      switch (imode)
+       {
+       case V16QImode:
+         if (unsigned_p)
+           unpack = gen_sse4_1_zero_extendv8qiv8hi2;
+         else
+           unpack = gen_sse4_1_sign_extendv8qiv8hi2;
+         break;
+       case V8HImode:
+         if (unsigned_p)
+           unpack = gen_sse4_1_zero_extendv4hiv4si2;
+         else
+           unpack = gen_sse4_1_sign_extendv4hiv4si2;
+         break;
+       case V4SImode:
+         if (unsigned_p)
+           unpack = gen_sse4_1_zero_extendv2siv2di2;
+         else
+           unpack = gen_sse4_1_sign_extendv2siv2di2;
+         break;
+       default:
+         gcc_unreachable ();
+       }
+
       if (high_p)
-        unpack = gen_vec_interleave_highv4si;
+       {
+         /* Shift higher 8 bytes to lower 8 bytes.  */
+         tmp = gen_reg_rtx (imode);
+         emit_insn (gen_sse2_lshrv1ti3 (gen_lowpart (V1TImode, tmp),
+                                        gen_lowpart (V1TImode, operands[1]),
+                                        GEN_INT (64)));
+       }
       else
-        unpack = gen_vec_interleave_lowv4si;
-      break;
-    default:
-      gcc_unreachable ();
-    }
+       tmp = operands[1];
 
-  dest = gen_lowpart (imode, operands[0]);
-
-  if (unsigned_p)
-    se = force_reg (imode, CONST0_RTX (imode));
+      emit_insn (unpack (operands[0], tmp));
+    }
   else
-    se = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
-                              operands[1], pc_rtx, pc_rtx);
-
-  emit_insn (unpack (dest, operands[1], se));
-}
+    {
+      rtx (*unpack)(rtx, rtx, rtx);
 
-/* This function performs the same task as ix86_expand_sse_unpack,
-   but with SSE4.1 instructions.  */
+      switch (imode)
+       {
+       case V16QImode:
+         if (high_p)
+           unpack = gen_vec_interleave_highv16qi;
+         else
+           unpack = gen_vec_interleave_lowv16qi;
+         break;
+       case V8HImode:
+         if (high_p)
+           unpack = gen_vec_interleave_highv8hi;
+         else
+           unpack = gen_vec_interleave_lowv8hi;
+         break;
+       case V4SImode:
+         if (high_p)
+           unpack = gen_vec_interleave_highv4si;
+         else
+           unpack = gen_vec_interleave_lowv4si;
+         break;
+       default:
+         gcc_unreachable ();
+       }
 
-void
-ix86_expand_sse4_unpack (rtx operands[2], bool unsigned_p, bool high_p)
-{
-  enum machine_mode imode = GET_MODE (operands[1]);
-  rtx (*unpack)(rtx, rtx);
-  rtx src, dest;
+      dest = gen_lowpart (imode, operands[0]);
 
-  switch (imode)
-    {
-    case V16QImode:
-      if (unsigned_p)
-       unpack = gen_sse4_1_zero_extendv8qiv8hi2;
-      else
-       unpack = gen_sse4_1_sign_extendv8qiv8hi2;
-      break;
-    case V8HImode:
       if (unsigned_p)
-       unpack = gen_sse4_1_zero_extendv4hiv4si2;
+       tmp = force_reg (imode, CONST0_RTX (imode));
       else
-       unpack = gen_sse4_1_sign_extendv4hiv4si2;
-      break;
-    case V4SImode:
-      if (unsigned_p)
-       unpack = gen_sse4_1_zero_extendv2siv2di2;
-      else
-       unpack = gen_sse4_1_sign_extendv2siv2di2;
-      break;
-    default:
-      gcc_unreachable ();
-    }
+       tmp = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
+                                  operands[1], pc_rtx, pc_rtx);
 
-  dest = operands[0];
-  if (high_p)
-    {
-      /* Shift higher 8 bytes to lower 8 bytes.  */
-      src = gen_reg_rtx (imode);
-      emit_insn (gen_sse2_lshrv1ti3 (gen_lowpart (V1TImode, src),
-                                    gen_lowpart (V1TImode, operands[1]),
-                                    GEN_INT (64)));
+      emit_insn (unpack (dest, operands[1], tmp));
     }
-  else
-    src = operands[1];
-
-  emit_insn (unpack (dest, src));
 }
 
 /* Expand conditional increment or decrement using adb/sbb instructions.
@@ -20545,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)
     {
@@ -20702,23 +21000,24 @@ smallest_pow2_greater_than (int val)
   return ret;
 }
 
-/* Expand string move (memcpy) operation.  Use i386 string operations when
-   profitable.  expand_setmem contains similar code.  The code depends upon
-   architecture, block size and alignment, but always has the same
-   overall structure:
+/* Expand string move (memcpy) operation.  Use i386 string operations
+   when profitable.  expand_setmem contains similar code.  The code
+   depends upon architecture, block size and alignment, but always has
+   the same overall structure:
 
    1) Prologue guard: Conditional that jumps up to epilogues for small
-      blocks that can be handled by epilogue alone.  This is faster but
-      also needed for correctness, since prologue assume the block is larger
-      than the desired alignment.
+      blocks that can be handled by epilogue alone.  This is faster
+      but also needed for correctness, since prologue assume the block
+      is larger than the desired alignment.
 
       Optional dynamic check for size and libcall for large
       blocks is emitted here too, with -minline-stringops-dynamically.
 
-   2) Prologue: copy first few bytes in order to get destination aligned
-      to DESIRED_ALIGN.  It is emitted only when ALIGN is less than
-      DESIRED_ALIGN and and up to DESIRED_ALIGN - ALIGN bytes can be copied.
-      We emit either a jump tree on power of two sized blocks, or a byte loop.
+   2) Prologue: copy first few bytes in order to get destination
+      aligned to DESIRED_ALIGN.  It is emitted only when ALIGN is less
+      than DESIRED_ALIGN and up to DESIRED_ALIGN - ALIGN bytes can be
+      copied.  We emit either a jump tree on power of two sized
+      blocks, or a byte loop.
 
    3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
       with specified algorithm.
@@ -21670,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;
 
@@ -21723,8 +22022,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
       pop = gen_rtx_SET (VOIDmode, stack_pointer_rtx, pop);
       call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, call, pop));
     }
-  if (TARGET_64BIT
-      && ix86_cfun_abi () == MS_ABI
+  if (TARGET_64BIT_MS_ABI
       && (!callarg2 || INTVAL (callarg2) != -2))
     {
       /* We need to represent that SI and DI registers are clobbered
@@ -21803,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
@@ -21853,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.
@@ -21914,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.  */
@@ -22074,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;
@@ -22184,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;
 
@@ -22233,6 +22492,10 @@ ix86_issue_rate (void)
 
     case PROCESSOR_PENTIUMPRO:
     case PROCESSOR_PENTIUM4:
+    case PROCESSOR_CORE2_32:
+    case PROCESSOR_CORE2_64:
+    case PROCESSOR_COREI7_32:
+    case PROCESSOR_COREI7_64:
     case PROCESSOR_ATHLON:
     case PROCESSOR_K8:
     case PROCESSOR_AMDFAM10:
@@ -22240,20 +22503,18 @@ ix86_issue_rate (void)
     case PROCESSOR_GENERIC32:
     case PROCESSOR_GENERIC64:
     case PROCESSOR_BDVER1:
+    case PROCESSOR_BTVER1:
       return 3;
 
-    case PROCESSOR_CORE2:
-      return 4;
-
     default:
       return 1;
     }
 }
 
-/* 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;
@@ -22263,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)
     {
@@ -22279,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
@@ -22430,6 +22691,7 @@ ix86_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
     case PROCESSOR_K8:
     case PROCESSOR_AMDFAM10:
     case PROCESSOR_BDVER1:
+    case PROCESSOR_BTVER1:
     case PROCESSOR_ATOM:
     case PROCESSOR_GENERIC32:
     case PROCESSOR_GENERIC64:
@@ -22483,7 +22745,8 @@ ia32_multipass_dfa_lookahead (void)
     case PROCESSOR_K6:
       return 1;
 
-    case PROCESSOR_CORE2:
+    case PROCESSOR_CORE2_32:
+    case PROCESSOR_CORE2_64:
     case PROCESSOR_COREI7_32:
     case PROCESSOR_COREI7_64:
       /* Generally, we want haifa-sched:max_issue() to look ahead as far
@@ -22705,7 +22968,8 @@ ix86_sched_init_global (FILE *dump ATTRIBUTE_UNUSED,
      they are actually used.  */
   switch (ix86_tune)
     {
-    case PROCESSOR_CORE2:
+    case PROCESSOR_CORE2_32:
+    case PROCESSOR_CORE2_64:
     case PROCESSOR_COREI7_32:
     case PROCESSOR_COREI7_64:
       targetm.sched.dfa_post_advance_cycle
@@ -22896,8 +23160,9 @@ ix86_local_alignment (tree exp, enum machine_mode mode,
       && TARGET_SSE)
     {
       if (AGGREGATE_TYPE_P (type)
-          && (TYPE_MAIN_VARIANT (type)
-              != TYPE_MAIN_VARIANT (va_list_type_node))
+          && (va_list_type_node == NULL_TREE
+              || (TYPE_MAIN_VARIANT (type)
+                  != TYPE_MAIN_VARIANT (va_list_type_node)))
           && TYPE_SIZE (type)
           && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
           && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 16
@@ -22995,20 +23260,19 @@ ix86_static_chain (const_tree fndecl, bool incoming_p)
   else
     {
       tree fntype;
+      unsigned int ccvt;
+
       /* By default in 32-bit mode we use ECX to pass the static chain.  */
       regno = CX_REG;
 
       fntype = TREE_TYPE (fndecl);
-      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
+      ccvt = ix86_get_callcvt (fntype);
+      if ((ccvt & (IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL)) != 0)
        {
          /* Fastcall functions use ecx/edx for arguments, which leaves
-            us with EAX for the static chain.  */
-         regno = AX_REG;
-       }
-      else if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (fntype)))
-       {
-         /* Thiscall functions use ecx for arguments, which leaves
-            us with EAX for the static chain.  */
+            us with EAX for the static chain.
+            Thiscall functions use ecx for arguments, which also
+            leaves us with EAX for the static chain.  */
          regno = AX_REG;
        }
       else if (ix86_function_regparm (fntype, fndecl) == 3)
@@ -23650,6 +23914,7 @@ enum ix86_builtins
   IX86_BUILTIN_CLFLUSH,
   IX86_BUILTIN_MFENCE,
   IX86_BUILTIN_LFENCE,
+  IX86_BUILTIN_PAUSE,
 
   IX86_BUILTIN_BSRSI,
   IX86_BUILTIN_BSRDI,
@@ -23769,6 +24034,15 @@ enum ix86_builtins
   IX86_BUILTIN_ROUNDSD,
   IX86_BUILTIN_ROUNDSS,
 
+  IX86_BUILTIN_FLOORPD,
+  IX86_BUILTIN_CEILPD,
+  IX86_BUILTIN_TRUNCPD,
+  IX86_BUILTIN_RINTPD,
+  IX86_BUILTIN_FLOORPS,
+  IX86_BUILTIN_CEILPS,
+  IX86_BUILTIN_TRUNCPS,
+  IX86_BUILTIN_RINTPS,
+
   IX86_BUILTIN_PTESTZ,
   IX86_BUILTIN_PTESTC,
   IX86_BUILTIN_PTESTNZC,
@@ -23936,6 +24210,15 @@ enum ix86_builtins
   IX86_BUILTIN_ROUNDPD256,
   IX86_BUILTIN_ROUNDPS256,
 
+  IX86_BUILTIN_FLOORPD256,
+  IX86_BUILTIN_CEILPD256,
+  IX86_BUILTIN_TRUNCPD256,
+  IX86_BUILTIN_RINTPD256,
+  IX86_BUILTIN_FLOORPS256,
+  IX86_BUILTIN_CEILPS256,
+  IX86_BUILTIN_TRUNCPS256,
+  IX86_BUILTIN_RINTPS256,
+
   IX86_BUILTIN_UNPCKHPD256,
   IX86_BUILTIN_UNPCKLPD256,
   IX86_BUILTIN_UNPCKHPS256,
@@ -24180,9 +24463,9 @@ enum ix86_builtins
   IX86_BUILTIN_WRGSBASE64,
 
   /* RDRND instructions.  */
-  IX86_BUILTIN_RDRAND16,
-  IX86_BUILTIN_RDRAND32,
-  IX86_BUILTIN_RDRAND64,
+  IX86_BUILTIN_RDRAND16_STEP,
+  IX86_BUILTIN_RDRAND32_STEP,
+  IX86_BUILTIN_RDRAND64_STEP,
 
   /* F16C instructions.  */
   IX86_BUILTIN_CVTPH2PS,
@@ -24190,6 +24473,9 @@ enum ix86_builtins
   IX86_BUILTIN_CVTPS2PH,
   IX86_BUILTIN_CVTPS2PH256,
 
+  /* CFString built-in for darwin */
+  IX86_BUILTIN_CFSTRING,
+
   IX86_BUILTIN_MAX
 };
 
@@ -24381,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 },
@@ -24448,14 +24735,14 @@ static const struct builtin_description bdesc_special_args[] =
   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movntv4df, "__builtin_ia32_movntpd256", IX86_BUILTIN_MOVNTPD256, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V4DF },
   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movntv8sf, "__builtin_ia32_movntps256", IX86_BUILTIN_MOVNTPS256, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V8SF },
 
-  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadpd, "__builtin_ia32_maskloadpd", IX86_BUILTIN_MASKLOADPD, UNKNOWN, (int) V2DF_FTYPE_PCV2DF_V2DF },
-  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadps, "__builtin_ia32_maskloadps", IX86_BUILTIN_MASKLOADPS, UNKNOWN, (int) V4SF_FTYPE_PCV4SF_V4SF },
-  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadpd256, "__builtin_ia32_maskloadpd256", IX86_BUILTIN_MASKLOADPD256, UNKNOWN, (int) V4DF_FTYPE_PCV4DF_V4DF },
-  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadps256, "__builtin_ia32_maskloadps256", IX86_BUILTIN_MASKLOADPS256, UNKNOWN, (int) V8SF_FTYPE_PCV8SF_V8SF },
-  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstorepd, "__builtin_ia32_maskstorepd", IX86_BUILTIN_MASKSTOREPD, UNKNOWN, (int) VOID_FTYPE_PV2DF_V2DF_V2DF },
-  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstoreps, "__builtin_ia32_maskstoreps", IX86_BUILTIN_MASKSTOREPS, UNKNOWN, (int) VOID_FTYPE_PV4SF_V4SF_V4SF },
-  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstorepd256, "__builtin_ia32_maskstorepd256", IX86_BUILTIN_MASKSTOREPD256, UNKNOWN, (int) VOID_FTYPE_PV4DF_V4DF_V4DF },
-  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstoreps256, "__builtin_ia32_maskstoreps256", IX86_BUILTIN_MASKSTOREPS256, UNKNOWN, (int) VOID_FTYPE_PV8SF_V8SF_V8SF },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadpd, "__builtin_ia32_maskloadpd", IX86_BUILTIN_MASKLOADPD, UNKNOWN, (int) V2DF_FTYPE_PCV2DF_V2DI },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadps, "__builtin_ia32_maskloadps", IX86_BUILTIN_MASKLOADPS, UNKNOWN, (int) V4SF_FTYPE_PCV4SF_V4SI },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadpd256, "__builtin_ia32_maskloadpd256", IX86_BUILTIN_MASKLOADPD256, UNKNOWN, (int) V4DF_FTYPE_PCV4DF_V4DI },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskloadps256, "__builtin_ia32_maskloadps256", IX86_BUILTIN_MASKLOADPS256, UNKNOWN, (int) V8SF_FTYPE_PCV8SF_V8SI },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstorepd, "__builtin_ia32_maskstorepd", IX86_BUILTIN_MASKSTOREPD, UNKNOWN, (int) VOID_FTYPE_PV2DF_V2DI_V2DF },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstoreps, "__builtin_ia32_maskstoreps", IX86_BUILTIN_MASKSTOREPS, UNKNOWN, (int) VOID_FTYPE_PV4SF_V4SI_V4SF },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstorepd256, "__builtin_ia32_maskstorepd256", IX86_BUILTIN_MASKSTOREPD256, UNKNOWN, (int) VOID_FTYPE_PV4DF_V4DI_V4DF },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_maskstoreps256, "__builtin_ia32_maskstoreps256", IX86_BUILTIN_MASKSTOREPS256, UNKNOWN, (int) VOID_FTYPE_PV8SF_V8SI_V8SF },
 
   { OPTION_MASK_ISA_LWP, CODE_FOR_lwp_llwpcb, "__builtin_ia32_llwpcb", IX86_BUILTIN_LLWPCB, UNKNOWN, (int) VOID_FTYPE_PVOID },
   { OPTION_MASK_ISA_LWP, CODE_FOR_lwp_slwpcb, "__builtin_ia32_slwpcb", IX86_BUILTIN_SLWPCB, UNKNOWN, (int) PVOID_FTYPE_VOID },
@@ -24473,11 +24760,6 @@ static const struct builtin_description bdesc_special_args[] =
   { OPTION_MASK_ISA_FSGSBASE | OPTION_MASK_ISA_64BIT, CODE_FOR_wrfsbasedi, "__builtin_ia32_wrfsbase64", IX86_BUILTIN_WRFSBASE64, UNKNOWN, (int) VOID_FTYPE_UINT64 },
   { OPTION_MASK_ISA_FSGSBASE | OPTION_MASK_ISA_64BIT, CODE_FOR_wrgsbasesi, "__builtin_ia32_wrgsbase32", IX86_BUILTIN_WRGSBASE32, UNKNOWN, (int) VOID_FTYPE_UNSIGNED },
   { OPTION_MASK_ISA_FSGSBASE | OPTION_MASK_ISA_64BIT, CODE_FOR_wrgsbasedi, "__builtin_ia32_wrgsbase64", IX86_BUILTIN_WRGSBASE64, UNKNOWN, (int) VOID_FTYPE_UINT64 },
-
-  /* RDRND */
-  { OPTION_MASK_ISA_RDRND, CODE_FOR_rdrandhi, "__builtin_ia32_rdrand16", IX86_BUILTIN_RDRAND16, UNKNOWN, (int) UINT16_FTYPE_VOID },
-  { OPTION_MASK_ISA_RDRND, CODE_FOR_rdrandsi, "__builtin_ia32_rdrand32", IX86_BUILTIN_RDRAND32, UNKNOWN, (int) UNSIGNED_FTYPE_VOID },
-  { OPTION_MASK_ISA_RDRND | OPTION_MASK_ISA_64BIT, CODE_FOR_rdranddi, "__builtin_ia32_rdrand64", IX86_BUILTIN_RDRAND64, UNKNOWN, (int) UINT64_FTYPE_VOID },
 };
 
 /* Builtins with variable number of arguments.  */
@@ -24960,6 +25242,16 @@ static const struct builtin_description bdesc_args[] =
   { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundsd, "__builtin_ia32_roundsd", IX86_BUILTIN_ROUNDSD, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_INT },
   { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundss, "__builtin_ia32_roundss", IX86_BUILTIN_ROUNDSS, UNKNOWN, (int) V4SF_FTYPE_V4SF_V4SF_INT },
 
+  { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_floorpd", IX86_BUILTIN_FLOORPD, (enum rtx_code) ROUND_FLOOR, (int) V2DF_FTYPE_V2DF_ROUND },
+  { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_ceilpd", IX86_BUILTIN_CEILPD, (enum rtx_code) ROUND_CEIL, (int) V2DF_FTYPE_V2DF_ROUND },
+  { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_truncpd", IX86_BUILTIN_TRUNCPD, (enum rtx_code) ROUND_TRUNC, (int) V2DF_FTYPE_V2DF_ROUND },
+  { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_rintpd", IX86_BUILTIN_RINTPD, (enum rtx_code) ROUND_MXCSR, (int) V2DF_FTYPE_V2DF_ROUND },
+
+  { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps, "__builtin_ia32_floorps", IX86_BUILTIN_FLOORPS, (enum rtx_code) ROUND_FLOOR, (int) V4SF_FTYPE_V4SF_ROUND },
+  { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps, "__builtin_ia32_ceilps", IX86_BUILTIN_CEILPS, (enum rtx_code) ROUND_CEIL, (int) V4SF_FTYPE_V4SF_ROUND },
+  { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps, "__builtin_ia32_truncps", IX86_BUILTIN_TRUNCPS, (enum rtx_code) ROUND_TRUNC, (int) V4SF_FTYPE_V4SF_ROUND },
+  { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps, "__builtin_ia32_rintps", IX86_BUILTIN_RINTPS, (enum rtx_code) ROUND_MXCSR, (int) V4SF_FTYPE_V4SF_ROUND },
+
   { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_ptest, "__builtin_ia32_ptestz128", IX86_BUILTIN_PTESTZ, EQ, (int) INT_FTYPE_V2DI_V2DI_PTEST },
   { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_ptest, "__builtin_ia32_ptestc128", IX86_BUILTIN_PTESTC, LTU, (int) INT_FTYPE_V2DI_V2DI_PTEST },
   { OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_ptest, "__builtin_ia32_ptestnzc128", IX86_BUILTIN_PTESTNZC, GTU, (int) INT_FTYPE_V2DI_V2DI_PTEST },
@@ -25029,12 +25321,12 @@ static const struct builtin_description bdesc_args[] =
   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_dpps256, "__builtin_ia32_dpps256", IX86_BUILTIN_DPPS256, UNKNOWN, (int) V8SF_FTYPE_V8SF_V8SF_INT },
   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_shufpd256, "__builtin_ia32_shufpd256", IX86_BUILTIN_SHUFPD256, UNKNOWN, (int) V4DF_FTYPE_V4DF_V4DF_INT },
   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_shufps256, "__builtin_ia32_shufps256", IX86_BUILTIN_SHUFPS256, UNKNOWN, (int) V8SF_FTYPE_V8SF_V8SF_INT },
-  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cmpsdv2df3, "__builtin_ia32_cmpsd", IX86_BUILTIN_CMPSD, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_INT },
-  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cmpssv4sf3, "__builtin_ia32_cmpss", IX86_BUILTIN_CMPSS, UNKNOWN, (int) V4SF_FTYPE_V4SF_V4SF_INT },
-  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cmppdv2df3, "__builtin_ia32_cmppd", IX86_BUILTIN_CMPPD, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_INT },
-  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cmppsv4sf3, "__builtin_ia32_cmpps", IX86_BUILTIN_CMPPS, UNKNOWN, (int) V4SF_FTYPE_V4SF_V4SF_INT },
-  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cmppdv4df3, "__builtin_ia32_cmppd256", IX86_BUILTIN_CMPPD256, UNKNOWN, (int) V4DF_FTYPE_V4DF_V4DF_INT },
-  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cmppsv8sf3, "__builtin_ia32_cmpps256", IX86_BUILTIN_CMPPS256, UNKNOWN, (int) V8SF_FTYPE_V8SF_V8SF_INT },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_vmcmpv2df3, "__builtin_ia32_cmpsd", IX86_BUILTIN_CMPSD, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_INT },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_vmcmpv4sf3, "__builtin_ia32_cmpss", IX86_BUILTIN_CMPSS, UNKNOWN, (int) V4SF_FTYPE_V4SF_V4SF_INT },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cmpv2df3, "__builtin_ia32_cmppd", IX86_BUILTIN_CMPPD, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_INT },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cmpv4sf3, "__builtin_ia32_cmpps", IX86_BUILTIN_CMPPS, UNKNOWN, (int) V4SF_FTYPE_V4SF_V4SF_INT },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cmpv4df3, "__builtin_ia32_cmppd256", IX86_BUILTIN_CMPPD256, UNKNOWN, (int) V4DF_FTYPE_V4DF_V4DF_INT },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cmpv8sf3, "__builtin_ia32_cmpps256", IX86_BUILTIN_CMPPS256, UNKNOWN, (int) V8SF_FTYPE_V8SF_V8SF_INT },
   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_vextractf128v4df, "__builtin_ia32_vextractf128_pd256", IX86_BUILTIN_EXTRACTF128PD256, UNKNOWN, (int) V2DF_FTYPE_V4DF_INT },
   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_vextractf128v8sf, "__builtin_ia32_vextractf128_ps256", IX86_BUILTIN_EXTRACTF128PS256, UNKNOWN, (int) V4SF_FTYPE_V8SF_INT },
   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_vextractf128v8si, "__builtin_ia32_vextractf128_si256", IX86_BUILTIN_EXTRACTF128SI256, UNKNOWN, (int) V4SI_FTYPE_V8SI_INT },
@@ -25072,6 +25364,16 @@ static const struct builtin_description bdesc_args[] =
   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundpd256, "__builtin_ia32_roundpd256", IX86_BUILTIN_ROUNDPD256, UNKNOWN, (int) V4DF_FTYPE_V4DF_INT },
   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundps256, "__builtin_ia32_roundps256", IX86_BUILTIN_ROUNDPS256, UNKNOWN, (int) V8SF_FTYPE_V8SF_INT },
 
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundpd256, "__builtin_ia32_floorpd256", IX86_BUILTIN_FLOORPD256, (enum rtx_code) ROUND_FLOOR, (int) V4DF_FTYPE_V4DF_ROUND },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundpd256, "__builtin_ia32_ceilpd256", IX86_BUILTIN_CEILPD256, (enum rtx_code) ROUND_CEIL, (int) V4DF_FTYPE_V4DF_ROUND },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundpd256, "__builtin_ia32_truncpd256", IX86_BUILTIN_TRUNCPD256, (enum rtx_code) ROUND_TRUNC, (int) V4DF_FTYPE_V4DF_ROUND },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundpd256, "__builtin_ia32_rintpd256", IX86_BUILTIN_RINTPD256, (enum rtx_code) ROUND_MXCSR, (int) V4DF_FTYPE_V4DF_ROUND },
+
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundps256, "__builtin_ia32_floorps256", IX86_BUILTIN_FLOORPS256, (enum rtx_code) ROUND_FLOOR, (int) V8SF_FTYPE_V8SF_ROUND },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundps256, "__builtin_ia32_ceilps256", IX86_BUILTIN_CEILPS256, (enum rtx_code) ROUND_CEIL, (int) V8SF_FTYPE_V8SF_ROUND },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundps256, "__builtin_ia32_truncps256", IX86_BUILTIN_TRUNCPS256, (enum rtx_code) ROUND_TRUNC, (int) V8SF_FTYPE_V8SF_ROUND },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_avx_roundps256, "__builtin_ia32_rintps256", IX86_BUILTIN_RINTPS256, (enum rtx_code) ROUND_MXCSR, (int) V8SF_FTYPE_V8SF_ROUND },
+
   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_unpckhpd256,  "__builtin_ia32_unpckhpd256", IX86_BUILTIN_UNPCKHPD256, UNKNOWN, (int) V4DF_FTYPE_V4DF_V4DF },
   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_unpcklpd256,  "__builtin_ia32_unpcklpd256", IX86_BUILTIN_UNPCKLPD256, UNKNOWN, (int) V4DF_FTYPE_V4DF_V4DF },
   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_unpckhps256,  "__builtin_ia32_unpckhps256", IX86_BUILTIN_UNPCKHPS256, UNKNOWN, (int) V8SF_FTYPE_V8SF_V8SF },
@@ -25486,6 +25788,15 @@ ix86_init_mmx_sse_builtins (void)
   def_builtin_const (OPTION_MASK_ISA_PCLMUL, "__builtin_ia32_pclmulqdq128",
                     V2DI_FTYPE_V2DI_V2DI_INT, IX86_BUILTIN_PCLMULQDQ128);
 
+  /* RDRND */
+  def_builtin (OPTION_MASK_ISA_RDRND, "__builtin_ia32_rdrand16_step",
+              INT_FTYPE_PUSHORT, IX86_BUILTIN_RDRAND16_STEP);
+  def_builtin (OPTION_MASK_ISA_RDRND, "__builtin_ia32_rdrand32_step",
+              INT_FTYPE_PUNSIGNED, IX86_BUILTIN_RDRAND32_STEP);
+  def_builtin (OPTION_MASK_ISA_RDRND | OPTION_MASK_ISA_64BIT,
+              "__builtin_ia32_rdrand64_step", INT_FTYPE_PULONGLONG,
+              IX86_BUILTIN_RDRAND64_STEP);
+
   /* MMX access to the vec_init patterns.  */
   def_builtin_const (OPTION_MASK_ISA_MMX, "__builtin_ia32_vec_init_v2si",
                     V2SI_FTYPE_INT_INT, IX86_BUILTIN_VEC_INIT_V2SI);
@@ -26062,6 +26373,39 @@ ix86_expand_sse_comi (const struct builtin_description *d, tree exp,
   return SUBREG_REG (target);
 }
 
+/* Subroutine of ix86_expand_args_builtin to take care of round insns.  */
+
+static rtx
+ix86_expand_sse_round (const struct builtin_description *d, tree exp,
+                      rtx target)
+{
+  rtx pat;
+  tree arg0 = CALL_EXPR_ARG (exp, 0);
+  rtx op1, op0 = expand_normal (arg0);
+  enum machine_mode tmode = insn_data[d->icode].operand[0].mode;
+  enum machine_mode mode0 = insn_data[d->icode].operand[1].mode;
+
+  if (optimize || target == 0
+      || GET_MODE (target) != tmode
+      || !insn_data[d->icode].operand[0].predicate (target, tmode))
+    target = gen_reg_rtx (tmode);
+
+  if (VECTOR_MODE_P (mode0))
+    op0 = safe_vector_operand (op0, mode0);
+
+  if ((optimize && !register_operand (op0, mode0))
+      || !insn_data[d->icode].operand[0].predicate (op0, mode0))
+    op0 = copy_to_mode_reg (mode0, op0);
+
+  op1 = GEN_INT (d->comparison);
+
+  pat = GEN_FCN (d->icode) (target, op0, op1);
+  if (! pat)
+    return 0;
+  emit_insn (pat);
+  return target;
+}
+
 /* Subroutine of ix86_expand_builtin to take care of ptest insns.  */
 
 static rtx
@@ -26331,6 +26675,11 @@ ix86_expand_args_builtin (const struct builtin_description *d,
 
   switch ((enum ix86_builtin_func_type) d->flag)
     {
+    case V2DF_FTYPE_V2DF_ROUND:
+    case V4DF_FTYPE_V4DF_ROUND:
+    case V4SF_FTYPE_V4SF_ROUND:
+    case V8SF_FTYPE_V8SF_ROUND:
+      return ix86_expand_sse_round (d, exp, target);
     case INT_FTYPE_V8SF_V8SF_PTEST:
     case INT_FTYPE_V4DI_V4DI_PTEST:
     case INT_FTYPE_V4DF_V4DF_PTEST:
@@ -26624,12 +26973,12 @@ ix86_expand_args_builtin (const struct builtin_description *d,
                error ("the last argument must be a 1-bit immediate");
                return const0_rtx;
 
-             case CODE_FOR_avx_cmpsdv2df3:
-             case CODE_FOR_avx_cmpssv4sf3:
-             case CODE_FOR_avx_cmppdv2df3:
-             case CODE_FOR_avx_cmppsv4sf3:
-             case CODE_FOR_avx_cmppdv4df3:
-             case CODE_FOR_avx_cmppsv8sf3:
+             case CODE_FOR_avx_vmcmpv2df3:
+             case CODE_FOR_avx_vmcmpv4sf3:
+             case CODE_FOR_avx_cmpv2df3:
+             case CODE_FOR_avx_cmpv4sf3:
+             case CODE_FOR_avx_cmpv4df3:
+             case CODE_FOR_avx_cmpv8sf3:
                error ("the last argument must be a 5-bit immediate");
                return const0_rtx;
 
@@ -26741,7 +27090,6 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
       break;
     case UINT64_FTYPE_VOID:
     case UNSIGNED_FTYPE_VOID:
-    case UINT16_FTYPE_VOID:
       nargs = 0;
       klass = load;
       memory = 0;
@@ -26783,18 +27131,18 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
       klass = load;
       memory = 1;
       break;
-    case V8SF_FTYPE_PCV8SF_V8SF:
-    case V4DF_FTYPE_PCV4DF_V4DF:
-    case V4SF_FTYPE_PCV4SF_V4SF:
-    case V2DF_FTYPE_PCV2DF_V2DF:
+    case V8SF_FTYPE_PCV8SF_V8SI:
+    case V4DF_FTYPE_PCV4DF_V4DI:
+    case V4SF_FTYPE_PCV4SF_V4SI:
+    case V2DF_FTYPE_PCV2DF_V2DI:
       nargs = 2;
       klass = load;
       memory = 0;
       break;
-    case VOID_FTYPE_PV8SF_V8SF_V8SF:
-    case VOID_FTYPE_PV4DF_V4DF_V4DF:
-    case VOID_FTYPE_PV4SF_V4SF_V4SF:
-    case VOID_FTYPE_PV2DF_V2DF_V2DF:
+    case VOID_FTYPE_PV8SF_V8SI_V8SF:
+    case VOID_FTYPE_PV4DF_V4DI_V4DF:
+    case VOID_FTYPE_PV4SF_V4SI_V4SF:
+    case VOID_FTYPE_PV2DF_V2DI_V2DF:
       nargs = 2;
       klass = store;
       /* Reserve memory operand for target.  */
@@ -27059,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);
@@ -27253,6 +27601,53 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
           return target;
         }
 
+    case IX86_BUILTIN_RDRAND16_STEP:
+      icode = CODE_FOR_rdrandhi_1;
+      mode0 = HImode;
+      goto rdrand_step;
+
+    case IX86_BUILTIN_RDRAND32_STEP:
+      icode = CODE_FOR_rdrandsi_1;
+      mode0 = SImode;
+      goto rdrand_step;
+
+    case IX86_BUILTIN_RDRAND64_STEP:
+      icode = CODE_FOR_rdranddi_1;
+      mode0 = DImode;
+
+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));
+
+      /* Emit SImode conditional move.  */
+      if (mode0 == HImode)
+       {
+         op2 = gen_reg_rtx (SImode);
+         emit_insn (gen_zero_extendhisi2 (op2, op0));
+       }
+      else if (mode0 == SImode)
+       op2 = op0;
+      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, target,
+                             gen_rtx_IF_THEN_ELSE (SImode, pat, op2, op1)));
+      return target;
+
     default:
       break;
     }
@@ -27383,6 +27778,118 @@ ix86_builtin_vectorized_function (tree fndecl, tree type_out,
        }
       break;
 
+    case BUILT_IN_FLOOR:
+      /* The round insn does not trap on denormals.  */
+      if (flag_trapping_math || !TARGET_ROUND)
+       break;
+
+      if (out_mode == DFmode && in_mode == DFmode)
+       {
+         if (out_n == 2 && in_n == 2)
+           return ix86_builtins[IX86_BUILTIN_FLOORPD];
+         else if (out_n == 4 && in_n == 4)
+           return ix86_builtins[IX86_BUILTIN_FLOORPD256];
+       }
+      break;
+
+    case BUILT_IN_FLOORF:
+      /* The round insn does not trap on denormals.  */
+      if (flag_trapping_math || !TARGET_ROUND)
+       break;
+
+      if (out_mode == SFmode && in_mode == SFmode)
+       {
+         if (out_n == 4 && in_n == 4)
+           return ix86_builtins[IX86_BUILTIN_FLOORPS];
+         else if (out_n == 8 && in_n == 8)
+           return ix86_builtins[IX86_BUILTIN_FLOORPS256];
+       }
+      break;
+
+    case BUILT_IN_CEIL:
+      /* The round insn does not trap on denormals.  */
+      if (flag_trapping_math || !TARGET_ROUND)
+       break;
+
+      if (out_mode == DFmode && in_mode == DFmode)
+       {
+         if (out_n == 2 && in_n == 2)
+           return ix86_builtins[IX86_BUILTIN_CEILPD];
+         else if (out_n == 4 && in_n == 4)
+           return ix86_builtins[IX86_BUILTIN_CEILPD256];
+       }
+      break;
+
+    case BUILT_IN_CEILF:
+      /* The round insn does not trap on denormals.  */
+      if (flag_trapping_math || !TARGET_ROUND)
+       break;
+
+      if (out_mode == SFmode && in_mode == SFmode)
+       {
+         if (out_n == 4 && in_n == 4)
+           return ix86_builtins[IX86_BUILTIN_CEILPS];
+         else if (out_n == 8 && in_n == 8)
+           return ix86_builtins[IX86_BUILTIN_CEILPS256];
+       }
+      break;
+
+    case BUILT_IN_TRUNC:
+      /* The round insn does not trap on denormals.  */
+      if (flag_trapping_math || !TARGET_ROUND)
+       break;
+
+      if (out_mode == DFmode && in_mode == DFmode)
+       {
+         if (out_n == 2 && in_n == 2)
+           return ix86_builtins[IX86_BUILTIN_TRUNCPD];
+         else if (out_n == 4 && in_n == 4)
+           return ix86_builtins[IX86_BUILTIN_TRUNCPD256];
+       }
+      break;
+
+    case BUILT_IN_TRUNCF:
+      /* The round insn does not trap on denormals.  */
+      if (flag_trapping_math || !TARGET_ROUND)
+       break;
+
+      if (out_mode == SFmode && in_mode == SFmode)
+       {
+         if (out_n == 4 && in_n == 4)
+           return ix86_builtins[IX86_BUILTIN_TRUNCPS];
+         else if (out_n == 8 && in_n == 8)
+           return ix86_builtins[IX86_BUILTIN_TRUNCPS256];
+       }
+      break;
+
+    case BUILT_IN_RINT:
+      /* The round insn does not trap on denormals.  */
+      if (flag_trapping_math || !TARGET_ROUND)
+       break;
+
+      if (out_mode == DFmode && in_mode == DFmode)
+       {
+         if (out_n == 2 && in_n == 2)
+           return ix86_builtins[IX86_BUILTIN_RINTPD];
+         else if (out_n == 4 && in_n == 4)
+           return ix86_builtins[IX86_BUILTIN_RINTPD256];
+       }
+      break;
+
+    case BUILT_IN_RINTF:
+      /* The round insn does not trap on denormals.  */
+      if (flag_trapping_math || !TARGET_ROUND)
+       break;
+
+      if (out_mode == SFmode && in_mode == SFmode)
+       {
+         if (out_n == 4 && in_n == 4)
+           return ix86_builtins[IX86_BUILTIN_RINTPS];
+         else if (out_n == 8 && in_n == 8)
+           return ix86_builtins[IX86_BUILTIN_RINTPS256];
+       }
+      break;
+
     case BUILT_IN_FMA:
       if (out_mode == DFmode && in_mode == DFmode)
        {
@@ -27969,22 +28476,6 @@ ix86_free_from_memory (enum machine_mode mode)
     }
 }
 
-/* Implement TARGET_IRA_COVER_CLASSES.  If -mfpmath=sse, we prefer
-   SSE_REGS to FLOAT_REGS if their costs for a pseudo are the
-   same.  */
-static const reg_class_t *
-i386_ira_cover_classes (void)
-{
-  static const reg_class_t sse_fpmath_classes[] = {
-    GENERAL_REGS, SSE_REGS, MMX_REGS, FLOAT_REGS, LIM_REG_CLASSES
-  };
-  static const reg_class_t no_sse_fpmath_classes[] = {
-    GENERAL_REGS, FLOAT_REGS, MMX_REGS, SSE_REGS, LIM_REG_CLASSES
-  };
-
- return TARGET_SSE_MATH ? sse_fpmath_classes : no_sse_fpmath_classes;
-}
-
 /* Implement TARGET_PREFERRED_RELOAD_CLASS.
 
    Put float CONST_DOUBLE in the constant pool instead of fp regs.
@@ -28028,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)
@@ -28098,7 +28589,8 @@ ix86_secondary_reload (bool in_p, rtx x, reg_class_t rclass,
 {
   /* QImode spills from non-QI registers require
      intermediate register on 32bit targets.  */
-  if (!in_p && mode == QImode && !TARGET_64BIT
+  if (!TARGET_64BIT
+      && !in_p && mode == QImode
       && (rclass == GENERAL_REGS
          || rclass == LEGACY_REGS
          || rclass == INDEX_REGS))
@@ -28118,6 +28610,45 @@ ix86_secondary_reload (bool in_p, rtx x, reg_class_t rclass,
        return Q_REGS;
     }
 
+  /* This condition handles corner case where an expression involving
+     pointers gets vectorized.  We're trying to use the address of a
+     stack slot as a vector initializer.  
+
+     (set (reg:V2DI 74 [ vect_cst_.2 ])
+          (vec_duplicate:V2DI (reg/f:DI 20 frame)))
+
+     Eventually frame gets turned into sp+offset like this:
+
+     (set (reg:V2DI 21 xmm0 [orig:74 vect_cst_.2 ] [74])
+          (vec_duplicate:V2DI (plus:DI (reg/f:DI 7 sp)
+                                      (const_int 392 [0x188]))))
+
+     That later gets turned into:
+
+     (set (reg:V2DI 21 xmm0 [orig:74 vect_cst_.2 ] [74])
+          (vec_duplicate:V2DI (plus:DI (reg/f:DI 7 sp)
+           (mem/u/c/i:DI (symbol_ref/u:DI ("*.LC0") [flags 0x2]) [0 S8 A64]))))
+
+     We'll have the following reload recorded:
+
+     Reload 0: reload_in (DI) =
+           (plus:DI (reg/f:DI 7 sp)
+            (mem/u/c/i:DI (symbol_ref/u:DI ("*.LC0") [flags 0x2]) [0 S8 A64]))
+     reload_out (V2DI) = (reg:V2DI 21 xmm0 [orig:74 vect_cst_.2 ] [74])
+     SSE_REGS, RELOAD_OTHER (opnum = 0), can't combine
+     reload_in_reg: (plus:DI (reg/f:DI 7 sp) (const_int 392 [0x188]))
+     reload_out_reg: (reg:V2DI 21 xmm0 [orig:74 vect_cst_.2 ] [74])
+     reload_reg_rtx: (reg:V2DI 22 xmm1)
+
+     Which isn't going to work since SSE instructions can't handle scalar
+     additions.  Returning GENERAL_REGS forces the addition into integer
+     register and reload can handle subsequent reloads without problems.  */
+
+  if (in_p && GET_CODE (x) == PLUS
+      && SSE_CLASS_P (rclass)
+      && SCALAR_INT_MODE_P (mode))
+    return GENERAL_REGS;
+
   return NO_REGS;
 }
 
@@ -28439,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)
@@ -28450,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))
@@ -28480,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
@@ -29111,6 +29643,58 @@ x86_order_regs_for_local_alloc (void)
      reg_alloc_order [pos++] = 0;
 }
 
+/* Handle a "callee_pop_aggregate_return" attribute; arguments as
+   in struct attribute_spec handler.  */
+static tree
+ix86_handle_callee_pop_aggregate_return (tree *node, tree name,
+                                             tree args,
+                                             int flags ATTRIBUTE_UNUSED,
+                                             bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_TYPE
+      && TREE_CODE (*node) != METHOD_TYPE
+      && TREE_CODE (*node) != FIELD_DECL
+      && TREE_CODE (*node) != TYPE_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute only applies to functions",
+              name);
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+  if (TARGET_64BIT)
+    {
+      warning (OPT_Wattributes, "%qE attribute only available for 32-bit",
+              name);
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+  if (is_attribute_p ("callee_pop_aggregate_return", name))
+    {
+      tree cst;
+
+      cst = TREE_VALUE (args);
+      if (TREE_CODE (cst) != INTEGER_CST)
+       {
+         warning (OPT_Wattributes,
+                  "%qE attribute requires an integer constant argument",
+                  name);
+         *no_add_attrs = true;
+       }
+      else if (compare_tree_int (cst, 0) != 0
+              && compare_tree_int (cst, 1) != 0)
+       {
+         warning (OPT_Wattributes,
+                  "argument to %qE attribute is neither zero, nor one",
+                  name);
+         *no_add_attrs = true;
+       }
+
+      return NULL_TREE;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "ms_abi" or "sysv" attribute; arguments as in
    struct attribute_spec.handler.  */
 static tree
@@ -29244,10 +29828,11 @@ x86_this_parameter (tree function)
   if (nregs > 0 && !stdarg_p (type))
     {
       int regno;
+      unsigned int ccvt = ix86_get_callcvt (type);
 
-      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
+      if ((ccvt & IX86_CALLCVT_FASTCALL) != 0)
        regno = aggr ? DX_REG : CX_REG;
-      else if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type)))
+      else if ((ccvt & IX86_CALLCVT_THISCALL) != 0)
         {
          regno = CX_REG;
          if (aggr)
@@ -29364,10 +29949,8 @@ x86_output_mi_thunk (FILE *file,
       else
        {
          int tmp_regno = CX_REG;
-         if (lookup_attribute ("fastcall",
-                               TYPE_ATTRIBUTES (TREE_TYPE (function)))
-             || lookup_attribute ("thiscall",
-                                  TYPE_ATTRIBUTES (TREE_TYPE (function))))
+         unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (function));
+         if ((ccvt & (IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL)) != 0)
            tmp_regno = AX_REG;
          tmp = gen_rtx_REG (SImode, tmp_regno);
        }
@@ -29857,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)
@@ -29868,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
@@ -30901,10 +31484,19 @@ ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt)
       break;
 
     case V2DImode:
-      use_vec_merge = TARGET_SSE4_1;
+      use_vec_merge = TARGET_SSE4_1 && TARGET_64BIT;
       if (use_vec_merge)
        break;
 
+      tmp = gen_reg_rtx (GET_MODE_INNER (mode));
+      ix86_expand_vector_extract (false, tmp, target, 1 - elt);
+      if (elt == 0)
+       tmp = gen_rtx_VEC_CONCAT (mode, tmp, val);
+      else
+       tmp = gen_rtx_VEC_CONCAT (mode, val, tmp);
+      emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
+      return;
+
     case V2DFmode:
       {
        rtx op0, op1;
@@ -31457,38 +32049,38 @@ void ix86_emit_i387_log1p (rtx op0, rtx op1)
 
 void ix86_emit_swdivsf (rtx res, rtx a, rtx b, enum machine_mode mode)
 {
-  rtx x0, x1, e0, e1, two;
+  rtx x0, x1, e0, e1;
 
   x0 = gen_reg_rtx (mode);
   e0 = gen_reg_rtx (mode);
   e1 = gen_reg_rtx (mode);
   x1 = gen_reg_rtx (mode);
 
-  two = CONST_DOUBLE_FROM_REAL_VALUE (dconst2, SFmode);
-
-  if (VECTOR_MODE_P (mode))
-    two = ix86_build_const_vector (mode, true, two);
-
-  two = force_reg (mode, two);
-
-  /* a / b = a * rcp(b) * (2.0 - b * rcp(b)) */
+  /* a / b = a * ((rcp(b) + rcp(b)) - (b * rcp(b) * rcp (b))) */
 
   /* x0 = rcp(b) estimate */
   emit_insn (gen_rtx_SET (VOIDmode, x0,
                          gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
                                          UNSPEC_RCP)));
-  /* e0 = x0 * a */
+  /* e0 = x0 * b */
   emit_insn (gen_rtx_SET (VOIDmode, e0,
-                         gen_rtx_MULT (mode, x0, a)));
-  /* e1 = x0 * b */
-  emit_insn (gen_rtx_SET (VOIDmode, e1,
                          gen_rtx_MULT (mode, x0, b)));
-  /* x1 = 2. - e1 */
+
+  /* e0 = x0 * e0 */
+  emit_insn (gen_rtx_SET (VOIDmode, e0,
+                         gen_rtx_MULT (mode, x0, e0)));
+
+  /* e1 = x0 + x0 */
+  emit_insn (gen_rtx_SET (VOIDmode, e1,
+                         gen_rtx_PLUS (mode, x0, x0)));
+
+  /* x1 = e1 - e0 */
   emit_insn (gen_rtx_SET (VOIDmode, x1,
-                         gen_rtx_MINUS (mode, two, e1)));
-  /* res = e0 * x1 */
+                         gen_rtx_MINUS (mode, e1, e0)));
+
+  /* res = a * x1 */
   emit_insn (gen_rtx_SET (VOIDmode, res,
-                         gen_rtx_MULT (mode, e0, x1)));
+                         gen_rtx_MULT (mode, a, x1)));
 }
 
 /* Output code to perform a Newton-Rhapson approximation of a
@@ -31568,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)
 {
@@ -31584,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.  */
 
@@ -31758,6 +32361,7 @@ static rtx
 ix86_expand_sse_compare_mask (enum rtx_code code, rtx op0, rtx op1,
                              bool swap_operands)
 {
+  rtx (*insn)(rtx, rtx, rtx, rtx);
   enum machine_mode mode = GET_MODE (op0);
   rtx mask = gen_reg_rtx (mode);
 
@@ -31768,13 +32372,10 @@ ix86_expand_sse_compare_mask (enum rtx_code code, rtx op0, rtx op1,
       op1 = tmp;
     }
 
-  if (mode == DFmode)
-    emit_insn (gen_sse2_maskcmpdf3 (mask, op0, op1,
-                                   gen_rtx_fmt_ee (code, mode, op0, op1)));
-  else
-    emit_insn (gen_sse_maskcmpsf3 (mask, op0, op1,
-                                  gen_rtx_fmt_ee (code, mode, op0, op1)));
+  insn = mode == DFmode ? gen_setcc_df_sse : gen_setcc_sf_sse;
 
+  emit_insn (insn (mask, op0, op1,
+                  gen_rtx_fmt_ee (code, mode, op0, op1)));
   return mask;
 }
 
@@ -32245,43 +32846,56 @@ ix86_expand_round (rtx operand0, rtx operand1)
 /* Table of valid machine attributes.  */
 static const struct attribute_spec ix86_attribute_table[] =
 {
-  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+       affects_type_identity } */
   /* Stdcall attribute says callee is responsible for popping arguments
      if they are not variable.  */
-  { "stdcall",   0, 0, false, true,  true,  ix86_handle_cconv_attribute },
+  { "stdcall",   0, 0, false, true,  true,  ix86_handle_cconv_attribute,
+    true },
   /* Fastcall attribute says callee is responsible for popping arguments
      if they are not variable.  */
-  { "fastcall",  0, 0, false, true,  true,  ix86_handle_cconv_attribute },
+  { "fastcall",  0, 0, false, true,  true,  ix86_handle_cconv_attribute,
+    true },
   /* Thiscall attribute says callee is responsible for popping arguments
      if they are not variable.  */
-  { "thiscall",  0, 0, false, true,  true,  ix86_handle_cconv_attribute },
+  { "thiscall",  0, 0, false, true,  true,  ix86_handle_cconv_attribute,
+    true },
   /* Cdecl attribute says the callee is a normal C declaration */
-  { "cdecl",     0, 0, false, true,  true,  ix86_handle_cconv_attribute },
+  { "cdecl",     0, 0, false, true,  true,  ix86_handle_cconv_attribute,
+    true },
   /* Regparm attribute specifies how many integer arguments are to be
      passed in registers.  */
-  { "regparm",   1, 1, false, true,  true,  ix86_handle_cconv_attribute },
+  { "regparm",   1, 1, false, true,  true,  ix86_handle_cconv_attribute,
+    true },
   /* Sseregparm attribute says we are using x86_64 calling conventions
      for FP arguments.  */
-  { "sseregparm", 0, 0, false, true, true, ix86_handle_cconv_attribute },
+  { "sseregparm", 0, 0, false, true, true, ix86_handle_cconv_attribute,
+    true },
   /* force_align_arg_pointer says this function realigns the stack at entry.  */
   { (const char *)&ix86_force_align_arg_pointer_string, 0, 0,
-    false, true,  true, ix86_handle_cconv_attribute },
+    false, true,  true, ix86_handle_cconv_attribute, false },
 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
-  { "dllimport", 0, 0, false, false, false, handle_dll_attribute },
-  { "dllexport", 0, 0, false, false, false, handle_dll_attribute },
-  { "shared",    0, 0, true,  false, false, ix86_handle_shared_attribute },
+  { "dllimport", 0, 0, false, false, false, handle_dll_attribute, false },
+  { "dllexport", 0, 0, false, false, false, handle_dll_attribute, false },
+  { "shared",    0, 0, true,  false, false, ix86_handle_shared_attribute,
+    false },
 #endif
-  { "ms_struct", 0, 0, false, false,  false, ix86_handle_struct_attribute },
-  { "gcc_struct", 0, 0, false, false,  false, ix86_handle_struct_attribute },
+  { "ms_struct", 0, 0, false, false,  false, ix86_handle_struct_attribute,
+    false },
+  { "gcc_struct", 0, 0, false, false,  false, ix86_handle_struct_attribute,
+    false },
 #ifdef SUBTARGET_ATTRIBUTE_TABLE
   SUBTARGET_ATTRIBUTE_TABLE,
 #endif
   /* ms_abi and sysv_abi calling convention function attributes.  */
-  { "ms_abi", 0, 0, false, true, true, ix86_handle_abi_attribute },
-  { "sysv_abi", 0, 0, false, true, true, ix86_handle_abi_attribute },
-  { "ms_hook_prologue", 0, 0, true, false, false, ix86_handle_fndecl_attribute },
+  { "ms_abi", 0, 0, false, true, true, ix86_handle_abi_attribute, true },
+  { "sysv_abi", 0, 0, false, true, true, ix86_handle_abi_attribute, true },
+  { "ms_hook_prologue", 0, 0, true, false, false, ix86_handle_fndecl_attribute,
+    false },
+  { "callee_pop_aggregate_return", 1, 1, false, true, true,
+    ix86_handle_callee_pop_aggregate_return, true },
   /* End element.  */
-  { NULL,        0, 0, false, false, false, NULL }
+  { NULL,        0, 0, false, false, false, NULL, false }
 };
 
 /* Implement targetm.vectorize.builtin_vectorization_cost.  */
@@ -33512,6 +34126,88 @@ ix86_expand_vec_extract_even_odd (rtx targ, rtx op0, rtx op1, unsigned odd)
   /* ... or we use the special-case patterns.  */
   expand_vec_perm_even_odd_1 (&d, odd);
 }
+
+/* Expand an insert into a vector register through pinsr insn.
+   Return true if successful.  */
+
+bool
+ix86_expand_pinsr (rtx *operands)
+{
+  rtx dst = operands[0];
+  rtx src = operands[3];
+
+  unsigned int size = INTVAL (operands[1]);
+  unsigned int pos = INTVAL (operands[2]);
+
+  if (GET_CODE (dst) == SUBREG)
+    {
+      pos += SUBREG_BYTE (dst) * BITS_PER_UNIT;
+      dst = SUBREG_REG (dst);
+    }
+
+  if (GET_CODE (src) == SUBREG)
+    src = SUBREG_REG (src);
+
+  switch (GET_MODE (dst))
+    {
+    case V16QImode:
+    case V8HImode:
+    case V4SImode:
+    case V2DImode:
+      {
+       enum machine_mode srcmode, dstmode;
+       rtx (*pinsr)(rtx, rtx, rtx, rtx);
+
+       srcmode = mode_for_size (size, MODE_INT, 0);
+
+       switch (srcmode)
+         {
+         case QImode:
+           if (!TARGET_SSE4_1)
+             return false;
+           dstmode = V16QImode;
+           pinsr = gen_sse4_1_pinsrb;
+           break;
+
+         case HImode:
+           if (!TARGET_SSE2)
+             return false;
+           dstmode = V8HImode;
+           pinsr = gen_sse2_pinsrw;
+           break;
+
+         case SImode:
+           if (!TARGET_SSE4_1)
+             return false;
+           dstmode = V4SImode;
+           pinsr = gen_sse4_1_pinsrd;
+           break;
+
+         case DImode:
+           gcc_assert (TARGET_64BIT);
+           if (!TARGET_SSE4_1)
+             return false;
+           dstmode = V2DImode;
+           pinsr = gen_sse4_1_pinsrq;
+           break;
+
+         default:
+           return false;
+         }
+
+       dst = gen_lowpart (dstmode, dst);
+       src = gen_lowpart (srcmode, src);
+
+       pos /= size;
+
+       emit_insn (pinsr (dst, dst, src, GEN_INT (1 << pos)));
+       return true;
+      }
+
+    default:
+      return false;
+    }
+}
 \f
 /* This function returns the calling abi specific va_list type node.
    It returns  the FNDECL specific va_list type.  */
@@ -33545,7 +34241,7 @@ ix86_canonical_va_list_type (tree type)
   else if (POINTER_TYPE_P (type) && TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
     type = TREE_TYPE (type);
 
-  if (TARGET_64BIT)
+  if (TARGET_64BIT && va_list_type_node != NULL_TREE)
     {
       wtype = va_list_type_node;
          gcc_assert (wtype != NULL_TREE);
@@ -34445,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 ? V8SFmode : V4SFmode;
-    case DFmode:
-      return TARGET_AVX ? 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;
 
-  return word_mode;
+    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 */
+
+    default:
+      return word_mode;
+    }
 }
 
 /* If AVX is enabled then try vectorizing with both 256bit and 128bit
@@ -34479,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.  */
@@ -34779,8 +35481,8 @@ ix86_autovectorize_vector_sizes (void)
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P ix86_legitimate_address_p
 
-#undef TARGET_IRA_COVER_CLASSES
-#define TARGET_IRA_COVER_CLASSES i386_ira_cover_classes
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P ix86_legitimate_constant_p
 
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED ix86_frame_pointer_required
@@ -34797,6 +35499,11 @@ ix86_autovectorize_vector_sizes (void)
 #undef TARGET_CONDITIONAL_REGISTER_USAGE
 #define TARGET_CONDITIONAL_REGISTER_USAGE ix86_conditional_register_usage
 
+#if TARGET_MACHO
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS darwin_rename_builtins
+#endif
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 #include "gt-i386.h"