OSDN Git Service

PR c/9506
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.c
index bbd5553..d70054b 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 Free Software Foundation, Inc.
+   2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -21,6 +21,8 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "tree.h"
 #include "tm_p.h"
@@ -48,6 +50,14 @@ Boston, MA 02111-1307, USA.  */
 #define CHECK_STACK_LIMIT (-1)
 #endif
 
+/* Return index of given mode in mult and division cost tables.  */
+#define MODE_INDEX(mode)                                       \
+  ((mode) == QImode ? 0                                                \
+   : (mode) == HImode ? 1                                      \
+   : (mode) == SImode ? 2                                      \
+   : (mode) == DImode ? 3                                      \
+   : 4)
+
 /* Processor costs (relative to an add) */
 static const
 struct processor_costs size_cost = {   /* costs for tunning for size */
@@ -55,9 +65,9 @@ struct processor_costs size_cost = {  /* costs for tunning for size */
   3,                                   /* cost of a lea instruction */
   2,                                   /* variable shift costs */
   3,                                   /* constant shift costs */
-  3,                                   /* cost of starting a multiply */
+  {3, 3, 3, 3, 5},                     /* cost of starting a multiply */
   0,                                   /* cost of multiply per each bit set */
-  3,                                   /* cost of a divide/mod */
+  {3, 3, 3, 3, 5},                     /* cost of a divide/mod */
   3,                                   /* cost of movsx */
   3,                                   /* cost of movzx */
   0,                                   /* "large" insn */
@@ -84,7 +94,15 @@ struct processor_costs size_cost = { /* costs for tunning for size */
   3,                                   /* MMX or SSE register to integer */
   0,                                   /* size of prefetch block */
   0,                                   /* number of parallel prefetches */
+  1,                                   /* Branch cost */
+  2,                                   /* cost of FADD and FSUB insns.  */
+  2,                                   /* cost of FMUL instruction.  */
+  2,                                   /* cost of FDIV instruction.  */
+  2,                                   /* cost of FABS instruction.  */
+  2,                                   /* cost of FCHS instruction.  */
+  2,                                   /* cost of FSQRT instruction.  */
 };
+
 /* Processor costs (relative to an add) */
 static const
 struct processor_costs i386_cost = {   /* 386 specific costs */
@@ -92,9 +110,9 @@ struct processor_costs i386_cost = { /* 386 specific costs */
   1,                                   /* cost of a lea instruction */
   3,                                   /* variable shift costs */
   2,                                   /* constant shift costs */
-  6,                                   /* cost of starting a multiply */
+  {6, 6, 6, 6, 6},                     /* cost of starting a multiply */
   1,                                   /* cost of multiply per each bit set */
-  23,                                  /* cost of a divide/mod */
+  {23, 23, 23, 23, 23},                        /* cost of a divide/mod */
   3,                                   /* cost of movsx */
   2,                                   /* cost of movzx */
   15,                                  /* "large" insn */
@@ -121,6 +139,13 @@ struct processor_costs i386_cost = {       /* 386 specific costs */
   3,                                   /* MMX or SSE register to integer */
   0,                                   /* size of prefetch block */
   0,                                   /* number of parallel prefetches */
+  1,                                   /* Branch cost */
+  23,                                  /* cost of FADD and FSUB insns.  */
+  27,                                  /* cost of FMUL instruction.  */
+  88,                                  /* cost of FDIV instruction.  */
+  22,                                  /* cost of FABS instruction.  */
+  24,                                  /* cost of FCHS instruction.  */
+  122,                                 /* cost of FSQRT instruction.  */
 };
 
 static const
@@ -129,9 +154,9 @@ struct processor_costs i486_cost = {        /* 486 specific costs */
   1,                                   /* cost of a lea instruction */
   3,                                   /* variable shift costs */
   2,                                   /* constant shift costs */
-  12,                                  /* cost of starting a multiply */
+  {12, 12, 12, 12, 12},                        /* cost of starting a multiply */
   1,                                   /* cost of multiply per each bit set */
-  40,                                  /* cost of a divide/mod */
+  {40, 40, 40, 40, 40},                        /* cost of a divide/mod */
   3,                                   /* cost of movsx */
   2,                                   /* cost of movzx */
   15,                                  /* "large" insn */
@@ -158,6 +183,13 @@ struct processor_costs i486_cost = {       /* 486 specific costs */
   3,                                   /* MMX or SSE register to integer */
   0,                                   /* size of prefetch block */
   0,                                   /* number of parallel prefetches */
+  1,                                   /* Branch cost */
+  8,                                   /* cost of FADD and FSUB insns.  */
+  16,                                  /* cost of FMUL instruction.  */
+  73,                                  /* cost of FDIV instruction.  */
+  3,                                   /* cost of FABS instruction.  */
+  3,                                   /* cost of FCHS instruction.  */
+  83,                                  /* cost of FSQRT instruction.  */
 };
 
 static const
@@ -166,9 +198,9 @@ struct processor_costs pentium_cost = {
   1,                                   /* cost of a lea instruction */
   4,                                   /* variable shift costs */
   1,                                   /* constant shift costs */
-  11,                                  /* cost of starting a multiply */
+  {11, 11, 11, 11, 11},                        /* cost of starting a multiply */
   0,                                   /* cost of multiply per each bit set */
-  25,                                  /* cost of a divide/mod */
+  {25, 25, 25, 25, 25},                        /* cost of a divide/mod */
   3,                                   /* cost of movsx */
   2,                                   /* cost of movzx */
   8,                                   /* "large" insn */
@@ -195,6 +227,13 @@ struct processor_costs pentium_cost = {
   3,                                   /* MMX or SSE register to integer */
   0,                                   /* size of prefetch block */
   0,                                   /* number of parallel prefetches */
+  2,                                   /* Branch cost */
+  3,                                   /* cost of FADD and FSUB insns.  */
+  3,                                   /* cost of FMUL instruction.  */
+  39,                                  /* cost of FDIV instruction.  */
+  1,                                   /* cost of FABS instruction.  */
+  1,                                   /* cost of FCHS instruction.  */
+  70,                                  /* cost of FSQRT instruction.  */
 };
 
 static const
@@ -203,9 +242,9 @@ struct processor_costs pentiumpro_cost = {
   1,                                   /* cost of a lea instruction */
   1,                                   /* variable shift costs */
   1,                                   /* constant shift costs */
-  4,                                   /* cost of starting a multiply */
+  {4, 4, 4, 4, 4},                     /* cost of starting a multiply */
   0,                                   /* cost of multiply per each bit set */
-  17,                                  /* cost of a divide/mod */
+  {17, 17, 17, 17, 17},                        /* cost of a divide/mod */
   1,                                   /* cost of movsx */
   1,                                   /* cost of movzx */
   8,                                   /* "large" insn */
@@ -232,6 +271,13 @@ struct processor_costs pentiumpro_cost = {
   3,                                   /* MMX or SSE register to integer */
   32,                                  /* size of prefetch block */
   6,                                   /* number of parallel prefetches */
+  2,                                   /* Branch cost */
+  3,                                   /* cost of FADD and FSUB insns.  */
+  5,                                   /* cost of FMUL instruction.  */
+  56,                                  /* cost of FDIV instruction.  */
+  2,                                   /* cost of FABS instruction.  */
+  2,                                   /* cost of FCHS instruction.  */
+  56,                                  /* cost of FSQRT instruction.  */
 };
 
 static const
@@ -240,9 +286,9 @@ struct processor_costs k6_cost = {
   2,                                   /* cost of a lea instruction */
   1,                                   /* variable shift costs */
   1,                                   /* constant shift costs */
-  3,                                   /* cost of starting a multiply */
+  {3, 3, 3, 3, 3},                     /* cost of starting a multiply */
   0,                                   /* cost of multiply per each bit set */
-  18,                                  /* cost of a divide/mod */
+  {18, 18, 18, 18, 18},                        /* cost of a divide/mod */
   2,                                   /* cost of movsx */
   2,                                   /* cost of movzx */
   8,                                   /* "large" insn */
@@ -269,6 +315,13 @@ struct processor_costs k6_cost = {
   6,                                   /* MMX or SSE register to integer */
   32,                                  /* size of prefetch block */
   1,                                   /* number of parallel prefetches */
+  1,                                   /* Branch cost */
+  2,                                   /* cost of FADD and FSUB insns.  */
+  2,                                   /* cost of FMUL instruction.  */
+  56,                                  /* cost of FDIV instruction.  */
+  2,                                   /* cost of FABS instruction.  */
+  2,                                   /* cost of FCHS instruction.  */
+  56,                                  /* cost of FSQRT instruction.  */
 };
 
 static const
@@ -277,46 +330,97 @@ struct processor_costs athlon_cost = {
   2,                                   /* cost of a lea instruction */
   1,                                   /* variable shift costs */
   1,                                   /* constant shift costs */
-  5,                                   /* cost of starting a multiply */
+  {5, 5, 5, 5, 5},                     /* cost of starting a multiply */
   0,                                   /* cost of multiply per each bit set */
-  42,                                  /* cost of a divide/mod */
+  {18, 26, 42, 74, 74},                        /* cost of a divide/mod */
   1,                                   /* cost of movsx */
   1,                                   /* cost of movzx */
   8,                                   /* "large" insn */
   9,                                   /* MOVE_RATIO */
   4,                                   /* cost for loading QImode using movzbl */
-  {4, 5, 4},                           /* cost of loading integer registers
+  {3, 4, 3},                           /* cost of loading integer registers
                                           in QImode, HImode and SImode.
                                           Relative to reg-reg move (2).  */
-  {2, 3, 2},                           /* cost of storing integer registers */
+  {3, 4, 3},                           /* cost of storing integer registers */
   4,                                   /* cost of reg,reg fld/fst */
-  {6, 6, 20},                          /* cost of loading fp registers
+  {4, 4, 12},                          /* cost of loading fp registers
                                           in SFmode, DFmode and XFmode */
-  {4, 4, 16},                          /* cost of loading integer registers */
+  {6, 6, 8},                           /* cost of loading integer registers */
   2,                                   /* cost of moving MMX register */
-  {2, 2},                              /* cost of loading MMX registers
+  {4, 4},                              /* cost of loading MMX registers
                                           in SImode and DImode */
-  {2, 2},                              /* cost of storing MMX registers
+  {4, 4},                              /* cost of storing MMX registers
                                           in SImode and DImode */
   2,                                   /* cost of moving SSE register */
-  {2, 2, 8},                           /* cost of loading SSE registers
+  {4, 4, 6},                           /* cost of loading SSE registers
                                           in SImode, DImode and TImode */
-  {2, 2, 8},                           /* cost of storing SSE registers
+  {4, 4, 5},                           /* cost of storing SSE registers
                                           in SImode, DImode and TImode */
-  6,                                   /* MMX or SSE register to integer */
+  5,                                   /* MMX or SSE register to integer */
+  64,                                  /* size of prefetch block */
+  6,                                   /* number of parallel prefetches */
+  2,                                   /* Branch cost */
+  4,                                   /* cost of FADD and FSUB insns.  */
+  4,                                   /* cost of FMUL instruction.  */
+  24,                                  /* cost of FDIV instruction.  */
+  2,                                   /* cost of FABS instruction.  */
+  2,                                   /* cost of FCHS instruction.  */
+  35,                                  /* cost of FSQRT instruction.  */
+};
+
+static const
+struct processor_costs k8_cost = {
+  1,                                   /* cost of an add instruction */
+  2,                                   /* cost of a lea instruction */
+  1,                                   /* variable shift costs */
+  1,                                   /* constant shift costs */
+  {3, 4, 3, 4, 5},                     /* cost of starting a multiply */
+  0,                                   /* cost of multiply per each bit set */
+  {18, 26, 42, 74, 74},                        /* cost of a divide/mod */
+  1,                                   /* cost of movsx */
+  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 loading integer registers */
+  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, 3, 6},                           /* cost of loading SSE registers
+                                          in SImode, DImode and TImode */
+  {4, 4, 5},                           /* cost of storing SSE registers
+                                          in SImode, DImode and TImode */
+  5,                                   /* MMX or SSE register to integer */
   64,                                  /* size of prefetch block */
   6,                                   /* number of parallel prefetches */
+  2,                                   /* Branch cost */
+  4,                                   /* cost of FADD and FSUB insns.  */
+  4,                                   /* cost of FMUL instruction.  */
+  19,                                  /* cost of FDIV instruction.  */
+  2,                                   /* cost of FABS instruction.  */
+  2,                                   /* cost of FCHS instruction.  */
+  35,                                  /* cost of FSQRT instruction.  */
 };
 
 static const
 struct processor_costs pentium4_cost = {
   1,                                   /* cost of an add instruction */
   1,                                   /* cost of a lea instruction */
-  8,                                   /* variable shift costs */
-  8,                                   /* constant shift costs */
-  30,                                  /* cost of starting a multiply */
+  4,                                   /* variable shift costs */
+  4,                                   /* constant shift costs */
+  {15, 15, 15, 15, 15},                        /* cost of starting a multiply */
   0,                                   /* cost of multiply per each bit set */
-  112,                                 /* cost of a divide/mod */
+  {56, 56, 56, 56, 56},                        /* cost of a divide/mod */
   1,                                   /* cost of movsx */
   1,                                   /* cost of movzx */
   16,                                  /* "large" insn */
@@ -343,6 +447,13 @@ struct processor_costs pentium4_cost = {
   10,                                  /* MMX or SSE register to integer */
   64,                                  /* size of prefetch block */
   6,                                   /* number of parallel prefetches */
+  2,                                   /* Branch cost */
+  5,                                   /* cost of FADD and FSUB insns.  */
+  7,                                   /* cost of FMUL instruction.  */
+  43,                                  /* cost of FDIV instruction.  */
+  2,                                   /* cost of FABS instruction.  */
+  2,                                   /* cost of FCHS instruction.  */
+  43,                                  /* cost of FSQRT instruction.  */
 };
 
 const struct processor_costs *ix86_cost = &pentium_cost;
@@ -355,52 +466,66 @@ const struct processor_costs *ix86_cost = &pentium_cost;
 #define m_K6  (1<<PROCESSOR_K6)
 #define m_ATHLON  (1<<PROCESSOR_ATHLON)
 #define m_PENT4  (1<<PROCESSOR_PENTIUM4)
+#define m_K8  (1<<PROCESSOR_K8)
+#define m_ATHLON_K8  (m_K8 | m_ATHLON)
 
-const int x86_use_leave = m_386 | m_K6 | m_ATHLON;
-const int x86_push_memory = m_386 | m_K6 | m_ATHLON | m_PENT4;
+const int x86_use_leave = m_386 | m_K6 | m_ATHLON_K8;
+const int x86_push_memory = m_386 | m_K6 | m_ATHLON_K8 | m_PENT4;
 const int x86_zero_extend_with_and = m_486 | m_PENT;
-const int x86_movx = m_ATHLON | m_PPRO | m_PENT4 /* m_386 | m_K6 */;
+const int x86_movx = m_ATHLON_K8 | m_PPRO | m_PENT4 /* m_386 | m_K6 */;
 const int x86_double_with_add = ~m_386;
 const int x86_use_bit_test = m_386;
-const int x86_unroll_strlen = m_486 | m_PENT | m_PPRO | m_ATHLON | m_K6;
-const int x86_cmove = m_PPRO | m_ATHLON | m_PENT4;
-const int x86_3dnow_a = m_ATHLON;
-const int x86_deep_branch = m_PPRO | m_K6 | m_ATHLON | m_PENT4;
+const int x86_unroll_strlen = m_486 | m_PENT | m_PPRO | m_ATHLON_K8 | m_K6;
+const int x86_cmove = m_PPRO | m_ATHLON_K8 | m_PENT4;
+const int x86_3dnow_a = m_ATHLON_K8;
+const int x86_deep_branch = m_PPRO | m_K6 | m_ATHLON_K8 | m_PENT4;
 const int x86_branch_hints = m_PENT4;
 const int x86_use_sahf = m_PPRO | m_K6 | m_PENT4;
 const int x86_partial_reg_stall = m_PPRO;
 const int x86_use_loop = m_K6;
-const int x86_use_fiop = ~(m_PPRO | m_ATHLON | m_PENT);
+const int x86_use_fiop = ~(m_PPRO | m_ATHLON_K8 | m_PENT);
 const int x86_use_mov0 = m_K6;
 const int x86_use_cltd = ~(m_PENT | m_K6);
 const int x86_read_modify_write = ~m_PENT;
 const int x86_read_modify = ~(m_PENT | m_PPRO);
 const int x86_split_long_moves = m_PPRO;
-const int x86_promote_QImode = m_K6 | m_PENT | m_386 | m_486 | m_ATHLON;
+const int x86_promote_QImode = m_K6 | m_PENT | m_386 | m_486 | m_ATHLON_K8;
 const int x86_fast_prefix = ~(m_PENT | m_486 | m_386);
 const int x86_single_stringop = m_386 | m_PENT4;
 const int x86_qimode_math = ~(0);
 const int x86_promote_qi_regs = 0;
 const int x86_himode_math = ~(m_PPRO);
 const int x86_promote_hi_regs = m_PPRO;
-const int x86_sub_esp_4 = m_ATHLON | m_PPRO | m_PENT4;
-const int x86_sub_esp_8 = m_ATHLON | m_PPRO | m_386 | m_486 | m_PENT4;
-const int x86_add_esp_4 = m_ATHLON | m_K6 | m_PENT4;
-const int x86_add_esp_8 = m_ATHLON | m_PPRO | m_K6 | m_386 | m_486 | m_PENT4;
-const int x86_integer_DFmode_moves = ~(m_ATHLON | m_PENT4 | m_PPRO);
-const int x86_partial_reg_dependency = m_ATHLON | m_PENT4;
-const int x86_memory_mismatch_stall = m_ATHLON | m_PENT4;
-const int x86_accumulate_outgoing_args = m_ATHLON | m_PENT4 | m_PPRO;
-const int x86_prologue_using_move = m_ATHLON | m_PENT4 | m_PPRO;
-const int x86_epilogue_using_move = m_ATHLON | m_PENT4 | m_PPRO;
+const int x86_sub_esp_4 = m_ATHLON_K8 | m_PPRO | m_PENT4;
+const int x86_sub_esp_8 = m_ATHLON_K8 | m_PPRO | m_386 | m_486 | m_PENT4;
+const int x86_add_esp_4 = m_ATHLON_K8 | m_K6 | m_PENT4;
+const int x86_add_esp_8 = m_ATHLON_K8 | m_PPRO | m_K6 | m_386 | m_486 | m_PENT4;
+const int x86_integer_DFmode_moves = ~(m_ATHLON_K8 | m_PENT4 | m_PPRO);
+const int x86_partial_reg_dependency = m_ATHLON_K8 | m_PENT4;
+const int x86_memory_mismatch_stall = m_ATHLON_K8 | m_PENT4;
+const int x86_accumulate_outgoing_args = m_ATHLON_K8 | m_PENT4 | m_PPRO;
+const int x86_prologue_using_move = m_ATHLON_K8 | m_PENT4 | m_PPRO;
+const int x86_epilogue_using_move = m_ATHLON_K8 | m_PENT4 | m_PPRO;
 const int x86_decompose_lea = m_PENT4;
 const int x86_shift1 = ~m_486;
-const int x86_arch_always_fancy_math_387 = m_PENT | m_PPRO | m_ATHLON | m_PENT4;
-
-/* In case the avreage insn count for single function invocation is
+const int x86_arch_always_fancy_math_387 = m_PENT | m_PPRO | m_ATHLON_K8 | m_PENT4;
+const int x86_sse_partial_reg_dependency = m_PENT4 | m_PPRO;
+/* Set for machines where the type and dependencies are resolved on SSE register
+   parts instead of whole registers, so we may maintain just lower part of
+   scalar values in proper format leaving the upper part undefined.  */
+const int x86_sse_partial_regs = m_ATHLON_K8;
+/* Athlon optimizes partial-register FPS special case, thus avoiding the
+   need for extra instructions beforehand  */
+const int x86_sse_partial_regs_for_cvtsd2ss = 0;
+const int x86_sse_typeless_stores = m_ATHLON_K8;
+const int x86_sse_load0_by_pxor = m_PPRO | m_PENT4;
+const int x86_use_ffreep = m_ATHLON_K8;
+const int x86_rep_movl_optimal = m_386 | m_PENT | m_PPRO | m_K6;
+
+/* In case the average insn count for single function invocation is
    lower than this constant, emit fast (but longer) prologue and
    epilogue code.  */
-#define FAST_PROLOGUE_INSN_COUNT 30
+#define FAST_PROLOGUE_INSN_COUNT 20
 
 /* Set by prologue expander and used by epilogue expander to determine
    the style used.  */
@@ -534,8 +659,8 @@ int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER] =
   -1, 9, -1, -1, -1,                   /* arg, flags, fpsr, dir, frame */
   21, 22, 23, 24, 25, 26, 27, 28,      /* SSE registers */
   29, 30, 31, 32, 33, 34, 35, 36,      /* MMX registers */
-  -1, -1, -1, -1, -1, -1, -1, -1,      /* extemded integer registers */
-  -1, -1, -1, -1, -1, -1, -1, -1,      /* extemded SSE registers */
+  -1, -1, -1, -1, -1, -1, -1, -1,      /* extended integer registers */
+  -1, -1, -1, -1, -1, -1, -1, -1,      /* extended SSE registers */
 };
 
 /* Test and compare insns in i386.md store the information needed to
@@ -701,6 +826,12 @@ static int ix86_variable_issue PARAMS ((FILE *, int, rtx, int));
 static int ia32_use_dfa_pipeline_interface PARAMS ((void));
 static int ia32_multipass_dfa_lookahead PARAMS ((void));
 static void ix86_init_mmx_sse_builtins PARAMS ((void));
+static rtx x86_this_parameter PARAMS ((tree));
+static void x86_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+                                        HOST_WIDE_INT, tree));
+static bool x86_can_output_mi_thunk PARAMS ((tree, HOST_WIDE_INT,
+                                            HOST_WIDE_INT, tree));
+bool ix86_expand_carry_flag_compare PARAMS ((enum rtx_code, rtx, rtx, rtx*));
 
 struct ix86_address
 {
@@ -709,6 +840,8 @@ struct ix86_address
 };
 
 static int ix86_decompose_address PARAMS ((rtx, struct ix86_address *));
+static int ix86_address_cost PARAMS ((rtx));
+static bool ix86_cannot_force_const_mem PARAMS ((rtx));
 
 static void ix86_encode_section_info PARAMS ((tree, int)) ATTRIBUTE_UNUSED;
 static const char *ix86_strip_name_encoding PARAMS ((const char *))
@@ -722,8 +855,6 @@ static rtx ix86_expand_sse_compare PARAMS ((const struct builtin_description *,
 static rtx ix86_expand_unop1_builtin PARAMS ((enum insn_code, tree, rtx));
 static rtx ix86_expand_unop_builtin PARAMS ((enum insn_code, tree, rtx, int));
 static rtx ix86_expand_binop_builtin PARAMS ((enum insn_code, tree, rtx));
-static rtx ix86_expand_timode_binop_builtin PARAMS ((enum insn_code,
-                                                    tree, rtx));
 static rtx ix86_expand_store_builtin PARAMS ((enum insn_code, tree));
 static rtx safe_vector_operand PARAMS ((rtx, enum machine_mode));
 static enum rtx_code ix86_fp_compare_code_to_integer PARAMS ((enum rtx_code));
@@ -741,9 +872,16 @@ static unsigned int ix86_select_alt_pic_regnum PARAMS ((void));
 static int ix86_save_reg PARAMS ((unsigned int, int));
 static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
 static int ix86_comp_type_attributes PARAMS ((tree, tree));
+static int ix86_fntype_regparm PARAMS ((tree));
 const struct attribute_spec ix86_attribute_table[];
+static bool ix86_function_ok_for_sibcall PARAMS ((tree, tree));
 static tree ix86_handle_cdecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
 static tree ix86_handle_regparm_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static int ix86_value_regno PARAMS ((enum machine_mode));
+static bool ix86_ms_bitfield_layout_p PARAMS ((tree));
+static tree ix86_handle_struct_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static int extended_reg_mentioned_1 PARAMS ((rtx *, void *));
+static bool ix86_rtx_costs PARAMS ((rtx, int, int, int *));
 
 #if defined (DO_GLOBAL_CTORS_BODY) && defined (HAS_INIT_SECTION)
 static void ix86_svr3_asm_out_constructor PARAMS ((rtx, int));
@@ -752,9 +890,9 @@ static void ix86_svr3_asm_out_constructor PARAMS ((rtx, int));
 /* Register class used for passing given 64bit part of the argument.
    These represent classes as documented by the PS ABI, with the exception
    of SSESF, SSEDF classes, that are basically SSE class, just gcc will
-   use SF or DFmode move instead of DImode to avoid reformating penalties.
+   use SF or DFmode move instead of DImode to avoid reformatting penalties.
 
-   Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
+   Similarly we play games with INTEGERSI_CLASS to use cheaper SImode moves
    whenever possible (upper half does contain padding).
  */
 enum x86_64_reg_class
@@ -842,10 +980,28 @@ static enum x86_64_reg_class merge_classes PARAMS ((enum x86_64_reg_class,
 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
   ia32_multipass_dfa_lookahead
 
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL ix86_function_ok_for_sibcall
+
 #ifdef HAVE_AS_TLS
 #undef TARGET_HAVE_TLS
 #define TARGET_HAVE_TLS true
 #endif
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM ix86_cannot_force_const_mem
+
+#undef TARGET_MS_BITFIELD_LAYOUT_P
+#define TARGET_MS_BITFIELD_LAYOUT_P ix86_ms_bitfield_layout_p
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK x86_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK x86_can_output_mi_thunk
+
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS ix86_rtx_costs
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST ix86_address_cost
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
@@ -875,17 +1031,17 @@ override_options ()
       const int align_jump;
       const int align_jump_max_skip;
       const int align_func;
-      const int branch_cost;
     }
   const processor_target_table[PROCESSOR_max] =
     {
-      {&i386_cost, 0, 0, 4, 3, 4, 3, 4, 1},
-      {&i486_cost, 0, 0, 16, 15, 16, 15, 16, 1},
-      {&pentium_cost, 0, 0, 16, 7, 16, 7, 16, 1},
-      {&pentiumpro_cost, 0, 0, 16, 15, 16, 7, 16, 1},
-      {&k6_cost, 0, 0, 32, 7, 32, 7, 32, 1},
-      {&athlon_cost, 0, 0, 16, 7, 64, 7, 16, 1},
-      {&pentium4_cost, 0, 0, 0, 0, 0, 0, 0, 1}
+      {&i386_cost, 0, 0, 4, 3, 4, 3, 4},
+      {&i486_cost, 0, 0, 16, 15, 16, 15, 16},
+      {&pentium_cost, 0, 0, 16, 7, 16, 7, 16},
+      {&pentiumpro_cost, 0, 0, 16, 15, 16, 7, 16},
+      {&k6_cost, 0, 0, 32, 7, 32, 7, 32},
+      {&athlon_cost, 0, 0, 16, 7, 16, 7, 16},
+      {&pentium4_cost, 0, 0, 0, 0, 0, 0, 0},
+      {&k8_cost, 0, 0, 16, 7, 16, 7, 16}
     };
 
   static const char * const cpu_names[] = TARGET_CPU_DEFAULT_NAMES;
@@ -900,7 +1056,8 @@ override_options ()
          PTA_MMX = 4,
          PTA_PREFETCH_SSE = 8,
          PTA_3DNOW = 16,
-         PTA_3DNOW_A = 64
+         PTA_3DNOW_A = 64,
+         PTA_64BIT = 128
        } flags;
     }
   const processor_alias_table[] =
@@ -910,6 +1067,9 @@ override_options ()
       {"i586", PROCESSOR_PENTIUM, 0},
       {"pentium", PROCESSOR_PENTIUM, 0},
       {"pentium-mmx", PROCESSOR_PENTIUM, PTA_MMX},
+      {"winchip-c6", PROCESSOR_I486, PTA_MMX},
+      {"winchip2", PROCESSOR_I486, PTA_MMX | PTA_3DNOW},
+      {"c3", PROCESSOR_I486, PTA_MMX | PTA_3DNOW},
       {"i686", PROCESSOR_PENTIUMPRO, 0},
       {"pentiumpro", PROCESSOR_PENTIUMPRO, 0},
       {"pentium2", PROCESSOR_PENTIUMPRO, PTA_MMX},
@@ -929,10 +1089,38 @@ override_options ()
                                      | PTA_3DNOW_A | PTA_SSE},
       {"athlon-mp", PROCESSOR_ATHLON, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW
                                      | PTA_3DNOW_A | PTA_SSE},
+      {"k8", PROCESSOR_K8, PTA_MMX | PTA_PREFETCH_SSE | PTA_3DNOW | PTA_64BIT
+                                     | PTA_3DNOW_A | PTA_SSE | PTA_SSE2},
     };
 
   int const pta_size = ARRAY_SIZE (processor_alias_table);
 
+  /* By default our XFmode is the 80-bit extended format.  If we have
+     use TFmode instead, it's also the 80-bit format, but with padding.  */
+  real_format_for_mode[XFmode - QFmode] = &ieee_extended_intel_96_format;
+  real_format_for_mode[TFmode - QFmode] = &ieee_extended_intel_128_format;
+
+  /* Set the default values for switches whose default depends on TARGET_64BIT
+     in case they weren't overwritten by command line options.  */
+  if (TARGET_64BIT)
+    {
+      if (flag_omit_frame_pointer == 2)
+       flag_omit_frame_pointer = 1;
+      if (flag_asynchronous_unwind_tables == 2)
+       flag_asynchronous_unwind_tables = 1;
+      if (flag_pcc_struct_return == 2)
+       flag_pcc_struct_return = 0;
+    }
+  else
+    {
+      if (flag_omit_frame_pointer == 2)
+       flag_omit_frame_pointer = 0;
+      if (flag_asynchronous_unwind_tables == 2)
+       flag_asynchronous_unwind_tables = 0;
+      if (flag_pcc_struct_return == 2)
+       flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
+    }
+
 #ifdef SUBTARGET_OVERRIDE_OPTIONS
   SUBTARGET_OVERRIDE_OPTIONS;
 #endif
@@ -942,7 +1130,7 @@ override_options ()
   if (!ix86_cpu_string)
     ix86_cpu_string = cpu_names [TARGET_CPU_DEFAULT];
   if (!ix86_arch_string)
-    ix86_arch_string = TARGET_64BIT ? "athlon-4" : "i386";
+    ix86_arch_string = TARGET_64BIT ? "k8" : "i386";
 
   if (ix86_cmodel_string != 0)
     {
@@ -992,22 +1180,24 @@ override_options ()
        /* Default cpu tuning to the architecture.  */
        ix86_cpu = ix86_arch;
        if (processor_alias_table[i].flags & PTA_MMX
-           && !(target_flags & MASK_MMX_SET))
+           && !(target_flags_explicit & MASK_MMX))
          target_flags |= MASK_MMX;
        if (processor_alias_table[i].flags & PTA_3DNOW
-           && !(target_flags & MASK_3DNOW_SET))
+           && !(target_flags_explicit & MASK_3DNOW))
          target_flags |= MASK_3DNOW;
        if (processor_alias_table[i].flags & PTA_3DNOW_A
-           && !(target_flags & MASK_3DNOW_A_SET))
+           && !(target_flags_explicit & MASK_3DNOW_A))
          target_flags |= MASK_3DNOW_A;
        if (processor_alias_table[i].flags & PTA_SSE
-           && !(target_flags & MASK_SSE_SET))
+           && !(target_flags_explicit & MASK_SSE))
          target_flags |= MASK_SSE;
        if (processor_alias_table[i].flags & PTA_SSE2
-           && !(target_flags & MASK_SSE2_SET))
+           && !(target_flags_explicit & MASK_SSE2))
          target_flags |= MASK_SSE2;
        if (processor_alias_table[i].flags & PTA_PREFETCH_SSE)
          x86_prefetch_sse = true;
+       if (TARGET_64BIT && !(processor_alias_table[i].flags & PTA_64BIT))
+         error ("CPU you selected does not support x86-64 instruction set");
        break;
       }
 
@@ -1018,6 +1208,8 @@ override_options ()
     if (! strcmp (ix86_cpu_string, processor_alias_table[i].name))
       {
        ix86_cpu = processor_alias_table[i].processor;
+       if (TARGET_64BIT && !(processor_alias_table[i].flags & PTA_64BIT))
+         error ("CPU you selected does not support x86-64 instruction set");
        break;
       }
   if (processor_alias_table[i].flags & PTA_PREFETCH_SSE)
@@ -1111,20 +1303,20 @@ override_options ()
      don't want additional code to keep the stack aligned when
      optimizing for code size.  */
   ix86_preferred_stack_boundary = (optimize_size
-                                  ? TARGET_64BIT ? 64 : 32
+                                  ? TARGET_64BIT ? 128 : 32
                                   : 128);
   if (ix86_preferred_stack_boundary_string)
     {
       i = atoi (ix86_preferred_stack_boundary_string);
-      if (i < (TARGET_64BIT ? 3 : 2) || i > 12)
+      if (i < (TARGET_64BIT ? 4 : 2) || i > 12)
        error ("-mpreferred-stack-boundary=%d is not between %d and 12", i,
-              TARGET_64BIT ? 3 : 2);
+              TARGET_64BIT ? 4 : 2);
       else
        ix86_preferred_stack_boundary = (1 << i) * BITS_PER_UNIT;
     }
 
   /* Validate -mbranch-cost= value, or provide default.  */
-  ix86_branch_cost = processor_target_table[ix86_cpu].branch_cost;
+  ix86_branch_cost = processor_target_table[ix86_cpu].cost->branch_cost;
   if (ix86_branch_cost_string)
     {
       i = atoi (ix86_branch_cost_string);
@@ -1218,13 +1410,13 @@ override_options ()
   if (TARGET_3DNOW)
     {
       target_flags |= MASK_MMX;
-      /* If we are targetting the Athlon architecture, enable the 3Dnow/MMX
+      /* If we are targeting the Athlon architecture, enable the 3Dnow/MMX
         extensions it adds.  */
       if (x86_3dnow_a & (1 << ix86_arch))
        target_flags |= MASK_3DNOW_A;
     }
   if ((x86_accumulate_outgoing_args & CPUMASK)
-      && !(target_flags & MASK_ACCUMULATE_OUTGOING_ARGS_SET)
+      && !(target_flags_explicit & MASK_ACCUMULATE_OUTGOING_ARGS)
       && !optimize_size)
     target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS;
 
@@ -1249,13 +1441,15 @@ optimization_options (level, size)
   if (level > 1)
     flag_schedule_insns = 0;
 #endif
-  if (TARGET_64BIT && optimize >= 1)
-    flag_omit_frame_pointer = 1;
-  if (TARGET_64BIT)
-    {
-      flag_pcc_struct_return = 0;
-      flag_asynchronous_unwind_tables = 1;
-    }
+
+  /* The default values of these switches depend on the TARGET_64BIT
+     that is not known at this moment.  Mark these values with 2 and
+     let user the to override these.  In case there is no command line option
+     specifying them, we will set the defaults in override_options.  */
+  if (optimize >= 1)
+    flag_omit_frame_pointer = 2;
+  flag_pcc_struct_return = 2;
+  flag_asynchronous_unwind_tables = 2;
 }
 \f
 /* Table of valid machine attributes.  */
@@ -1265,6 +1459,9 @@ const struct attribute_spec ix86_attribute_table[] =
   /* Stdcall attribute says callee is responsible for popping arguments
      if they are not variable.  */
   { "stdcall",   0, 0, false, true,  true,  ix86_handle_cdecl_attribute },
+  /* Fastcall attribute says callee is responsible for popping arguments
+     if they are not variable.  */
+  { "fastcall",  0, 0, false, true,  true,  ix86_handle_cdecl_attribute },
   /* Cdecl attribute says the callee is a normal C declaration */
   { "cdecl",     0, 0, false, true,  true,  ix86_handle_cdecl_attribute },
   /* Regparm attribute specifies how many integer arguments are to be
@@ -1275,10 +1472,66 @@ const struct attribute_spec ix86_attribute_table[] =
   { "dllexport", 0, 0, false, false, false, ix86_handle_dll_attribute },
   { "shared",    0, 0, true,  false, false, ix86_handle_shared_attribute },
 #endif
+  { "ms_struct", 0, 0, false, false,  false, ix86_handle_struct_attribute },
+  { "gcc_struct", 0, 0, false, false,  false, ix86_handle_struct_attribute },
   { NULL,        0, 0, false, false, false, NULL }
 };
 
-/* Handle a "cdecl" or "stdcall" attribute;
+/* If PIC, we cannot make sibling calls to global functions
+   because the PLT requires %ebx live.
+   If we are returning floats on the register stack, we cannot make
+   sibling calls to functions that return floats.  (The stack adjust
+   instruction will wind up after the sibcall jump, and not be executed.)  */
+
+static bool
+ix86_function_ok_for_sibcall (decl, exp)
+     tree decl;
+     tree exp;
+{
+  /* If we are generating position-independent code, we cannot sibcall
+     optimize any indirect call, or a direct call to a global function,
+     as the PLT requires %ebx be live.  */
+  if (!TARGET_64BIT && flag_pic && (!decl || TREE_PUBLIC (decl)))
+    return false;
+
+  /* If we are returning floats on the 80387 register stack, we cannot
+     make a sibcall from a function that doesn't return a float to a
+     function that does; the necessary stack adjustment will not be
+     executed.  */
+  if (STACK_REG_P (ix86_function_value (TREE_TYPE (exp)))
+      && ! STACK_REG_P (ix86_function_value (TREE_TYPE (DECL_RESULT (cfun->decl)))))
+    return false;
+
+  /* If this call is indirect, we'll need to be able to use a call-clobbered
+     register for the address of the target function.  Make sure that all 
+     such registers are not used for passing parameters.  */
+  if (!decl && !TARGET_64BIT)
+    {
+      int regparm = ix86_regparm;
+      tree attr, type;
+
+      /* We're looking at the CALL_EXPR, we need the type of the function.  */
+      type = TREE_OPERAND (exp, 0);            /* pointer expression */
+      type = TREE_TYPE (type);                 /* pointer type */
+      type = TREE_TYPE (type);                 /* function type */
+
+      attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
+      if (attr)
+        regparm = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
+
+      if (regparm >= 3)
+       {
+         /* ??? Need to count the actual number of registers to be used,
+            not the possible number of registers.  Fix later.  */
+         return false;
+       }
+    }
+
+  /* Otherwise okay.  That also includes certain types of indirect calls.  */
+  return true;
+}
+
+/* Handle a "cdecl", "stdcall", or "fastcall" attribute;
    arguments as in struct attribute_spec.handler.  */
 static tree
 ix86_handle_cdecl_attribute (node, name, args, flags, no_add_attrs)
@@ -1297,6 +1550,27 @@ ix86_handle_cdecl_attribute (node, name, args, flags, no_add_attrs)
               IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
+  else
+    {
+      if (is_attribute_p ("fastcall", name))
+        {
+          if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (*node)))
+            {
+              error ("fastcall and stdcall attributes are not compatible");
+            }
+           else if (lookup_attribute ("regparm", TYPE_ATTRIBUTES (*node)))
+            {
+              error ("fastcall and regparm attributes are not compatible");
+            }
+        }
+      else if (is_attribute_p ("stdcall", name))
+        {
+          if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (*node)))
+            {
+              error ("fastcall and stdcall attributes are not compatible");
+            }
+        }
+    }
 
   if (TARGET_64BIT)
     {
@@ -1343,6 +1617,11 @@ ix86_handle_regparm_attribute (node, name, args, flags, no_add_attrs)
                   IDENTIFIER_POINTER (name), REGPARM_MAX);
          *no_add_attrs = true;
        }
+
+      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (*node)))
+    {
+      error ("fastcall and regparm attributes are not compatible");
+    }
     }
 
   return NULL_TREE;
@@ -1363,6 +1642,11 @@ ix86_comp_type_attributes (type1, type2)
   if (TREE_CODE (type1) != FUNCTION_TYPE)
     return 1;
 
+  /*  Check for mismatched fastcall types */ 
+  if (!lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type1))
+      != !lookup_attribute ("fastcall", 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)))
@@ -1370,6 +1654,21 @@ ix86_comp_type_attributes (type1, type2)
   return 1;
 }
 \f
+/* Return the regparm value for a fuctio with the indicated TYPE.  */
+
+static int
+ix86_fntype_regparm (type)
+     tree type;
+{
+  tree attr;
+
+  attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
+  if (attr)
+    return TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
+  else
+    return ix86_regparm;
+}
+
 /* 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),
@@ -1398,8 +1697,9 @@ ix86_return_pops_args (fundecl, funtype, size)
     /* Cdecl functions override -mrtd, and never pop the stack.  */
   if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) {
 
-    /* Stdcall functions will pop the stack if not variable args.  */
-    if (lookup_attribute ("stdcall", 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)))
       rtd = 1;
 
     if (rtd
@@ -1413,15 +1713,7 @@ ix86_return_pops_args (fundecl, funtype, size)
   if (aggregate_value_p (TREE_TYPE (funtype))
       && !TARGET_64BIT)
     {
-      int nregs = ix86_regparm;
-
-      if (funtype)
-       {
-         tree attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (funtype));
-
-         if (attr)
-           nregs = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
-       }
+      int nregs = ix86_fntype_regparm (funtype);
 
       if (!nregs)
        return GET_MODE_SIZE (Pmode);
@@ -1493,6 +1785,17 @@ init_cumulative_args (cum, fntype, libname)
     }
   cum->maybe_vaarg = false;
 
+  /* Use ecx and edx registers if function has fastcall attribute */
+  if (fntype && !TARGET_64BIT)
+    {
+      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
+       {
+         cum->nregs = 2;
+         cum->fastcall = 1;
+       }
+    }
+
+
   /* Determine if this function has variable arguments.  This is
      indicated by the last argument being 'void_type_mode' if there
      are no variable arguments.  If there are variable arguments, then
@@ -1507,7 +1810,10 @@ init_cumulative_args (cum, fntype, libname)
          if (next_param == 0 && TREE_VALUE (param) != void_type_node)
            {
              if (!TARGET_64BIT)
-               cum->nregs = 0;
+               {
+                 cum->nregs = 0;
+                 cum->fastcall = 0;
+               }
              cum->maybe_vaarg = true;
            }
        }
@@ -1522,7 +1828,7 @@ init_cumulative_args (cum, fntype, libname)
   return;
 }
 
-/* x86-64 register passing impleemntation.  See x86-64 ABI for details.  Goal
+/* x86-64 register passing implementation.  See x86-64 ABI for details.  Goal
    of this code is to classify each 8bytes of incoming argument by the register
    class and assign registers accordingly.  */
 
@@ -1586,7 +1892,11 @@ classify_argument (mode, type, classes, bit_offset)
 {
   int bytes =
     (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
-  int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+  int words = (bytes + (bit_offset % 64) / 8 + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+
+  /* Variable sized entities are always passed/returned in memory.  */
+  if (bytes < 0)
+    return 0;
 
   if (type && AGGREGATE_TYPE_P (type))
     {
@@ -1633,7 +1943,7 @@ classify_argument (mode, type, classes, bit_offset)
                     return 0;
                   for (i = 0; i < num; i++)
                     {
-                      int pos = (offset + bit_offset) / 8 / 8;
+                      int pos = (offset + (bit_offset % 64)) / 8 / 8;
                       classes[i + pos] =
                         merge_classes (subclasses[i], classes[i + pos]);
                     }
@@ -1670,7 +1980,7 @@ classify_argument (mode, type, classes, bit_offset)
                      for (i = 0; i < num; i++)
                        {
                          int pos =
-                           (int_bit_position (field) + bit_offset) / 8 / 8;
+                           (int_bit_position (field) + (bit_offset % 64)) / 8 / 8;
                          classes[i + pos] =
                            merge_classes (subclasses[i], classes[i + pos]);
                        }
@@ -1716,12 +2026,12 @@ classify_argument (mode, type, classes, bit_offset)
 
                   num = classify_argument (TYPE_MODE (type),
                                            type, subclasses,
-                                           (offset + bit_offset) % 256);
+                                           (offset + (bit_offset % 64)) % 256);
                   if (!num)
                     return 0;
                   for (i = 0; i < num; i++)
                     {
-                      int pos = (offset + bit_offset) / 8 / 8;
+                      int pos = (offset + (bit_offset % 64)) / 8 / 8;
                       classes[i + pos] =
                         merge_classes (subclasses[i], classes[i + pos]);
                     }
@@ -1844,8 +2154,7 @@ classify_argument (mode, type, classes, bit_offset)
     case V2SImode:
     case V4HImode:
     case V8QImode:
-      classes[0] = X86_64_SSE_CLASS;
-      return 1;
+      return 0;
     case BLKmode:
     case VOIDmode:
       return 0;
@@ -1983,7 +2292,7 @@ construct_container (mode, type, in_return, nintregs, nsseregs, intreg, sse_regn
            break;
          case X86_64_INTEGER_CLASS:
          case X86_64_INTEGERSI_CLASS:
-           /* Merge TImodes on aligned occassions here too.  */
+           /* Merge TImodes on aligned occasions here too.  */
            if (i * 8 + 8 > bytes)
              tmpmode = mode_for_size ((bytes - i * 8) * BITS_PER_UNIT, MODE_INT, 0);
            else if (class[i] == X86_64_INTEGERSI_CLASS)
@@ -2013,14 +2322,16 @@ construct_container (mode, type, in_return, nintregs, nsseregs, intreg, sse_regn
            sse_regno++;
            break;
          case X86_64_SSE_CLASS:
-           if (i < n && class[i + 1] == X86_64_SSEUP_CLASS)
-             tmpmode = TImode, i++;
+           if (i < n - 1 && class[i + 1] == X86_64_SSEUP_CLASS)
+             tmpmode = TImode;
            else
              tmpmode = DImode;
            exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
                                               gen_rtx_REG (tmpmode,
                                                            SSE_REGNO (sse_regno)),
                                               GEN_INT (i*8));
+           if (tmpmode == TImode)
+             i++;
            sse_regno++;
            break;
          default:
@@ -2121,7 +2432,7 @@ function_arg (cum, mode, type, named)
     (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
   int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
 
-  /* Handle an hidden AL argument containing number of registers for varargs
+  /* Handle a hidden AL argument containing number of registers for varargs
      x86-64 functions.  For i386 ABI just return constm1_rtx to avoid
      any AL settings.  */
   if (mode == VOIDmode)
@@ -2152,7 +2463,22 @@ function_arg (cum, mode, type, named)
       case HImode:
       case QImode:
        if (words <= cum->nregs)
-         ret = gen_rtx_REG (mode, cum->regno);
+         {
+           int regno = cum->regno;
+
+           /* Fastcall allocates the first two DWORD (SImode) or
+              smaller arguments to ECX and EDX.  */
+           if (cum->fastcall)
+             {
+               if (mode == BLKmode || mode == DImode)
+                 break;
+               /* ECX not EAX is the first allocated register.  */
+               if (regno == 0)
+                     regno = 2;
+             }
+           ret = gen_rtx_REG (mode, regno);
+         }
        break;
       case TImode:
        if (cum->sse_nregs)
@@ -2177,6 +2503,32 @@ function_arg (cum, mode, type, named)
   return ret;
 }
 
+/* A C expression that indicates when an argument must be passed by
+   reference.  If nonzero for an argument, a copy of that argument is
+   made in memory and a pointer to the argument is passed instead of
+   the argument itself.  The pointer is passed in whatever way is
+   appropriate for passing a pointer to that type.  */
+
+int
+function_arg_pass_by_reference (cum, mode, type, named)
+     CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+     tree type;
+     int named ATTRIBUTE_UNUSED;
+{
+  if (!TARGET_64BIT)
+    return 0;
+
+  if (type && int_size_in_bytes (type) == -1)
+    {
+      if (TARGET_DEBUG_ARG)
+       fprintf (stderr, "function_arg_pass_by_reference\n");
+      return 1;
+    }
+
+  return 0;
+}
+
 /* Gives the alignment boundary, in bits, of an argument with the specified mode
    and type.   */
 
@@ -2228,14 +2580,15 @@ ix86_function_value (valtype)
       rtx ret = construct_container (TYPE_MODE (valtype), valtype, 1,
                                     REGPARM_MAX, SSE_REGPARM_MAX,
                                     x86_64_int_return_registers, 0);
-      /* For zero sized structures, construct_continer return NULL, but we need
-         to keep rest of compiler happy by returning meaningfull value.  */
+      /* For zero sized structures, construct_container return NULL, but we need
+         to keep rest of compiler happy by returning meaningful value.  */
       if (!ret)
        ret = gen_rtx_REG (TYPE_MODE (valtype), 0);
       return ret;
     }
   else
-    return gen_rtx_REG (TYPE_MODE (valtype), VALUE_REGNO (TYPE_MODE (valtype)));
+    return gen_rtx_REG (TYPE_MODE (valtype),
+                       ix86_value_regno (TYPE_MODE (valtype)));
 }
 
 /* Return false iff type is returned in memory.  */
@@ -2285,7 +2638,20 @@ ix86_libcall_value (mode)
        }
     }
   else
-   return gen_rtx_REG (mode, VALUE_REGNO (mode));
+   return gen_rtx_REG (mode, ix86_value_regno (mode));
+}
+
+/* Given a mode, return the register to use for a return value.  */
+
+static int
+ix86_value_regno (mode)
+     enum machine_mode mode;
+{
+  if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_FLOAT_RETURNS_IN_80387)
+    return FIRST_FLOAT_REG;
+  if (mode == TImode || VECTOR_MODE_P (mode))
+    return FIRST_SSE_REG;
+  return 0;
 }
 \f
 /* Create the va_list data type.  */
@@ -2397,7 +2763,7 @@ ix86_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
   if (next_cum.sse_nregs)
     {
       /* Now emit code to save SSE registers.  The AX parameter contains number
-        of SSE parameter regsiters used to call this function.  We use
+        of SSE parameter registers used to call this function.  We use
         sse_prologue_save insn template that produces computed jump across
         SSE saves.  We need some preparation work to get this working.  */
 
@@ -2518,6 +2884,7 @@ ix86_va_arg (valist, type)
   rtx lab_false, lab_over = NULL_RTX;
   rtx addr_rtx, r;
   rtx container;
+  int indirect_p = 0;
 
   /* Only 64bit target needs something special.  */
   if (!TARGET_64BIT)
@@ -2537,6 +2904,13 @@ ix86_va_arg (valist, type)
   sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
 
   size = int_size_in_bytes (type);
+  if (size == -1)
+    {
+      /* Passed by reference.  */
+      indirect_p = 1;
+      type = build_pointer_type (type);
+      size = int_size_in_bytes (type);
+    }
   rsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
 
   container = construct_container (TYPE_MODE (type), type, 0,
@@ -2563,11 +2937,11 @@ ix86_va_arg (valist, type)
       need_temp = ((needed_intregs && TYPE_ALIGN (type) > 64)
                   || TYPE_ALIGN (type) > 128);
 
-      /* In case we are passing structure, verify that it is consetuctive block
+      /* In case we are passing structure, verify that it is consecutive block
          on the register save area.  If not we need to do moves.  */
       if (!need_temp && !REG_P (container))
        {
-         /* Verify that all registers are strictly consetuctive  */
+         /* Verify that all registers are strictly consecutive  */
          if (SSE_REGNO_P (REGNO (XEXP (XVECEXP (container, 0, 0), 0))))
            {
              int i;
@@ -2727,9 +3101,53 @@ ix86_va_arg (valist, type)
   if (container)
     emit_label (lab_over);
 
+  if (indirect_p)
+    {
+      r = gen_rtx_MEM (Pmode, addr_rtx);
+      set_mem_alias_set (r, get_varargs_alias_set ());
+      emit_move_insn (addr_rtx, r);
+    }
+
   return addr_rtx;
 }
 \f
+/* Return nonzero if OP is either a i387 or SSE fp register.  */
+int
+any_fp_register_operand (op, mode)
+     rtx op;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  return ANY_FP_REG_P (op);
+}
+
+/* Return nonzero if OP is an i387 fp register.  */
+int
+fp_register_operand (op, mode)
+     rtx op;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  return FP_REG_P (op);
+}
+
+/* Return nonzero if OP is a non-fp register_operand.  */
+int
+register_and_not_any_fp_reg_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  return register_operand (op, mode) && !ANY_FP_REG_P (op);
+}
+
+/* Return nonzero if OP is a register operand other than an
+   i387 fp register.  */
+int
+register_and_not_fp_reg_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  return register_operand (op, mode) && !FP_REG_P (op);
+}
+
 /* Return nonzero if OP is general operand representable on x86_64.  */
 
 int
@@ -2930,14 +3348,14 @@ local_symbolic_operand (op, mode)
      rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
-  if (GET_CODE (op) == LABEL_REF)
-    return 1;
-
   if (GET_CODE (op) == CONST
       && GET_CODE (XEXP (op, 0)) == PLUS
       && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
     op = XEXP (XEXP (op, 0), 0);
 
+  if (GET_CODE (op) == LABEL_REF)
+    return 1;
+
   if (GET_CODE (op) != SYMBOL_REF)
     return 0;
 
@@ -3053,6 +3471,32 @@ call_insn_operand (op, mode)
   return general_operand (op, Pmode);
 }
 
+/* Test for a valid operand for a call instruction.  Don't allow the
+   arg pointer register or virtual regs since they may decay into
+   reg + const, which the patterns can't handle.  */
+
+int
+sibcall_insn_operand (op, mode)
+     rtx op;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  /* Disallow indirect through a virtual register.  This leads to
+     compiler aborts when trying to eliminate them.  */
+  if (GET_CODE (op) == REG
+      && (op == arg_pointer_rtx
+         || op == frame_pointer_rtx
+         || (REGNO (op) >= FIRST_PSEUDO_REGISTER
+             && REGNO (op) <= LAST_VIRTUAL_REGISTER)))
+    return 0;
+
+  /* Explicitly allow SYMBOL_REF even if pic.  */
+  if (GET_CODE (op) == SYMBOL_REF)
+    return 1;
+
+  /* Otherwise we can only allow register operands.  */
+  return register_operand (op, Pmode);
+}
+
 int
 constant_call_address_operand (op, mode)
      rtx op;
@@ -3094,7 +3538,7 @@ const248_operand (op, mode)
          && (INTVAL (op) == 2 || INTVAL (op) == 4 || INTVAL (op) == 8));
 }
 
-/* True if this is a constant appropriate for an increment or decremenmt.  */
+/* True if this is a constant appropriate for an increment or decrement.  */
 
 int
 incdec_operand (op, mode)
@@ -3193,6 +3637,30 @@ nonmemory_no_elim_operand (op, mode)
   return GET_CODE (op) == CONST_INT || register_operand (op, mode);
 }
 
+/* Return false if this is any eliminable register or stack register,
+   otherwise work like register_operand.  */
+
+int
+index_register_operand (op, mode)
+     register rtx op;
+     enum machine_mode mode;
+{
+  rtx t = op;
+  if (GET_CODE (t) == SUBREG)
+    t = SUBREG_REG (t);
+  if (!REG_P (t))
+    return 0;
+  if (t == arg_pointer_rtx
+      || t == frame_pointer_rtx
+      || t == virtual_incoming_args_rtx
+      || t == virtual_stack_vars_rtx
+      || t == virtual_stack_dynamic_rtx
+      || REGNO (t) == STACK_POINTER_REGNUM)
+    return 0;
+
+  return general_operand (op, mode);
+}
+
 /* Return true if op is a Q_REGS class register.  */
 
 int
@@ -3207,6 +3675,18 @@ q_regs_operand (op, mode)
   return ANY_QI_REG_P (op);
 }
 
+/* Return true if op is an flags register.  */
+
+int
+flags_reg_operand (op, mode)
+     register rtx op;
+     enum machine_mode mode;
+{
+  if (mode != VOIDmode && GET_MODE (op) != mode)
+    return 0;
+  return REG_P (op) && REGNO (op) == FLAGS_REG && GET_MODE (op) != VOIDmode;
+}
+
 /* Return true if op is a NON_Q_REGS class register.  */
 
 int
@@ -3221,6 +3701,31 @@ non_q_regs_operand (op, mode)
   return NON_QI_REG_P (op);
 }
 
+int
+zero_extended_scalar_load_operand (op, mode)
+     rtx op;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  unsigned n_elts;
+  if (GET_CODE (op) != MEM)
+    return 0;
+  op = maybe_get_pool_constant (op);
+  if (!op)
+    return 0;
+  if (GET_CODE (op) != CONST_VECTOR)
+    return 0;
+  n_elts =
+    (GET_MODE_SIZE (GET_MODE (op)) /
+     GET_MODE_SIZE (GET_MODE_INNER (GET_MODE (op))));
+  for (n_elts--; n_elts > 0; n_elts--)
+    {
+      rtx elt = CONST_VECTOR_ELT (op, n_elts);
+      if (elt != CONST0_RTX (GET_MODE_INNER (GET_MODE (op))))
+       return 0;
+    }
+  return 1;
+}
+
 /* Return 1 if OP is a comparison that can be used in the CMPSS/CMPPS
    insns.  */
 int
@@ -3295,40 +3800,76 @@ ix86_comparison_operator (op, mode)
     }
 }
 
-/* Return 1 if OP is a comparison operator that can be issued by fcmov.  */
-
+/* Return 1 if OP is a valid comparison operator testing carry flag
+   to be set.  */
 int
-fcmov_comparison_operator (op, mode)
-    register rtx op;
-    enum machine_mode mode;
+ix86_carry_flag_operator (op, mode)
+     register rtx op;
+     enum machine_mode mode;
 {
   enum machine_mode inmode;
   enum rtx_code code = GET_CODE (op);
+
   if (mode != VOIDmode && GET_MODE (op) != mode)
     return 0;
   if (GET_RTX_CLASS (code) != '<')
     return 0;
   inmode = GET_MODE (XEXP (op, 0));
+  if (GET_CODE (XEXP (op, 0)) != REG
+      || REGNO (XEXP (op, 0)) != 17
+      || XEXP (op, 1) != const0_rtx)
+    return 0;
+
   if (inmode == CCFPmode || inmode == CCFPUmode)
     {
       enum rtx_code second_code, bypass_code;
+
       ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
       if (bypass_code != NIL || second_code != NIL)
        return 0;
       code = ix86_fp_compare_code_to_integer (code);
     }
-  /* i387 supports just limited amount of conditional codes.  */
-  switch (code)
-    {
-    case LTU: case GTU: case LEU: case GEU:
-      if (inmode == CCmode || inmode == CCFPmode || inmode == CCFPUmode)
-       return 1;
-      return 0;
-    case ORDERED: case UNORDERED:
-    case EQ: case NE:
-      return 1;
-    default:
-      return 0;
+  else if (inmode != CCmode)
+    return 0;
+  return code == LTU;
+}
+
+/* Return 1 if OP is a comparison operator that can be issued by fcmov.  */
+
+int
+fcmov_comparison_operator (op, mode)
+    register rtx op;
+    enum machine_mode mode;
+{
+  enum machine_mode inmode;
+  enum rtx_code code = GET_CODE (op);
+
+  if (mode != VOIDmode && GET_MODE (op) != mode)
+    return 0;
+  if (GET_RTX_CLASS (code) != '<')
+    return 0;
+  inmode = GET_MODE (XEXP (op, 0));
+  if (inmode == CCFPmode || inmode == CCFPUmode)
+    {
+      enum rtx_code second_code, bypass_code;
+
+      ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
+      if (bypass_code != NIL || second_code != NIL)
+       return 0;
+      code = ix86_fp_compare_code_to_integer (code);
+    }
+  /* i387 supports just limited amount of conditional codes.  */
+  switch (code)
+    {
+    case LTU: case GTU: case LEU: case GEU:
+      if (inmode == CCmode || inmode == CCFPmode || inmode == CCFPUmode)
+       return 1;
+      return 0;
+    case ORDERED: case UNORDERED:
+    case EQ: case NE:
+      return 1;
+    default:
+      return 0;
     }
 }
 
@@ -3387,7 +3928,7 @@ ext_register_operand (op, mode)
   if (!register_operand (op, VOIDmode))
     return 0;
 
-  /* Be curefull to accept only registers having upper parts.  */
+  /* Be careful to accept only registers having upper parts.  */
   regno = REG_P (op) ? REGNO (op) : REGNO (SUBREG_REG (op));
   return (regno > LAST_VIRTUAL_REGISTER || regno < 4);
 }
@@ -3586,8 +4127,8 @@ int
 standard_sse_constant_p (x)
      rtx x;
 {
-  if (GET_CODE (x) != CONST_DOUBLE)
-    return -1;
+  if (x == const0_rtx)
+    return 1;
   return (x == CONST0_RTX (GET_MODE (x)));
 }
 
@@ -3677,21 +4218,33 @@ x86_64_sign_extended_value (value)
          }
        break;
 
-      /* For certain code models, the symbolic references are known to fit.  */
+      /* For certain code models, the symbolic references are known to fit.
+        in CM_SMALL_PIC model we know it fits if it is local to the shared
+        library.  Don't count TLS SYMBOL_REFs here, since they should fit
+        only if inside of UNSPEC handled below.  */
       case SYMBOL_REF:
-       return ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL;
+       return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL);
 
       /* For certain code models, the code is near as well.  */
       case LABEL_REF:
-       return ix86_cmodel != CM_LARGE && ix86_cmodel != CM_SMALL_PIC;
+       return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM
+               || ix86_cmodel == CM_KERNEL);
 
       /* We also may accept the offsetted memory references in certain special
          cases.  */
       case CONST:
-       if (GET_CODE (XEXP (value, 0)) == UNSPEC
-           && XINT (XEXP (value, 0), 1) == UNSPEC_GOTPCREL)
-         return 1;
-       else if (GET_CODE (XEXP (value, 0)) == PLUS)
+       if (GET_CODE (XEXP (value, 0)) == UNSPEC)
+         switch (XINT (XEXP (value, 0), 1))
+           {
+           case UNSPEC_GOTPCREL:
+           case UNSPEC_DTPOFF:
+           case UNSPEC_GOTNTPOFF:
+           case UNSPEC_NTPOFF:
+             return 1;
+           default:
+             break;
+           }
+       if (GET_CODE (XEXP (value, 0)) == PLUS)
          {
            rtx op1 = XEXP (XEXP (value, 0), 0);
            rtx op2 = XEXP (XEXP (value, 0), 1);
@@ -3705,12 +4258,12 @@ x86_64_sign_extended_value (value)
            switch (GET_CODE (op1))
              {
                case SYMBOL_REF:
-                 /* For CM_SMALL assume that latest object is 1MB before
+                 /* For CM_SMALL assume that latest object is 16MB before
                     end of 31bits boundary.  We may also accept pretty
                     large negative constants knowing that all objects are
                     in the positive half of address space.  */
                  if (ix86_cmodel == CM_SMALL
-                     && offset < 1024*1024*1024
+                     && offset < 16*1024*1024
                      && trunc_int_for_mode (offset, SImode) == offset)
                    return 1;
                  /* For CM_KERNEL we know that all object resist in the
@@ -3726,7 +4279,7 @@ x86_64_sign_extended_value (value)
                  /* These conditions are similar to SYMBOL_REF ones, just the
                     constraints for code models differ.  */
                  if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM)
-                     && offset < 1024*1024*1024
+                     && offset < 16*1024*1024
                      && trunc_int_for_mode (offset, SImode) == offset)
                    return 1;
                  if (ix86_cmodel == CM_KERNEL
@@ -3734,6 +4287,16 @@ x86_64_sign_extended_value (value)
                      && trunc_int_for_mode (offset, SImode) == offset)
                    return 1;
                  break;
+               case UNSPEC:
+                 switch (XINT (op1, 1))
+                   {
+                   case UNSPEC_DTPOFF:
+                   case UNSPEC_NTPOFF:
+                     if (offset > 0
+                         && trunc_int_for_mode (offset, SImode) == offset)
+                       return 1;
+                   }
+                 break;
                default:
                  return 0;
              }
@@ -3842,7 +4405,10 @@ ix86_frame_pointer_required ()
      the frame pointer by default.  Turn it back on now if we've not
      got a leaf function.  */
   if (TARGET_OMIT_LEAF_FRAME_POINTER
-      && (!current_function_is_leaf || current_function_profile))
+      && (!current_function_is_leaf))
+    return 1;
+
+  if (current_function_profile)
     return 1;
 
   return 0;
@@ -3911,7 +4477,7 @@ ix86_asm_file_end (file)
          (*targetm.asm_out.unique_section) (decl, 0);
          named_section (decl, NULL, 0);
 
-         ASM_GLOBALIZE_LABEL (file, name);
+         (*targetm.asm_out.globalize_label) (file, name);
          fputs ("\t.hidden\t", file);
          assemble_name (file, name);
          fputc ('\n', file);
@@ -3939,7 +4505,7 @@ output_set_got (dest)
   rtx xops[3];
 
   xops[0] = dest;
-  xops[1] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+  xops[1] = gen_rtx_SYMBOL_REF (Pmode, GOT_SYMBOL_NAME);
 
   if (! TARGET_DEEP_BRANCH_PREDICTION || !flag_pic)
     {
@@ -3950,7 +4516,12 @@ output_set_got (dest)
       else
        output_asm_insn ("call\t%a2", xops);
 
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+#if TARGET_MACHO
+      /* Output the "canonical" label name ("Lxx$pb") here too.  This
+         is what will be referred to by the Mach-O PIC subsystem.  */
+      ASM_OUTPUT_LABEL (asm_out_file, machopic_function_base_name ());
+#endif
+      (*targetm.asm_out.internal_label) (asm_out_file, "L",
                                 CODE_LABEL_NUMBER (XEXP (xops[2], 0)));
 
       if (flag_pic)
@@ -3969,7 +4540,7 @@ output_set_got (dest)
 
   if (!flag_pic || TARGET_DEEP_BRANCH_PREDICTION)
     output_asm_insn ("add{l}\t{%1, %0|%0, %1}", xops);
-  else
+  else if (!TARGET_MACHO)
     output_asm_insn ("add{l}\t{%1+[.-%a2], %0|%0, %a1+(.-%a2)}", xops);
 
   return "";
@@ -4246,14 +4817,32 @@ ix86_expand_prologue ()
   int use_mov = 0;
   HOST_WIDE_INT allocate;
 
+  ix86_compute_frame_layout (&frame);
   if (!optimize_size)
     {
-      use_fast_prologue_epilogue
-        = !expensive_function_p (FAST_PROLOGUE_INSN_COUNT);
+      int count = frame.nregs;
+
+      /* The fast prologue uses move instead of push to save registers.  This
+         is significantly longer, but also executes faster as modern hardware
+         can execute the moves in parallel, but can't do that for push/pop.
+        
+        Be careful about choosing what prologue to emit:  When function takes
+        many instructions to execute we may use slow version as well as in
+        case function is known to be outside hot spot (this is known with
+        feedback only).  Weight the size of function by number of registers
+        to save as it is cheap to use one or two push instructions but very
+        slow to use many of them.  */
+      if (count)
+       count = (count - 1) * FAST_PROLOGUE_INSN_COUNT;
+      if (cfun->function_frequency < FUNCTION_FREQUENCY_NORMAL
+         || (flag_branch_probabilities
+             && cfun->function_frequency < FUNCTION_FREQUENCY_HOT))
+       use_fast_prologue_epilogue = 0;
+      else
+        use_fast_prologue_epilogue = !expensive_function_p (count);
       if (TARGET_PROLOGUE_USING_MOVE)
         use_mov = use_fast_prologue_epilogue;
     }
-  ix86_compute_frame_layout (&frame);
 
   /* Note: AT&T enter does NOT have reversed args.  Enter is probably
      slower on all targets.  Also sdb doesn't like it.  */
@@ -4306,6 +4895,10 @@ ix86_expand_prologue ()
       CALL_INSN_FUNCTION_USAGE (insn)
        = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_USE (VOIDmode, arg0),
                             CALL_INSN_FUNCTION_USAGE (insn));
+
+      /* Don't allow scheduling pass to move insns across __alloca
+         call.  */
+      emit_insn (gen_blockage (const0_rtx));
     }
   if (use_mov)
     {
@@ -4340,7 +4933,7 @@ ix86_expand_prologue ()
       /* Even with accurate pre-reload life analysis, we can wind up
         deleting all references to the pic register after reload.
         Consider if cross-jumping unifies two sides of a branch
-        controled by a comparison vs the only read from a global.
+        controlled by a comparison vs the only read from a global.
         In which case, allow the set_got to be deleted, though we're
         too late to do anything about the ebx save in the prologue.  */
       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
@@ -4402,7 +4995,7 @@ ix86_expand_epilogue (style)
      while this code results in LEAVE instruction (or discrete equivalent),
      so it is profitable in some other cases as well.  Especially when there
      are no registers to restore.  We also use this code when TARGET_USE_LEAVE
-     and there is exactly one register to pop. This heruistic may need some
+     and there is exactly one register to pop. This heuristic may need some
      tuning in future.  */
   if ((!sp_valid && frame.nregs <= 1)
       || (TARGET_EPILOGUE_USING_MOVE
@@ -4685,7 +5278,7 @@ ix86_decompose_address (addr, out)
    the address into a reg and make a new pseudo.  But not if the address
    requires to two regs - that would mean more pseudos with longer
    lifetimes.  */
-int
+static int
 ix86_address_cost (x)
      rtx x;
 {
@@ -4830,8 +5423,6 @@ legitimate_constant_p (x)
          {
          case UNSPEC_TPOFF:
            return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
-         case UNSPEC_TP:
-           return true;
          default:
            return false;
          }
@@ -4845,6 +5436,17 @@ legitimate_constant_p (x)
   return true;
 }
 
+/* Determine if it's legal to put X into the constant pool.  This
+   is not possible for the address of thread-local symbols, which
+   is checked above.  */
+
+static bool
+ix86_cannot_force_const_mem (x)
+     rtx x;
+{
+  return !legitimate_constant_p (x);
+}
+
 /* Determine if a given RTX is a valid constant address.  */
 
 bool
@@ -4861,6 +5463,10 @@ constant_address_p (x)
       return TARGET_64BIT;
 
     case CONST:
+      /* For Mach-O, really believe the CONST.  */
+      if (TARGET_MACHO)
+       return true;
+      /* Otherwise fall through.  */
     case SYMBOL_REF:
       return !flag_pic && legitimate_constant_p (x);
 
@@ -4890,8 +5496,6 @@ legitimate_pic_operand_p (x)
          {
          case UNSPEC_TPOFF:
            return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
-         case UNSPEC_TP:
-           return true;
          default:
            return false;
          }
@@ -4919,17 +5523,26 @@ legitimate_pic_address_disp_p (disp)
      when they are not dynamic symbols.  */
   if (TARGET_64BIT)
     {
-      rtx x = disp;
-      if (GET_CODE (disp) == CONST)
-       x = XEXP (disp, 0);
-      /* ??? Handle PIC code models */
-      if (GET_CODE (x) == PLUS
-         && (GET_CODE (XEXP (x, 1)) == CONST_INT
-             && ix86_cmodel == CM_SMALL_PIC
-             && INTVAL (XEXP (x, 1)) < 1024*1024*1024
-             && INTVAL (XEXP (x, 1)) > -1024*1024*1024))
-       x = XEXP (x, 0);
-      if (local_symbolic_operand (x, Pmode))
+      /* TLS references should always be enclosed in UNSPEC.  */
+      if (tls_symbolic_operand (disp, GET_MODE (disp)))
+       return 0;
+      if (GET_CODE (disp) == SYMBOL_REF
+         && ix86_cmodel == CM_SMALL_PIC
+         && (CONSTANT_POOL_ADDRESS_P (disp)
+             || SYMBOL_REF_FLAG (disp)))
+       return 1;
+      if (GET_CODE (disp) == LABEL_REF)
+       return 1;
+      if (GET_CODE (disp) == CONST
+         && GET_CODE (XEXP (disp, 0)) == PLUS
+         && ((GET_CODE (XEXP (XEXP (disp, 0), 0)) == SYMBOL_REF
+              && ix86_cmodel == CM_SMALL_PIC
+              && (CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (disp, 0), 0))
+                  || SYMBOL_REF_FLAG (XEXP (XEXP (disp, 0), 0))))
+             || GET_CODE (XEXP (XEXP (disp, 0), 0)) == LABEL_REF)
+         && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT
+         && INTVAL (XEXP (XEXP (disp, 0), 1)) < 16*1024*1024
+         && INTVAL (XEXP (XEXP (disp, 0), 1)) >= -16*1024*1024)
        return 1;
     }
   if (GET_CODE (disp) != CONST)
@@ -4959,6 +5572,19 @@ legitimate_pic_address_disp_p (disp)
       saw_plus = true;
     }
 
+  /* Allow {LABEL | SYMBOL}_REF - SYMBOL_REF-FOR-PICBASE for Mach-O.  */
+  if (TARGET_MACHO && GET_CODE (disp) == MINUS)
+    {
+      if (GET_CODE (XEXP (disp, 0)) == LABEL_REF
+          || GET_CODE (XEXP (disp, 0)) == SYMBOL_REF)
+        if (GET_CODE (XEXP (disp, 1)) == SYMBOL_REF)
+          {
+            const char *sym_name = XSTR (XEXP (disp, 1), 0);
+            if (strstr (sym_name, "$pb") != 0)
+              return 1;
+          }
+    }
+
   if (GET_CODE (disp) != UNSPEC)
     return 0;
 
@@ -4971,18 +5597,14 @@ legitimate_pic_address_disp_p (disp)
     case UNSPEC_GOTOFF:
       return local_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
     case UNSPEC_GOTTPOFF:
+    case UNSPEC_GOTNTPOFF:
+    case UNSPEC_INDNTPOFF:
       if (saw_plus)
        return false;
       return initial_exec_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
     case UNSPEC_NTPOFF:
-      /* ??? Could support offset here.  */
-      if (saw_plus)
-       return false;
       return local_exec_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
     case UNSPEC_DTPOFF:
-      /* ??? Could support offset here.  */
-      if (saw_plus)
-       return false;
       return local_dynamic_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
     }
 
@@ -5017,6 +5639,13 @@ legitimate_address_p (mode, addr, strict)
       debug_rtx (addr);
     }
 
+  if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_TP)
+    {
+      if (TARGET_DEBUG_ADDR)
+       fprintf (stderr, "Success.\n");
+      return TRUE;
+    }
+
   if (ix86_decompose_address (addr, &parts) <= 0)
     {
       reason = "decomposition failed";
@@ -5122,23 +5751,6 @@ legitimate_address_p (mode, addr, strict)
     {
       reason_rtx = disp;
 
-      if (TARGET_64BIT)
-       {
-         if (!x86_64_sign_extended_value (disp))
-           {
-             reason = "displacement is out of range";
-             goto report_error;
-           }
-       }
-      else
-       {
-         if (GET_CODE (disp) == CONST_DOUBLE)
-           {
-             reason = "displacement is a const_double";
-             goto report_error;
-           }
-       }
-
       if (GET_CODE (disp) == CONST
          && GET_CODE (XEXP (disp, 0)) == UNSPEC)
        switch (XINT (XEXP (disp, 0), 1))
@@ -5151,6 +5763,8 @@ legitimate_address_p (mode, addr, strict)
            goto is_legitimate_pic;
 
          case UNSPEC_GOTTPOFF:
+         case UNSPEC_GOTNTPOFF:
+         case UNSPEC_INDNTPOFF:
          case UNSPEC_NTPOFF:
          case UNSPEC_DTPOFF:
            break;
@@ -5160,15 +5774,28 @@ legitimate_address_p (mode, addr, strict)
            goto report_error;
          }
 
-      else if (flag_pic && SYMBOLIC_CONST (disp))
+      else if (flag_pic && (SYMBOLIC_CONST (disp)
+#if TARGET_MACHO
+                           && !machopic_operand_p (disp)
+#endif
+                           ))
        {
        is_legitimate_pic:
          if (TARGET_64BIT && (index || base))
            {
-             reason = "non-constant pic memory reference";
-             goto report_error;
+             /* foo@dtpoff(%rX) is ok.  */
+             if (GET_CODE (disp) != CONST
+                 || GET_CODE (XEXP (disp, 0)) != PLUS
+                 || GET_CODE (XEXP (XEXP (disp, 0), 0)) != UNSPEC
+                 || GET_CODE (XEXP (XEXP (disp, 0), 1)) != CONST_INT
+                 || (XINT (XEXP (XEXP (disp, 0), 0), 1) != UNSPEC_DTPOFF
+                     && XINT (XEXP (XEXP (disp, 0), 0), 1) != UNSPEC_NTPOFF))
+               {
+                 reason = "non-constant pic memory reference";
+                 goto report_error;
+               }
            }
-         if (! legitimate_pic_address_disp_p (disp))
+         else if (! legitimate_pic_address_disp_p (disp))
            {
              reason = "displacement is an invalid pic construct";
              goto report_error;
@@ -5201,6 +5828,16 @@ legitimate_address_p (mode, addr, strict)
          reason = "displacement is not constant";
          goto report_error;
        }
+      else if (TARGET_64BIT && !x86_64_sign_extended_value (disp))
+       {
+         reason = "displacement is out of range";
+         goto report_error;
+       }
+      else if (!TARGET_64BIT && GET_CODE (disp) == CONST_DOUBLE)
+       {
+         reason = "displacement is a const_double";
+         goto report_error;
+       }
     }
 
   /* Everything looks valid.  */
@@ -5255,28 +5892,31 @@ legitimize_pic_address (orig, reg)
   rtx new = orig;
   rtx base;
 
-  if (local_symbolic_operand (addr, Pmode))
+#if TARGET_MACHO
+  if (reg == 0)
+    reg = gen_reg_rtx (Pmode);
+  /* Use the generic Mach-O PIC machinery.  */
+  return machopic_legitimize_pic_address (orig, GET_MODE (orig), reg);
+#endif
+
+  if (TARGET_64BIT && legitimate_pic_address_disp_p (addr))
+    new = addr;
+  else if (!TARGET_64BIT && local_symbolic_operand (addr, Pmode))
     {
-      /* In 64bit mode we can address such objects directly.  */
-      if (TARGET_64BIT)
-       new = addr;
-      else
-       {
-         /* This symbol may be referenced via a displacement from the PIC
-            base address (@GOTOFF).  */
+      /* This symbol may be referenced via a displacement from the PIC
+        base address (@GOTOFF).  */
 
-         if (reload_in_progress)
-           regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
-         new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
-         new = gen_rtx_CONST (Pmode, new);
-         new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
+      if (reload_in_progress)
+       regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+      new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
+      new = gen_rtx_CONST (Pmode, new);
+      new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
 
-         if (reg != 0)
-           {
-             emit_move_insn (reg, new);
-             new = reg;
-           }
-       }
+      if (reg != 0)
+       {
+         emit_move_insn (reg, new);
+         new = reg;
+       }
     }
   else if (GET_CODE (addr) == SYMBOL_REF)
     {
@@ -5359,7 +5999,9 @@ legitimize_pic_address (orig, reg)
                }
              else
                {
-                 /* ??? We need to limit offsets here.  */
+                 if (INTVAL (op1) < -16*1024*1024
+                     || INTVAL (op1) >= 16*1024*1024)
+                   new = gen_rtx_PLUS (Pmode, op0, force_reg (Pmode, op1));
                }
            }
          else
@@ -5415,23 +6057,22 @@ ix86_encode_section_info (decl, first)
       const char *symbol_str;
       char *newstr;
       size_t len;
-      enum tls_model kind;
+      enum tls_model kind = decl_tls_model (decl);
 
-      if (!flag_pic)
+      if (TARGET_64BIT && ! flag_pic)
        {
-         if (local_p)
-           kind = TLS_MODEL_LOCAL_EXEC;
-         else
-           kind = TLS_MODEL_INITIAL_EXEC;
+         /* x86-64 doesn't allow non-pic code for shared libraries,
+            so don't generate GD/LD TLS models for non-pic code.  */
+         switch (kind)
+           {
+           case TLS_MODEL_GLOBAL_DYNAMIC:
+             kind = TLS_MODEL_INITIAL_EXEC; break;
+           case TLS_MODEL_LOCAL_DYNAMIC:
+             kind = TLS_MODEL_LOCAL_EXEC; break;
+           default:
+             break;
+           }
        }
-      /* Local dynamic is inefficient when we're not combining the
-        parts of the address.  */
-      else if (optimize && local_p)
-       kind = TLS_MODEL_LOCAL_DYNAMIC;
-      else
-       kind = TLS_MODEL_GLOBAL_DYNAMIC;
-      if (kind < flag_tls_default)
-       kind = flag_tls_default;
 
       symbol_str = XSTR (symbol, 0);
 
@@ -5473,7 +6114,9 @@ get_thread_pointer ()
   rtx tp;
 
   tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP);
-  tp = gen_rtx_CONST (Pmode, tp);
+  tp = gen_rtx_MEM (Pmode, tp);
+  RTX_UNCHANGING_P (tp) = 1;
+  set_mem_alias_set (tp, ix86_GOT_alias_set ());
   tp = force_reg (Pmode, tp);
 
   return tp;
@@ -5520,17 +6163,44 @@ legitimize_address (x, oldx, mode)
   if (log)
     {
       rtx dest, base, off, pic;
+      int type;
 
       switch (log)
         {
         case TLS_MODEL_GLOBAL_DYNAMIC:
          dest = gen_reg_rtx (Pmode);
-          emit_insn (gen_tls_global_dynamic (dest, x));
+         if (TARGET_64BIT)
+           {
+             rtx rax = gen_rtx_REG (Pmode, 0), insns;
+
+             start_sequence ();
+             emit_call_insn (gen_tls_global_dynamic_64 (rax, x));
+             insns = get_insns ();
+             end_sequence ();
+
+             emit_libcall_block (insns, dest, rax, x);
+           }
+         else
+           emit_insn (gen_tls_global_dynamic_32 (dest, x));
          break;
 
         case TLS_MODEL_LOCAL_DYNAMIC:
          base = gen_reg_rtx (Pmode);
-         emit_insn (gen_tls_local_dynamic_base (base));
+         if (TARGET_64BIT)
+           {
+             rtx rax = gen_rtx_REG (Pmode, 0), 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);
+             emit_libcall_block (insns, base, rax, note);
+           }
+         else
+           emit_insn (gen_tls_local_dynamic_base_32 (base));
 
          off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPOFF);
          off = gen_rtx_CONST (Pmode, off);
@@ -5538,48 +6208,59 @@ legitimize_address (x, oldx, mode)
          return gen_rtx_PLUS (Pmode, base, off);
 
         case TLS_MODEL_INITIAL_EXEC:
-         if (flag_pic)
+         if (TARGET_64BIT)
+           {
+             pic = NULL;
+             type = UNSPEC_GOTNTPOFF;
+           }
+         else if (flag_pic)
            {
              if (reload_in_progress)
                regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
              pic = pic_offset_table_rtx;
+             type = TARGET_GNU_TLS ? UNSPEC_GOTNTPOFF : UNSPEC_GOTTPOFF;
            }
-         else
+         else if (!TARGET_GNU_TLS)
            {
              pic = gen_reg_rtx (Pmode);
              emit_insn (gen_set_got (pic));
+             type = UNSPEC_GOTTPOFF;
+           }
+         else
+           {
+             pic = NULL;
+             type = UNSPEC_INDNTPOFF;
            }
 
          base = get_thread_pointer ();
 
-         off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_GOTTPOFF);
+         off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), type);
          off = gen_rtx_CONST (Pmode, off);
-         off = gen_rtx_PLUS (Pmode, pic, off);
+         if (pic)
+           off = gen_rtx_PLUS (Pmode, pic, off);
          off = gen_rtx_MEM (Pmode, off);
          RTX_UNCHANGING_P (off) = 1;
          set_mem_alias_set (off, ix86_GOT_alias_set ());
-
-         /* Damn Sun for specifing a set of dynamic relocations without
-            considering the two-operand nature of the architecture!
-            We'd be much better off with a "GOTNTPOFF" relocation that
-            already contained the negated constant.  */
-         /* ??? Using negl and reg+reg addressing appears to be a lose
-            size-wise.  The negl is two bytes, just like the extra movl
-            incurred by the two-operand subl, but reg+reg addressing
-            uses the two-byte modrm form, unlike plain reg.  */
-
          dest = gen_reg_rtx (Pmode);
-         emit_insn (gen_subsi3 (dest, base, off));
+
+         if (TARGET_64BIT || TARGET_GNU_TLS)
+           {
+             emit_move_insn (dest, off);
+             return gen_rtx_PLUS (Pmode, base, dest);
+           }
+         else
+           emit_insn (gen_subsi3 (dest, base, off));
          break;
 
         case TLS_MODEL_LOCAL_EXEC:
          base = get_thread_pointer ();
 
          off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
-                               TARGET_GNU_TLS ? UNSPEC_NTPOFF : UNSPEC_TPOFF);
+                               (TARGET_64BIT || TARGET_GNU_TLS)
+                               ? UNSPEC_NTPOFF : UNSPEC_TPOFF);
          off = gen_rtx_CONST (Pmode, off);
 
-         if (TARGET_GNU_TLS)
+         if (TARGET_64BIT || TARGET_GNU_TLS)
            return gen_rtx_PLUS (Pmode, base, off);
          else
            {
@@ -5767,7 +6448,7 @@ output_pic_addr_const (file, x, code)
 
     case SYMBOL_REF:
       assemble_name (file, XSTR (x, 0));
-      if (code == 'P' && ! SYMBOL_REF_FLAG (x))
+      if (!TARGET_MACHO && code == 'P' && ! SYMBOL_REF_FLAG (x))
        fputs ("@PLT", file);
       break;
 
@@ -5825,11 +6506,13 @@ output_pic_addr_const (file, x, code)
       break;
 
     case MINUS:
-      putc (ASSEMBLER_DIALECT == ASM_INTEL ? '(' : '[', file);
+      if (!TARGET_MACHO)
+       putc (ASSEMBLER_DIALECT == ASM_INTEL ? '(' : '[', file);
       output_pic_addr_const (file, XEXP (x, 0), code);
       putc ('-', file);
       output_pic_addr_const (file, XEXP (x, 1), code);
-      putc (ASSEMBLER_DIALECT == ASM_INTEL ? ')' : ']', file);
+      if (!TARGET_MACHO)
+       putc (ASSEMBLER_DIALECT == ASM_INTEL ? ')' : ']', file);
       break;
 
      case UNSPEC:
@@ -5848,17 +6531,30 @@ output_pic_addr_const (file, x, code)
          fputs ("@GOTPCREL(%rip)", file);
          break;
        case UNSPEC_GOTTPOFF:
+         /* FIXME: This might be @TPOFF in Sun ld too.  */
          fputs ("@GOTTPOFF", file);
          break;
        case UNSPEC_TPOFF:
          fputs ("@TPOFF", file);
          break;
        case UNSPEC_NTPOFF:
-         fputs ("@NTPOFF", file);
+         if (TARGET_64BIT)
+           fputs ("@TPOFF", file);
+         else
+           fputs ("@NTPOFF", file);
          break;
        case UNSPEC_DTPOFF:
          fputs ("@DTPOFF", file);
          break;
+       case UNSPEC_GOTNTPOFF:
+         if (TARGET_64BIT)
+           fputs ("@GOTTPOFF(%rip)", file);
+         else
+           fputs ("@GOTNTPOFF", file);
+         break;
+       case UNSPEC_INDNTPOFF:
+         fputs ("@INDNTPOFF", file);
+         break;
        default:
          output_operand_lossage ("invalid UNSPEC as operand");
          break;
@@ -5892,6 +6588,30 @@ i386_dwarf_output_addr_const (file, x)
   fputc ('\n', file);
 }
 
+/* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL.
+   We need to emit DTP-relative relocations.  */
+
+void
+i386_output_dwarf_dtprel (file, size, x)
+     FILE *file;
+     int size;
+     rtx x;
+{
+  fputs (ASM_LONG, file);
+  output_addr_const (file, x);
+  fputs ("@DTPOFF", file);
+  switch (size)
+    {
+    case 4:
+      break;
+    case 8:
+      fputs (", 0", file);
+      break;
+    default:
+      abort ();
+   }
+}
+
 /* In the name of slightly smaller debug output, and to cater to
    general assembler losage, recognize PIC+GOTOFF and turn it back
    into a direct symbol reference.  */
@@ -6459,7 +7179,7 @@ print_operand (file, x, code)
                    int cputaken = final_forward_branch_p (current_output_insn) == 0;
 
                    /* Emit hints only in the case default branch prediction
-                      heruistics would fail.  */
+                      heuristics would fail.  */
                    if (taken != cputaken)
                      {
                        /* We use 3e (DS) prefix for taken branches and
@@ -6542,36 +7262,21 @@ print_operand (file, x, code)
  /* These float cases don't actually occur as immediate operands.  */
  else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
     {
-      REAL_VALUE_TYPE r;
       char dstr[30];
 
-      REAL_VALUE_FROM_CONST_DOUBLE (r, x);
-      REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
+      real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (x), sizeof (dstr), 0, 1);
       fprintf (file, "%s", dstr);
     }
 
   else if (GET_CODE (x) == CONST_DOUBLE
           && (GET_MODE (x) == XFmode || GET_MODE (x) == TFmode))
     {
-      REAL_VALUE_TYPE r;
       char dstr[30];
 
-      REAL_VALUE_FROM_CONST_DOUBLE (r, x);
-      REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
+      real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (x), sizeof (dstr), 0, 1);
       fprintf (file, "%s", dstr);
     }
 
-  else if (GET_CODE (x) == CONST
-          && GET_CODE (XEXP (x, 0)) == UNSPEC
-          && XINT (XEXP (x, 0), 1) == UNSPEC_TP)
-    {
-      if (ASSEMBLER_DIALECT == ASM_INTEL)
-       fputs ("DWORD PTR ", file);
-      if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0)
-       putc ('%', file);
-      fputs ("gs:0", file);
-    }
-
   else
     {
       if (code != 'P')
@@ -6610,6 +7315,19 @@ print_operand_address (file, addr)
   rtx base, index, disp;
   int scale;
 
+  if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_TP)
+    {
+      if (ASSEMBLER_DIALECT == ASM_INTEL)
+       fputs ("DWORD PTR ", file);
+      if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0)
+       putc ('%', file);
+      if (TARGET_64BIT)
+       fputs ("fs:0", file);
+      else
+       fputs ("gs:0", file);
+      return;
+    }
+
   if (! ix86_decompose_address (addr, &parts))
     abort ();
 
@@ -6639,11 +7357,13 @@ print_operand_address (file, addr)
 
       /* Use one byte shorter RIP relative addressing for 64bit mode.  */
       if (TARGET_64BIT
-         && (GET_CODE (addr) == SYMBOL_REF
+         && ((GET_CODE (addr) == SYMBOL_REF
+              && ! tls_symbolic_operand (addr, GET_MODE (addr)))
              || GET_CODE (addr) == LABEL_REF
              || (GET_CODE (addr) == CONST
                  && GET_CODE (XEXP (addr, 0)) == PLUS
-                 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF
+                 && (GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF
+                     || GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF)
                  && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)))
        fputs ("(%rip)", file);
     }
@@ -6742,6 +7462,7 @@ output_addr_const_extra (file, x)
     {
     case UNSPEC_GOTTPOFF:
       output_addr_const (file, op);
+      /* FIXME: This might be @TPOFF in Sun ld.  */
       fputs ("@GOTTPOFF", file);
       break;
     case UNSPEC_TPOFF:
@@ -6750,12 +7471,26 @@ output_addr_const_extra (file, x)
       break;
     case UNSPEC_NTPOFF:
       output_addr_const (file, op);
-      fputs ("@NTPOFF", file);
+      if (TARGET_64BIT)
+       fputs ("@TPOFF", file);
+      else
+       fputs ("@NTPOFF", file);
       break;
     case UNSPEC_DTPOFF:
       output_addr_const (file, op);
       fputs ("@DTPOFF", file);
       break;
+    case UNSPEC_GOTNTPOFF:
+      output_addr_const (file, op);
+      if (TARGET_64BIT)
+       fputs ("@GOTTPOFF(%rip)", file);
+      else
+       fputs ("@GOTNTPOFF", file);
+      break;
+    case UNSPEC_INDNTPOFF:
+      output_addr_const (file, op);
+      fputs ("@INDNTPOFF", file);
+      break;
 
     default:
       return false;
@@ -7132,12 +7867,12 @@ output_fp_compare (insn, operands, eflags_p, unordered_p)
        if (unordered_p)
          return "ucomiss\t{%1, %0|%0, %1}";
        else
-         return "comiss\t{%1, %0|%0, %y}";
+         return "comiss\t{%1, %0|%0, %1}";
       else
        if (unordered_p)
          return "ucomisd\t{%1, %0|%0, %1}";
        else
-         return "comisd\t{%1, %0|%0, %y}";
+         return "comisd\t{%1, %0|%0, %1}";
     }
 
   if (! STACK_TOP_P (cmp_op0))
@@ -7266,9 +8001,14 @@ ix86_output_addr_diff_elt (file, value, rel)
             ASM_LONG, LPREFIX, value, LPREFIX, rel);
   else if (HAVE_AS_GOTOFF_IN_DATA)
     fprintf (file, "%s%s%d@GOTOFF\n", ASM_LONG, LPREFIX, value);
+#if TARGET_MACHO
+  else if (TARGET_MACHO)
+    fprintf (file, "%s%s%d-%s\n", ASM_LONG, LPREFIX, value,
+            machopic_function_base_name () + 1);
+#endif
   else
-    asm_fprintf (file, "%s%U_GLOBAL_OFFSET_TABLE_+[.-%s%d]\n",
-                ASM_LONG, LPREFIX, value);
+    asm_fprintf (file, "%s%U%s+[.-%s%d]\n",
+                ASM_LONG, GOT_SYMBOL_NAME, LPREFIX, value);
 }
 \f
 /* Generate either "mov $0, reg" or "xor reg, reg", as appropriate
@@ -7309,7 +8049,7 @@ maybe_get_pool_constant (x)
 {
   x = XEXP (x, 0);
 
-  if (flag_pic)
+  if (flag_pic && ! TARGET_64BIT)
     {
       if (GET_CODE (x) != PLUS)
        return NULL_RTX;
@@ -7343,29 +8083,6 @@ ix86_expand_move (mode, operands)
   op0 = operands[0];
   op1 = operands[1];
 
-  /* ??? We have a slight problem.  We need to say that tls symbols are
-     not legitimate constants so that reload does not helpfully reload
-     these constants from a REG_EQUIV, which we cannot handle.  (Recall
-     that general- and local-dynamic address resolution requires a
-     function call.)
-
-     However, if we say that tls symbols are not legitimate constants,
-     then emit_move_insn helpfully drop them into the constant pool.
-
-     It is far easier to work around emit_move_insn than reload.  Recognize
-     the MEM that we would have created and extract the symbol_ref.  */
-
-  if (mode == Pmode
-      && GET_CODE (op1) == MEM
-      && RTX_UNCHANGING_P (op1))
-    {
-      tmp = maybe_get_pool_constant (op1);
-      /* Note that we only care about symbolic constants here, which
-        unlike CONST_INT will always have a proper mode.  */
-      if (tmp && GET_MODE (tmp) == Pmode)
-       op1 = tmp;
-    }
-
   if (tls_symbolic_operand (op1, Pmode))
     {
       op1 = legitimize_address (op1, op1, VOIDmode);
@@ -7378,6 +8095,29 @@ ix86_expand_move (mode, operands)
     }
   else if (flag_pic && mode == Pmode && symbolic_operand (op1, Pmode))
     {
+#if TARGET_MACHO
+      if (MACHOPIC_PURE)
+       {
+         rtx temp = ((reload_in_progress
+                      || ((op0 && GET_CODE (op0) == REG)
+                          && mode == Pmode))
+                     ? op0 : gen_reg_rtx (Pmode));
+         op1 = machopic_indirect_data_reference (op1, temp);
+         op1 = machopic_legitimize_pic_address (op1, mode,
+                                                temp == op1 ? 0 : temp);
+       }
+      else
+       {
+         if (MACHOPIC_INDIRECT)
+           op1 = machopic_indirect_data_reference (op1, 0);
+       }
+      if (op0 != op1)
+       {
+         insn = gen_rtx_SET (VOIDmode, op0, op1);
+         emit_insn (insn);
+       }
+      return;
+#endif /* TARGET_MACHO */
       if (GET_CODE (op0) == MEM)
        op1 = force_reg (Pmode, op1);
       else
@@ -7443,17 +8183,12 @@ ix86_expand_vector_move (mode, operands)
   if ((reload_in_progress | reload_completed) == 0
       && register_operand (operands[0], mode)
       && CONSTANT_P (operands[1]))
-    {
-      rtx addr = gen_reg_rtx (Pmode);
-      emit_move_insn (addr, XEXP (force_const_mem (mode, operands[1]), 0));
-      operands[1] = gen_rtx_MEM (mode, addr);
-    }
+    operands[1] = validize_mem (force_const_mem (mode, operands[1]));
 
   /* Make operand1 a register if it isn't already.  */
-  if ((reload_in_progress | reload_completed) == 0
+  if (!no_new_pseudos
       && !register_operand (operands[0], mode)
-      && !register_operand (operands[1], mode)
-      && operands[1] != CONST0_RTX (mode))
+      && !register_operand (operands[1], mode))
     {
       rtx temp = force_reg (GET_MODE (operands[1]), operands[1]);
       emit_move_insn (operands[0], temp);
@@ -7781,7 +8516,7 @@ ix86_cc_mode (code, op0, op1)
        return CCGCmode;
       /* Codes doable only with sign flag when comparing
          against zero, but we miss jump instruction for it
-         so we need to use relational tests agains overflow
+         so we need to use relational tests against overflow
          that thus needs to be zero.  */
     case GT:                   /* ZF=0 & SF=OF */
     case LE:                   /* ZF=1 | SF<>OF */
@@ -7812,7 +8547,7 @@ ix86_use_fcomi_compare (code)
 
 /* Swap, force into registers, or otherwise massage the two operands
    to a fp comparison.  The operands are updated in place; the new
-   comparsion code is returned.  */
+   comparison code is returned.  */
 
 static enum rtx_code
 ix86_prepare_fp_compare_args (code, pop0, pop1)
@@ -7983,7 +8718,7 @@ ix86_fp_comparison_codes (code, bypass_code, first_code, second_code)
 }
 
 /* Return cost of comparison done fcom + arithmetics operations on AX.
-   All following functions do use number of instructions as an cost metrics.
+   All following functions do use number of instructions as a cost metrics.
    In future this should be tweaked to compute bytes for optimize_size and
    take into account performance of various instructions on various CPUs.  */
 static int
@@ -8027,7 +8762,7 @@ ix86_fp_comparison_fcomi_cost (code)
      enum rtx_code code;
 {
   enum rtx_code bypass_code, first_code, second_code;
-  /* Return arbitarily high cost when instruction is not supported - this
+  /* Return arbitrarily high cost when instruction is not supported - this
      prevents gcc from using it.  */
   if (!TARGET_CMOVE)
     return 1024;
@@ -8042,7 +8777,7 @@ ix86_fp_comparison_sahf_cost (code)
      enum rtx_code code;
 {
   enum rtx_code bypass_code, first_code, second_code;
-  /* Return arbitarily high cost when instruction is not preferred - this
+  /* Return arbitrarily high cost when instruction is not preferred - this
      avoids gcc from using it.  */
   if (!TARGET_USE_SAHF && !optimize_size)
     return 1024;
@@ -8608,85 +9343,227 @@ ix86_expand_setcc (code, dest)
   return 1; /* DONE */
 }
 
-int
-ix86_expand_int_movcc (operands)
-     rtx operands[];
+/* Expand comparison setting or clearing carry flag.  Return true when successful
+   and set pop for the operation.  */
+bool
+ix86_expand_carry_flag_compare (code, op0, op1, pop)
+     rtx op0, op1, *pop;
+     enum rtx_code code;
 {
-  enum rtx_code code = GET_CODE (operands[1]), compare_code;
-  rtx compare_seq, compare_op;
-  rtx second_test, bypass_test;
-  enum machine_mode mode = GET_MODE (operands[0]);
+  enum machine_mode mode =
+    GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
 
-  /* When the compare code is not LTU or GEU, we can not use sbbl case.
-     In case comparsion is done with immediate, we can convert it to LTU or
-     GEU by altering the integer.  */
-
-  if ((code == LEU || code == GTU)
-      && GET_CODE (ix86_compare_op1) == CONST_INT
-      && mode != HImode
-      && INTVAL (ix86_compare_op1) != -1
-      /* For x86-64, the immediate field in the instruction is 32-bit
-        signed, so we can't increment a DImode value above 0x7fffffff.  */
-      && (!TARGET_64BIT
-         || GET_MODE (ix86_compare_op0) != DImode
-         || INTVAL (ix86_compare_op1) != 0x7fffffff)
-      && GET_CODE (operands[2]) == CONST_INT
-      && GET_CODE (operands[3]) == CONST_INT)
+  /* Do not handle DImode compares that go trought special path.  Also we can't
+     deal with FP compares yet.  This is possible to add.   */
+  if ((mode == DImode && !TARGET_64BIT))
+    return false;
+  if (FLOAT_MODE_P (mode))
     {
-      if (code == LEU)
-       code = LTU;
-      else
-       code = GEU;
-      ix86_compare_op1 = gen_int_mode (INTVAL (ix86_compare_op1) + 1,
-                                      GET_MODE (ix86_compare_op0));
-    }
+      rtx second_test = NULL, bypass_test = NULL;
+      rtx compare_op, compare_seq;
 
-  start_sequence ();
-  compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
-  compare_seq = get_insns ();
-  end_sequence ();
+      /* Shortcut:  following common codes never translate into carry flag compares.  */
+      if (code == EQ || code == NE || code == UNEQ || code == LTGT
+         || code == ORDERED || code == UNORDERED)
+       return false;
 
-  compare_code = GET_CODE (compare_op);
+      /* These comparisons require zero flag; swap operands so they won't.  */
+      if ((code == GT || code == UNLE || code == LE || code == UNGT)
+         && !TARGET_IEEE_FP)
+       {
+         rtx tmp = op0;
+         op0 = op1;
+         op1 = tmp;
+         code = swap_condition (code);
+       }
 
-  /* Don't attempt mode expansion here -- if we had to expand 5 or 6
-     HImode insns, we'd be swallowed in word prefix ops.  */
+      /* Try to expand the comparsion and verify that we end up with carry flag
+        based comparsion.  This is fails to be true only when we decide to expand
+        comparsion using arithmetic that is not too common scenario.  */
+      start_sequence ();
+      compare_op = ix86_expand_fp_compare (code, op0, op1, NULL_RTX,
+                                          &second_test, &bypass_test);
+      compare_seq = get_insns ();
+      end_sequence ();
 
-  if (mode != HImode
-      && (mode != DImode || TARGET_64BIT)
-      && GET_CODE (operands[2]) == CONST_INT
-      && GET_CODE (operands[3]) == CONST_INT)
-    {
-      rtx out = operands[0];
-      HOST_WIDE_INT ct = INTVAL (operands[2]);
+      if (second_test || bypass_test)
+       return false;
+      if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode
+         || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode)
+        code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op));
+      else
+       code = GET_CODE (compare_op);
+      if (code != LTU && code != GEU)
+       return false;
+      emit_insn (compare_seq);
+      *pop = compare_op;
+      return true;
+    }
+  if (!INTEGRAL_MODE_P (mode))
+    return false;
+  switch (code)
+    {
+    case LTU:
+    case GEU:
+      break;
+
+    /* Convert a==0 into (unsigned)a<1.  */
+    case EQ:
+    case NE:
+      if (op1 != const0_rtx)
+       return false;
+      op1 = const1_rtx;
+      code = (code == EQ ? LTU : GEU);
+      break;
+
+    /* Convert a>b into b<a or a>=b-1.  */
+    case GTU:
+    case LEU:
+      if (GET_CODE (op1) == CONST_INT)
+       {
+         op1 = gen_int_mode (INTVAL (op1) + 1, GET_MODE (op0));
+         /* Bail out on overflow.  We still can swap operands but that
+            would force loading of the constant into register. */
+         if (op1 == const0_rtx
+             || !x86_64_immediate_operand (op1, GET_MODE (op1)))
+           return false;
+         code = (code == GTU ? GEU : LTU);
+       }
+      else
+       {
+         rtx tmp = op1;
+         op1 = op0;
+         op0 = tmp;
+         code = (code == GTU ? LTU : GEU);
+       }
+      break;
+
+    /* Convert a>0 into (unsigned)a<0x7fffffff.  */
+    case LT:
+    case GE:
+      if (mode == DImode || op1 != const0_rtx)
+       return false;
+      op1 = gen_int_mode (~(1 << (GET_MODE_BITSIZE (mode) - 1)), mode);
+      code = (code == LT ? GEU : LTU);
+      break;
+    case LE:
+    case GT:
+      if (mode == DImode || op1 != constm1_rtx)
+       return false;
+      op1 = gen_int_mode (~(1 << (GET_MODE_BITSIZE (mode) - 1)), mode);
+      code = (code == LE ? GEU : LTU);
+      break;
+
+    default:
+      return false;
+    }
+  ix86_compare_op0 = op0;
+  ix86_compare_op1 = op1;
+  *pop = ix86_expand_compare (code, NULL, NULL);
+  if (GET_CODE (*pop) != LTU && GET_CODE (*pop) != GEU)
+    abort ();
+  return true;
+}
+
+int
+ix86_expand_int_movcc (operands)
+     rtx operands[];
+{
+  enum rtx_code code = GET_CODE (operands[1]), compare_code;
+  rtx compare_seq, compare_op;
+  rtx second_test, bypass_test;
+  enum machine_mode mode = GET_MODE (operands[0]);
+  bool sign_bit_compare_p = false;;
+
+  start_sequence ();
+  compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
+  compare_seq = get_insns ();
+  end_sequence ();
+
+  compare_code = GET_CODE (compare_op);
+
+  if ((ix86_compare_op1 == const0_rtx && (code == GE || code == LT))
+      || (ix86_compare_op1 == constm1_rtx && (code == GT || code == LE)))
+    sign_bit_compare_p = true;
+
+  /* Don't attempt mode expansion here -- if we had to expand 5 or 6
+     HImode insns, we'd be swallowed in word prefix ops.  */
+
+  if ((mode != HImode || TARGET_FAST_PREFIX)
+      && (mode != DImode || TARGET_64BIT)
+      && GET_CODE (operands[2]) == CONST_INT
+      && GET_CODE (operands[3]) == CONST_INT)
+    {
+      rtx out = operands[0];
+      HOST_WIDE_INT ct = INTVAL (operands[2]);
       HOST_WIDE_INT cf = INTVAL (operands[3]);
       HOST_WIDE_INT diff;
 
-      if ((compare_code == LTU || compare_code == GEU)
-         && !second_test && !bypass_test)
+      diff = ct - cf;
+      /*  Sign bit compares are better done using shifts than we do by using
+         sbb.  */
+      if (sign_bit_compare_p
+         || ix86_expand_carry_flag_compare (code, ix86_compare_op0,
+                                            ix86_compare_op1, &compare_op))
        {
          /* Detect overlap between destination and compare sources.  */
          rtx tmp = out;
 
-         /* To simplify rest of code, restrict to the GEU case.  */
-         if (compare_code == LTU)
+          if (!sign_bit_compare_p)
            {
-             int tmp = ct;
-             ct = cf;
-             cf = tmp;
-             compare_code = reverse_condition (compare_code);
-             code = reverse_condition (code);
-           }
-         diff = ct - cf;
+             bool fpcmp = false;
+
+             compare_code = GET_CODE (compare_op);
+
+             if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode
+                 || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode)
+               {
+                 fpcmp = true;
+                 compare_code = ix86_fp_compare_code_to_integer (compare_code);
+               }
+
+             /* To simplify rest of code, restrict to the GEU case.  */
+             if (compare_code == LTU)
+               {
+                 HOST_WIDE_INT tmp = ct;
+                 ct = cf;
+                 cf = tmp;
+                 compare_code = reverse_condition (compare_code);
+                 code = reverse_condition (code);
+               }
+             else
+               {
+                 if (fpcmp)
+                   PUT_CODE (compare_op,
+                             reverse_condition_maybe_unordered
+                               (GET_CODE (compare_op)));
+                 else
+                   PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op)));
+               }
+             diff = ct - cf;
 
-         if (reg_overlap_mentioned_p (out, ix86_compare_op0)
-             || reg_overlap_mentioned_p (out, ix86_compare_op1))
-           tmp = gen_reg_rtx (mode);
+             if (reg_overlap_mentioned_p (out, ix86_compare_op0)
+                 || reg_overlap_mentioned_p (out, ix86_compare_op1))
+               tmp = gen_reg_rtx (mode);
 
-         emit_insn (compare_seq);
-         if (mode == DImode)
-           emit_insn (gen_x86_movdicc_0_m1_rex64 (tmp));
+             if (mode == DImode)
+               emit_insn (gen_x86_movdicc_0_m1_rex64 (tmp, compare_op));
+             else
+               emit_insn (gen_x86_movsicc_0_m1 (gen_lowpart (SImode, tmp), compare_op));
+           }
          else
-           emit_insn (gen_x86_movsicc_0_m1 (tmp));
+           {
+             if (code == GT || code == GE)
+               code = reverse_condition (code);
+             else
+               {
+                 HOST_WIDE_INT tmp = ct;
+                 ct = cf;
+                 cf = tmp;
+               }
+             tmp = emit_store_flag (tmp, code, ix86_compare_op0,
+                                    ix86_compare_op1, VOIDmode, 0, -1);
+           }
 
          if (diff == 1)
            {
@@ -8700,7 +9577,7 @@ ix86_expand_int_movcc (operands)
              if (ct)
                tmp = expand_simple_binop (mode, PLUS,
                                           tmp, GEN_INT (ct),
-                                          tmp, 1, OPTAB_DIRECT);
+                                          copy_rtx (tmp), 1, OPTAB_DIRECT);
            }
          else if (cf == -1)
            {
@@ -8713,7 +9590,7 @@ ix86_expand_int_movcc (operands)
               */
              tmp = expand_simple_binop (mode, IOR,
                                         tmp, GEN_INT (ct),
-                                        tmp, 1, OPTAB_DIRECT);
+                                        copy_rtx (tmp), 1, OPTAB_DIRECT);
            }
          else if (diff == -1 && ct)
            {
@@ -8725,11 +9602,11 @@ ix86_expand_int_movcc (operands)
               *
               * Size 8 - 11.
               */
-             tmp = expand_simple_unop (mode, NOT, tmp, tmp, 1);
+             tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
              if (cf)
                tmp = expand_simple_binop (mode, PLUS,
-                                          tmp, GEN_INT (cf),
-                                          tmp, 1, OPTAB_DIRECT);
+                                          copy_rtx (tmp), GEN_INT (cf),
+                                          copy_rtx (tmp), 1, OPTAB_DIRECT);
            }
          else
            {
@@ -8747,26 +9624,25 @@ ix86_expand_int_movcc (operands)
                {
                  cf = ct;
                  ct = 0;
-                 tmp = expand_simple_unop (mode, NOT, tmp, tmp, 1);
+                 tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
                }
 
              tmp = expand_simple_binop (mode, AND,
-                                        tmp,
+                                        copy_rtx (tmp),
                                         gen_int_mode (cf - ct, mode),
-                                        tmp, 1, OPTAB_DIRECT);
+                                        copy_rtx (tmp), 1, OPTAB_DIRECT);
              if (ct)
                tmp = expand_simple_binop (mode, PLUS,
-                                          tmp, GEN_INT (ct),
-                                          tmp, 1, OPTAB_DIRECT);
+                                          copy_rtx (tmp), GEN_INT (ct),
+                                          copy_rtx (tmp), 1, OPTAB_DIRECT);
            }
 
-         if (tmp != out)
-           emit_move_insn (out, tmp);
+         if (!rtx_equal_p (tmp, out))
+           emit_move_insn (copy_rtx (out), copy_rtx (tmp));
 
          return 1; /* DONE */
        }
 
-      diff = ct - cf;
       if (diff < 0)
        {
          HOST_WIDE_INT tmp;
@@ -8842,8 +9718,10 @@ ix86_expand_int_movcc (operands)
            }
        }
 
+
       if ((diff == 1 || diff == 2 || diff == 4 || diff == 8
           || diff == 3 || diff == 5 || diff == 9)
+         && ((mode != QImode && mode != HImode) || !TARGET_PARTIAL_REG_STALL)
          && (mode != DImode || x86_64_sign_extended_value (GEN_INT (cf))))
        {
          /*
@@ -8867,11 +9745,11 @@ ix86_expand_int_movcc (operands)
          /* On x86_64 the lea instruction operates on Pmode, so we need
             to get arithmetics done in proper mode to match.  */
          if (diff == 1)
-           tmp = out;
+           tmp = copy_rtx (out);
          else
            {
              rtx out1;
-             out1 = out;
+             out1 = copy_rtx (out);
              tmp = gen_rtx_MULT (mode, out1, GEN_INT (diff & ~1));
              nops++;
              if (diff & 1)
@@ -8885,25 +9763,15 @@ ix86_expand_int_movcc (operands)
              tmp = gen_rtx_PLUS (mode, tmp, GEN_INT (cf));
              nops++;
            }
-         if (tmp != out
-             && (GET_CODE (tmp) != SUBREG || SUBREG_REG (tmp) != out))
+         if (!rtx_equal_p (tmp, out))
            {
              if (nops == 1)
-               {
-                 rtx clob;
-
-                 clob = gen_rtx_REG (CCmode, FLAGS_REG);
-                 clob = gen_rtx_CLOBBER (VOIDmode, clob);
-
-                 tmp = gen_rtx_SET (VOIDmode, out, tmp);
-                 tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
-                 emit_insn (tmp);
-               }
+               out = force_operand (tmp, copy_rtx (out));
              else
-               emit_insn (gen_rtx_SET (VOIDmode, out, tmp));
+               emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (out), copy_rtx (tmp)));
            }
-         if (out != operands[0])
-           emit_move_insn (operands[0], out);
+         if (!rtx_equal_p (out, operands[0]))
+           emit_move_insn (operands[0], copy_rtx (out));
 
          return 1; /* DONE */
        }
@@ -8922,12 +9790,10 @@ ix86_expand_int_movcc (operands)
        * This is reasonably steep, but branch mispredict costs are
        * high on modern cpus, so consider failing only if optimizing
        * for space.
-       *
-       * %%% Parameterize branch_cost on the tuning architecture, then
-       * use that.  The 80386 couldn't care less about mispredicts.
        */
 
-      if (!optimize_size && !TARGET_CMOVE)
+      if ((!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
+         && BRANCH_COST >= 2)
        {
          if (cf == 0)
            {
@@ -8981,31 +9847,31 @@ ix86_expand_int_movcc (operands)
              out = emit_store_flag (out, code, ix86_compare_op0,
                                     ix86_compare_op1, VOIDmode, 0, 1);
 
-             out = expand_simple_binop (mode, PLUS, out, constm1_rtx,
-                                        out, 1, OPTAB_DIRECT);
+             out = expand_simple_binop (mode, PLUS, copy_rtx (out), constm1_rtx,
+                                        copy_rtx (out), 1, OPTAB_DIRECT);
            }
 
-         out = expand_simple_binop (mode, AND, out,
+         out = expand_simple_binop (mode, AND, copy_rtx (out),
                                     gen_int_mode (cf - ct, mode),
-                                    out, 1, OPTAB_DIRECT);
+                                    copy_rtx (out), 1, OPTAB_DIRECT);
          if (ct)
-           out = expand_simple_binop (mode, PLUS, out, GEN_INT (ct),
-                                      out, 1, OPTAB_DIRECT);
-         if (out != operands[0])
-           emit_move_insn (operands[0], out);
+           out = expand_simple_binop (mode, PLUS, copy_rtx (out), GEN_INT (ct),
+                                      copy_rtx (out), 1, OPTAB_DIRECT);
+         if (!rtx_equal_p (out, operands[0]))
+           emit_move_insn (operands[0], copy_rtx (out));
 
          return 1; /* DONE */
        }
     }
 
-  if (!TARGET_CMOVE)
+  if (!TARGET_CMOVE || (mode == QImode && TARGET_PARTIAL_REG_STALL))
     {
       /* Try a few things more with specific constants and a variable.  */
 
       optab op;
       rtx var, orig_out, out, tmp;
 
-      if (optimize_size)
+      if (BRANCH_COST <= 2)
        return 0; /* FAIL */
 
       /* If one of the two operands is an interesting constant, load a
@@ -9014,9 +9880,9 @@ ix86_expand_int_movcc (operands)
       if (GET_CODE (operands[2]) == CONST_INT)
        {
          var = operands[3];
-         if (INTVAL (operands[2]) == 0)
+         if (INTVAL (operands[2]) == 0 && operands[3] != constm1_rtx)
            operands[3] = constm1_rtx, op = and_optab;
-         else if (INTVAL (operands[2]) == -1)
+         else if (INTVAL (operands[2]) == -1 && operands[3] != const0_rtx)
            operands[3] = const0_rtx, op = ior_optab;
          else
            return 0; /* FAIL */
@@ -9024,9 +9890,9 @@ ix86_expand_int_movcc (operands)
       else if (GET_CODE (operands[3]) == CONST_INT)
        {
          var = operands[2];
-         if (INTVAL (operands[3]) == 0)
+         if (INTVAL (operands[3]) == 0 && operands[2] != constm1_rtx)
            operands[2] = constm1_rtx, op = and_optab;
-         else if (INTVAL (operands[3]) == -1)
+         else if (INTVAL (operands[3]) == -1 && operands[3] != const0_rtx)
            operands[2] = const0_rtx, op = ior_optab;
          else
            return 0; /* FAIL */
@@ -9045,8 +9911,8 @@ ix86_expand_int_movcc (operands)
       /* Mask in the interesting variable.  */
       out = expand_binop (mode, op, var, tmp, orig_out, 0,
                          OPTAB_WIDEN);
-      if (out != orig_out)
-       emit_move_insn (orig_out, out);
+      if (!rtx_equal_p (out, orig_out))
+       emit_move_insn (copy_rtx (orig_out), copy_rtx (out));
 
       return 1; /* DONE */
     }
@@ -9079,27 +9945,33 @@ ix86_expand_int_movcc (operands)
       emit_move_insn (tmp, operands[2]);
       operands[2] = tmp;
     }
+
   if (! register_operand (operands[2], VOIDmode)
-      && ! register_operand (operands[3], VOIDmode))
+      && (mode == QImode 
+          || ! register_operand (operands[3], VOIDmode)))
     operands[2] = force_reg (mode, operands[2]);
 
+  if (mode == QImode
+      && ! register_operand (operands[3], VOIDmode))
+    operands[3] = force_reg (mode, operands[3]);
+
   emit_insn (compare_seq);
   emit_insn (gen_rtx_SET (VOIDmode, operands[0],
                          gen_rtx_IF_THEN_ELSE (mode,
                                                compare_op, operands[2],
                                                operands[3])));
   if (bypass_test)
-    emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+    emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (operands[0]),
                            gen_rtx_IF_THEN_ELSE (mode,
                                  bypass_test,
-                                 operands[3],
-                                 operands[0])));
+                                 copy_rtx (operands[3]),
+                                 copy_rtx (operands[0]))));
   if (second_test)
-    emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+    emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (operands[0]),
                            gen_rtx_IF_THEN_ELSE (mode,
                                  second_test,
-                                 operands[2],
-                                 operands[0])));
+                                 copy_rtx (operands[2]),
+                                 copy_rtx (operands[0]))));
 
   return 1; /* DONE */
 }
@@ -9140,8 +10012,14 @@ ix86_expand_fp_movcc (operands)
       if (rtx_equal_p (operands[2], op0) && rtx_equal_p (operands[3], op1))
        {
          /* Check for min operation.  */
-         if (code == LT)
+         if (code == LT || code == UNLE)
            {
+              if (code == UNLE)
+               {
+                 rtx tmp = op0;
+                 op0 = op1;
+                 op1 = tmp;
+               }
               operands[0] = force_reg (GET_MODE (operands[0]), operands[0]);
               if (memory_operand (op0, VOIDmode))
                 op0 = force_reg (GET_MODE (operands[0]), op0);
@@ -9152,8 +10030,14 @@ ix86_expand_fp_movcc (operands)
               return 1;
            }
          /* Check for max operation.  */
-         if (code == GT)
+         if (code == GT || code == UNGE)
            {
+              if (code == UNGE)
+               {
+                 rtx tmp = op0;
+                 op0 = op1;
+                 op1 = tmp;
+               }
               operands[0] = force_reg (GET_MODE (operands[0]), operands[0]);
               if (memory_operand (op0, VOIDmode))
                 op0 = force_reg (GET_MODE (operands[0]), op0);
@@ -9178,7 +10062,7 @@ ix86_expand_fp_movcc (operands)
                                        VOIDmode, ix86_compare_op0,
                                        ix86_compare_op1);
        }
-      /* Similary try to manage result to be first operand of conditional
+      /* Similarly try to manage result to be first operand of conditional
         move. We also don't support the NE comparison on SSE, so try to
         avoid it.  */
       if ((rtx_equal_p (operands[0], operands[3])
@@ -9258,6 +10142,92 @@ ix86_expand_fp_movcc (operands)
   return 1;
 }
 
+/* Expand conditional increment or decrement using adb/sbb instructions.
+   The default case using setcc followed by the conditional move can be
+   done by generic code.  */
+int
+ix86_expand_int_addcc (operands)
+     rtx operands[];
+{
+  enum rtx_code code = GET_CODE (operands[1]);
+  rtx compare_op;
+  rtx val = const0_rtx;
+  bool fpcmp = false;
+  rtx pat, clob;
+  enum machine_mode mode = GET_MODE (operands[0]);
+
+  if (operands[3] != const1_rtx
+      && operands[3] != constm1_rtx)
+    return 0;
+  if (!ix86_expand_carry_flag_compare (code, ix86_compare_op0,
+                                      ix86_compare_op1, &compare_op))
+     return 0;
+  code = GET_CODE (compare_op);
+
+  if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode
+      || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode)
+    {
+      fpcmp = true;
+      code = ix86_fp_compare_code_to_integer (code);
+    }
+
+  if (code != LTU)
+    {
+      val = constm1_rtx;
+      if (fpcmp)
+       PUT_CODE (compare_op,
+                 reverse_condition_maybe_unordered
+                   (GET_CODE (compare_op)));
+      else
+       PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op)));
+    }
+  PUT_MODE (compare_op, mode);
+
+  /* Construct either adc or sbb insn.  */
+  if ((code == LTU) == (operands[3] == constm1_rtx))
+    {
+      switch (GET_MODE (operands[0]))
+       {
+         case QImode:
+            emit_insn (gen_subqi3_carry (operands[0], operands[2], val, compare_op));
+           break;
+         case HImode:
+            emit_insn (gen_subhi3_carry (operands[0], operands[2], val, compare_op));
+           break;
+         case SImode:
+            emit_insn (gen_subsi3_carry (operands[0], operands[2], val, compare_op));
+           break;
+         case DImode:
+            emit_insn (gen_subdi3_carry_rex64 (operands[0], operands[2], val, compare_op));
+           break;
+         default:
+           abort ();
+       }
+    }
+  else
+    {
+      switch (GET_MODE (operands[0]))
+       {
+         case QImode:
+            emit_insn (gen_addqi3_carry (operands[0], operands[2], val, compare_op));
+           break;
+         case HImode:
+            emit_insn (gen_addhi3_carry (operands[0], operands[2], val, compare_op));
+           break;
+         case SImode:
+            emit_insn (gen_addsi3_carry (operands[0], operands[2], val, compare_op));
+           break;
+         case DImode:
+            emit_insn (gen_adddi3_carry_rex64 (operands[0], operands[2], val, compare_op));
+           break;
+         default:
+           abort ();
+       }
+    }
+  return 1; /* DONE */
+}
+
+
 /* Split operands 0 and 1 into SImode parts.  Similar to split_di, but
    works for floating pointer parameters and nonoffsetable memories.
    For pushes, it returns just stack offsets; the values will be saved
@@ -9805,7 +10775,6 @@ ix86_expand_movstr (dst, src, count_exp, align_exp)
   unsigned HOST_WIDE_INT count = 0;
   rtx insns;
 
-  start_sequence ();
 
   if (GET_CODE (align_exp) == CONST_INT)
     align = INTVAL (align_exp);
@@ -9815,7 +10784,11 @@ ix86_expand_movstr (dst, src, count_exp, align_exp)
     align = 64;
 
   if (GET_CODE (count_exp) == CONST_INT)
-    count = INTVAL (count_exp);
+    {
+      count = INTVAL (count_exp);
+      if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
+       return 0;
+    }
 
   /* Figure out proper mode for counter.  For 32bits it is always SImode,
      for 64bits use SImode when possible, otherwise DImode.
@@ -9826,6 +10799,8 @@ ix86_expand_movstr (dst, src, count_exp, align_exp)
   else
     counter_mode = DImode;
 
+  start_sequence ();
+
   if (counter_mode != SImode && counter_mode != DImode)
     abort ();
 
@@ -9899,8 +10874,12 @@ ix86_expand_movstr (dst, src, count_exp, align_exp)
 
       /* In case we don't know anything about the alignment, default to
          library version, since it is usually equally fast and result in
-         shorter code.  */
-      if (!TARGET_INLINE_ALL_STRINGOPS && align < UNITS_PER_WORD)
+         shorter code. 
+
+        Also emit call when we know that the count is large and call overhead
+        will not be important.  */
+      if (!TARGET_INLINE_ALL_STRINGOPS
+         && (align < UNITS_PER_WORD || !TARGET_REP_MOVL_OPTIMAL))
        {
          end_sequence ();
          return 0;
@@ -9918,11 +10897,11 @@ ix86_expand_movstr (dst, src, count_exp, align_exp)
          able to predict the branches) and also it is friendlier to the
          hardware branch prediction.
 
-         Using loops is benefical for generic case, because we can
+         Using loops is beneficial for generic case, because we can
          handle small counts using the loops.  Many CPUs (such as Athlon)
          have large REP prefix setup costs.
 
-         This is quite costy.  Maybe we can revisit this decision later or
+         This is quite costly.  Maybe we can revisit this decision later or
          add some customizability to this code.  */
 
       if (count == 0 && align < desired_alignment)
@@ -10039,7 +11018,11 @@ ix86_expand_clrstr (src, count_exp, align_exp)
     align = 32;
 
   if (GET_CODE (count_exp) == CONST_INT)
-    count = INTVAL (count_exp);
+    {
+      count = INTVAL (count_exp);
+      if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
+       return 0;
+    }
   /* Figure out proper mode for counter.  For 32bits it is always SImode,
      for 64bits use SImode when possible, otherwise DImode.
      Set count to number of bytes copied when known at compile time.  */
@@ -10114,8 +11097,12 @@ ix86_expand_clrstr (src, count_exp, align_exp)
 
       /* In case we don't know anything about the alignment, default to
          library version, since it is usually equally fast and result in
-         shorter code.  */
-      if (!TARGET_INLINE_ALL_STRINGOPS && align < UNITS_PER_WORD)
+         shorter code.
+
+        Also emit call when we know that the count is large and call overhead
+        will not be important.  */
+      if (!TARGET_INLINE_ALL_STRINGOPS
+         && (align < UNITS_PER_WORD || !TARGET_REP_MOVL_OPTIMAL))
        return 0;
 
       if (TARGET_SINGLE_STRINGOP)
@@ -10193,7 +11180,7 @@ ix86_expand_clrstr (src, count_exp, align_exp)
                                 gen_rtx_SUBREG (SImode, zeroreg, 0)));
       if (TARGET_64BIT && (align <= 4 || count == 0))
        {
-         rtx label = ix86_expand_aligntest (countreg, 2);
+         rtx label = ix86_expand_aligntest (countreg, 4);
          emit_insn (gen_strsetsi (destreg,
                                   gen_rtx_SUBREG (SImode, zeroreg, 0)));
          emit_label (label);
@@ -10318,6 +11305,7 @@ ix86_expand_strlensi_unroll_1 (out, align_rtx)
   rtx mem;
   rtx tmpreg = gen_reg_rtx (SImode);
   rtx scratch = gen_reg_rtx (SImode);
+  rtx cmp;
 
   align = 0;
   if (GET_CODE (align_rtx) == CONST_INT)
@@ -10476,17 +11464,19 @@ ix86_expand_strlensi_unroll_1 (out, align_rtx)
   /* Avoid branch in fixing the byte.  */
   tmpreg = gen_lowpart (QImode, tmpreg);
   emit_insn (gen_addqi3_cc (tmpreg, tmpreg, tmpreg));
+  cmp = gen_rtx_LTU (Pmode, gen_rtx_REG (CCmode, 17), const0_rtx);
   if (TARGET_64BIT)
-    emit_insn (gen_subdi3_carry_rex64 (out, out, GEN_INT (3)));
+    emit_insn (gen_subdi3_carry_rex64 (out, out, GEN_INT (3), cmp));
   else
-    emit_insn (gen_subsi3_carry (out, out, GEN_INT (3)));
+    emit_insn (gen_subsi3_carry (out, out, GEN_INT (3), cmp));
 
   emit_label (end_0_label);
 }
 
 void
-ix86_expand_call (retval, fnaddr, callarg1, callarg2, pop)
+ix86_expand_call (retval, fnaddr, callarg1, callarg2, pop, sibcall)
      rtx retval, fnaddr, callarg1, callarg2, pop;
+     int sibcall;
 {
   rtx use = NULL, call;
 
@@ -10495,6 +11485,10 @@ ix86_expand_call (retval, fnaddr, callarg1, callarg2, pop)
   if (TARGET_64BIT && pop)
     abort ();
 
+#if TARGET_MACHO
+  if (flag_pic && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
+    fnaddr = machopic_indirect_call_target (fnaddr);
+#else
   /* Static functions and indirect calls don't need the pic register.  */
   if (! TARGET_64BIT && flag_pic
       && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
@@ -10507,12 +11501,22 @@ ix86_expand_call (retval, fnaddr, callarg1, callarg2, pop)
       emit_move_insn (al, callarg2);
       use_reg (&use, al);
     }
+#endif /* TARGET_MACHO */
 
   if (! call_insn_operand (XEXP (fnaddr, 0), Pmode))
     {
       fnaddr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0));
       fnaddr = gen_rtx_MEM (QImode, fnaddr);
     }
+  if (sibcall && TARGET_64BIT
+      && !constant_call_address_operand (XEXP (fnaddr, 0), Pmode))
+    {
+      rtx addr;
+      addr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0));
+      fnaddr = gen_rtx_REG (Pmode, 40);
+      emit_move_insn (fnaddr, addr);
+      fnaddr = gen_rtx_MEM (QImode, fnaddr);
+    }
 
   call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
   if (retval)
@@ -10570,9 +11574,10 @@ ix86_tls_get_addr ()
 
   if (!ix86_tls_symbol)
     {
-      ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, (TARGET_GNU_TLS
-                                          ? "___tls_get_addr"
-                                          : "__tls_get_addr"));
+      ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode,
+                                           (TARGET_GNU_TLS && !TARGET_64BIT)
+                                           ? "___tls_get_addr"
+                                           : "__tls_get_addr");
     }
 
   return ix86_tls_symbol;
@@ -10711,6 +11716,7 @@ ix86_issue_rate ()
     case PROCESSOR_PENTIUMPRO:
     case PROCESSOR_PENTIUM4:
     case PROCESSOR_ATHLON:
+    case PROCESSOR_K8:
       return 3;
 
     default:
@@ -10815,7 +11821,7 @@ ix86_adjust_cost (insn, link, dep_insn, cost)
   rtx set, set2;
   int dep_insn_code_number;
 
-  /* Anti and output depenancies have zero cost on all CPUs.  */
+  /* Anti and output dependencies have zero cost on all CPUs.  */
   if (REG_NOTE_KIND (link) != 0)
     return 0;
 
@@ -10839,7 +11845,7 @@ ix86_adjust_cost (insn, link, dep_insn, cost)
       if (ix86_flags_dependant (insn, dep_insn, insn_type))
        cost = 0;
 
-      /* Floating point stores require value to be ready one cycle ealier.  */
+      /* Floating point stores require value to be ready one cycle earlier.  */
       if (insn_type == TYPE_FMOV
          && get_attr_memory (insn) == MEMORY_STORE
          && !ix86_agi_dependant (insn, dep_insn, insn_type))
@@ -10922,16 +11928,10 @@ ix86_adjust_cost (insn, link, dep_insn, cost)
       break;
 
     case PROCESSOR_ATHLON:
+    case PROCESSOR_K8:
       memory = get_attr_memory (insn);
       dep_memory = get_attr_memory (dep_insn);
 
-      if (dep_memory == MEMORY_LOAD || dep_memory == MEMORY_BOTH)
-       {
-         if (dep_insn_type == TYPE_IMOV || dep_insn_type == TYPE_FMOV)
-           cost += 2;
-         else
-           cost += 3;
-        }
       /* Show ability of reorder buffer to hide latency of load by executing
         in parallel with previous instruction in case
         previous instruction is not needed to compute the address.  */
@@ -11205,7 +12205,7 @@ ix86_variable_issue (dump, sched_verbose, insn, can_issue_more)
 static int
 ia32_use_dfa_pipeline_interface ()
 {
-  if (ix86_cpu == PROCESSOR_PENTIUM)
+  if (TARGET_PENTIUM || TARGET_ATHLON_K8)
     return 1;
   return 0;
 }
@@ -11476,6 +12476,11 @@ x86_initialize_trampoline (tramp, fnaddr, cxt)
       if (offset > TRAMPOLINE_SIZE)
        abort ();
     }
+
+#ifdef TRANSFER_FROM_TRAMPOLINE
+  emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
+                    LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
+#endif
 }
 \f
 #define def_builtin(MASK, NAME, TYPE, CODE)                    \
@@ -11500,30 +12505,30 @@ struct builtin_description
 
 static const struct builtin_description bdesc_comi[] =
 {
-  { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comieq", IX86_BUILTIN_COMIEQSS, EQ, 0 },
-  { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comilt", IX86_BUILTIN_COMILTSS, LT, 0 },
-  { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comile", IX86_BUILTIN_COMILESS, LE, 0 },
-  { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comigt", IX86_BUILTIN_COMIGTSS, LT, 1 },
-  { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comige", IX86_BUILTIN_COMIGESS, LE, 1 },
-  { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comineq", IX86_BUILTIN_COMINEQSS, NE, 0 },
-  { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomieq", IX86_BUILTIN_UCOMIEQSS, EQ, 0 },
-  { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomilt", IX86_BUILTIN_UCOMILTSS, LT, 0 },
-  { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomile", IX86_BUILTIN_UCOMILESS, LE, 0 },
-  { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomigt", IX86_BUILTIN_UCOMIGTSS, LT, 1 },
-  { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomige", IX86_BUILTIN_UCOMIGESS, LE, 1 },
-  { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomineq", IX86_BUILTIN_UCOMINEQSS, NE, 0 },
-  { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdeq", IX86_BUILTIN_COMIEQSD, EQ, 0 },
-  { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdlt", IX86_BUILTIN_COMILTSD, LT, 0 },
-  { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdle", IX86_BUILTIN_COMILESD, LE, 0 },
-  { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdgt", IX86_BUILTIN_COMIGTSD, LT, 1 },
-  { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdge", IX86_BUILTIN_COMIGESD, LE, 1 },
-  { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdneq", IX86_BUILTIN_COMINEQSD, NE, 0 },
-  { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdeq", IX86_BUILTIN_UCOMIEQSD, EQ, 0 },
-  { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdlt", IX86_BUILTIN_UCOMILTSD, LT, 0 },
-  { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdle", IX86_BUILTIN_UCOMILESD, LE, 0 },
-  { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdgt", IX86_BUILTIN_UCOMIGTSD, LT, 1 },
-  { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdge", IX86_BUILTIN_UCOMIGESD, LE, 1 },
-  { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdneq", IX86_BUILTIN_UCOMINEQSD, NE, 0 },
+  { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comieq", IX86_BUILTIN_COMIEQSS, UNEQ, 0 },
+  { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comilt", IX86_BUILTIN_COMILTSS, UNLT, 0 },
+  { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comile", IX86_BUILTIN_COMILESS, UNLE, 0 },
+  { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comigt", IX86_BUILTIN_COMIGTSS, GT, 0 },
+  { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comige", IX86_BUILTIN_COMIGESS, GE, 0 },
+  { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comineq", IX86_BUILTIN_COMINEQSS, LTGT, 0 },
+  { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomieq", IX86_BUILTIN_UCOMIEQSS, UNEQ, 0 },
+  { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomilt", IX86_BUILTIN_UCOMILTSS, UNLT, 0 },
+  { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomile", IX86_BUILTIN_UCOMILESS, UNLE, 0 },
+  { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomigt", IX86_BUILTIN_UCOMIGTSS, GT, 0 },
+  { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomige", IX86_BUILTIN_UCOMIGESS, GE, 0 },
+  { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomineq", IX86_BUILTIN_UCOMINEQSS, LTGT, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdeq", IX86_BUILTIN_COMIEQSD, UNEQ, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdlt", IX86_BUILTIN_COMILTSD, UNLT, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdle", IX86_BUILTIN_COMILESD, UNLE, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdgt", IX86_BUILTIN_COMIGTSD, GT, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdge", IX86_BUILTIN_COMIGESD, GE, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdneq", IX86_BUILTIN_COMINEQSD, LTGT, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdeq", IX86_BUILTIN_UCOMIEQSD, UNEQ, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdlt", IX86_BUILTIN_UCOMILTSD, UNLT, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdle", IX86_BUILTIN_UCOMILESD, UNLE, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdgt", IX86_BUILTIN_UCOMIGTSD, GT, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdge", IX86_BUILTIN_UCOMIGESD, GE, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdneq", IX86_BUILTIN_UCOMINEQSD, LTGT, 0 },
 };
 
 static const struct builtin_description bdesc_2arg[] =
@@ -11553,14 +12558,10 @@ static const struct builtin_description bdesc_2arg[] =
   { MASK_SSE1, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpeqss", IX86_BUILTIN_CMPEQSS, EQ, 0 },
   { MASK_SSE1, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpltss", IX86_BUILTIN_CMPLTSS, LT, 0 },
   { MASK_SSE1, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpless", IX86_BUILTIN_CMPLESS, LE, 0 },
-  { MASK_SSE1, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpgtss", IX86_BUILTIN_CMPGTSS, LT, 1 },
-  { MASK_SSE1, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpgess", IX86_BUILTIN_CMPGESS, LE, 1 },
   { MASK_SSE1, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpunordss", IX86_BUILTIN_CMPUNORDSS, UNORDERED, 0 },
   { MASK_SSE1, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpneqss", IX86_BUILTIN_CMPNEQSS, EQ, 0 },
   { MASK_SSE1, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpnltss", IX86_BUILTIN_CMPNLTSS, LT, 0 },
   { MASK_SSE1, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpnless", IX86_BUILTIN_CMPNLESS, LE, 0 },
-  { MASK_SSE1, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpngtss", IX86_BUILTIN_CMPNGTSS, LT, 1 },
-  { MASK_SSE1, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpngess", IX86_BUILTIN_CMPNGESS, LE, 1 },
   { MASK_SSE1, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpordss", IX86_BUILTIN_CMPORDSS, UNORDERED, 0 },
 
   { MASK_SSE1, CODE_FOR_sminv4sf3, "__builtin_ia32_minps", IX86_BUILTIN_MINPS, 0, 0 },
@@ -11568,6 +12569,11 @@ static const struct builtin_description bdesc_2arg[] =
   { MASK_SSE1, CODE_FOR_vmsminv4sf3, "__builtin_ia32_minss", IX86_BUILTIN_MINSS, 0, 0 },
   { MASK_SSE1, CODE_FOR_vmsmaxv4sf3, "__builtin_ia32_maxss", IX86_BUILTIN_MAXSS, 0, 0 },
 
+  { MASK_SSE1, CODE_FOR_sse_andv4sf3, "__builtin_ia32_andps", IX86_BUILTIN_ANDPS, 0, 0 },
+  { MASK_SSE1, CODE_FOR_sse_nandv4sf3,  "__builtin_ia32_andnps", IX86_BUILTIN_ANDNPS, 0, 0 },
+  { MASK_SSE1, CODE_FOR_sse_iorv4sf3, "__builtin_ia32_orps", IX86_BUILTIN_ORPS, 0, 0 },
+  { MASK_SSE1, CODE_FOR_sse_xorv4sf3,  "__builtin_ia32_xorps", IX86_BUILTIN_XORPS, 0, 0 },
+
   { MASK_SSE1, CODE_FOR_sse_movss,  "__builtin_ia32_movss", IX86_BUILTIN_MOVSS, 0, 0 },
   { MASK_SSE1, CODE_FOR_sse_movhlps,  "__builtin_ia32_movhlps", IX86_BUILTIN_MOVHLPS, 0, 0 },
   { MASK_SSE1, CODE_FOR_sse_movlhps,  "__builtin_ia32_movlhps", IX86_BUILTIN_MOVLHPS, 0, 0 },
@@ -11677,14 +12683,10 @@ static const struct builtin_description bdesc_2arg[] =
   { MASK_SSE2, CODE_FOR_vmmaskcmpv2df3, "__builtin_ia32_cmpeqsd", IX86_BUILTIN_CMPEQSD, EQ, 0 },
   { MASK_SSE2, CODE_FOR_vmmaskcmpv2df3, "__builtin_ia32_cmpltsd", IX86_BUILTIN_CMPLTSD, LT, 0 },
   { MASK_SSE2, CODE_FOR_vmmaskcmpv2df3, "__builtin_ia32_cmplesd", IX86_BUILTIN_CMPLESD, LE, 0 },
-  { MASK_SSE2, CODE_FOR_vmmaskcmpv2df3, "__builtin_ia32_cmpgtsd", IX86_BUILTIN_CMPGTSD, LT, 1 },
-  { MASK_SSE2, CODE_FOR_vmmaskcmpv2df3, "__builtin_ia32_cmpgesd", IX86_BUILTIN_CMPGESD, LE, 1 },
   { MASK_SSE2, CODE_FOR_vmmaskcmpv2df3, "__builtin_ia32_cmpunordsd", IX86_BUILTIN_CMPUNORDSD, UNORDERED, 0 },
   { MASK_SSE2, CODE_FOR_vmmaskncmpv2df3, "__builtin_ia32_cmpneqsd", IX86_BUILTIN_CMPNEQSD, EQ, 0 },
   { MASK_SSE2, CODE_FOR_vmmaskncmpv2df3, "__builtin_ia32_cmpnltsd", IX86_BUILTIN_CMPNLTSD, LT, 0 },
   { MASK_SSE2, CODE_FOR_vmmaskncmpv2df3, "__builtin_ia32_cmpnlesd", IX86_BUILTIN_CMPNLESD, LE, 0 },
-  { MASK_SSE2, CODE_FOR_vmmaskncmpv2df3, "__builtin_ia32_cmpngtsd", IX86_BUILTIN_CMPNGTSD, LT, 1 },
-  { MASK_SSE2, CODE_FOR_vmmaskncmpv2df3, "__builtin_ia32_cmpngesd", IX86_BUILTIN_CMPNGESD, LE, 1 },
   { MASK_SSE2, CODE_FOR_vmmaskncmpv2df3, "__builtin_ia32_cmpordsd", IX86_BUILTIN_CMPORDSD, UNORDERED, 0 },
 
   { MASK_SSE2, CODE_FOR_sminv2df3, "__builtin_ia32_minpd", IX86_BUILTIN_MINPD, 0, 0 },
@@ -11692,10 +12694,10 @@ static const struct builtin_description bdesc_2arg[] =
   { MASK_SSE2, CODE_FOR_vmsminv2df3, "__builtin_ia32_minsd", IX86_BUILTIN_MINSD, 0, 0 },
   { MASK_SSE2, CODE_FOR_vmsmaxv2df3, "__builtin_ia32_maxsd", IX86_BUILTIN_MAXSD, 0, 0 },
 
-  { MASK_SSE2, CODE_FOR_sse2_anddf3, "__builtin_ia32_andpd", IX86_BUILTIN_ANDPD, 0, 0 },
-  { MASK_SSE2, CODE_FOR_sse2_nanddf3,  "__builtin_ia32_andnpd", IX86_BUILTIN_ANDNPD, 0, 0 },
-  { MASK_SSE2, CODE_FOR_sse2_iordf3, "__builtin_ia32_orpd", IX86_BUILTIN_ORPD, 0, 0 },
-  { MASK_SSE2, CODE_FOR_sse2_xordf3,  "__builtin_ia32_xorpd", IX86_BUILTIN_XORPD, 0, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_andv2df3, "__builtin_ia32_andpd", IX86_BUILTIN_ANDPD, 0, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_nandv2df3,  "__builtin_ia32_andnpd", IX86_BUILTIN_ANDNPD, 0, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_iorv2df3, "__builtin_ia32_orpd", IX86_BUILTIN_ORPD, 0, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_xorv2df3,  "__builtin_ia32_xorpd", IX86_BUILTIN_XORPD, 0, 0 },
 
   { MASK_SSE2, CODE_FOR_sse2_movsd,  "__builtin_ia32_movsd", IX86_BUILTIN_MOVSD, 0, 0 },
   { MASK_SSE2, CODE_FOR_sse2_unpckhpd, "__builtin_ia32_unpckhpd", IX86_BUILTIN_UNPCKHPD, 0, 0 },
@@ -11748,9 +12750,11 @@ static const struct builtin_description bdesc_2arg[] =
   { MASK_SSE2, CODE_FOR_sse2_punpckhbw, "__builtin_ia32_punpckhbw128", IX86_BUILTIN_PUNPCKHBW128, 0, 0 },
   { MASK_SSE2, CODE_FOR_sse2_punpckhwd, "__builtin_ia32_punpckhwd128", IX86_BUILTIN_PUNPCKHWD128, 0, 0 },
   { MASK_SSE2, CODE_FOR_sse2_punpckhdq, "__builtin_ia32_punpckhdq128", IX86_BUILTIN_PUNPCKHDQ128, 0, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_punpckhqdq, "__builtin_ia32_punpckhqdq128", IX86_BUILTIN_PUNPCKHQDQ128, 0, 0 },
   { MASK_SSE2, CODE_FOR_sse2_punpcklbw, "__builtin_ia32_punpcklbw128", IX86_BUILTIN_PUNPCKLBW128, 0, 0 },
   { MASK_SSE2, CODE_FOR_sse2_punpcklwd, "__builtin_ia32_punpcklwd128", IX86_BUILTIN_PUNPCKLWD128, 0, 0 },
   { MASK_SSE2, CODE_FOR_sse2_punpckldq, "__builtin_ia32_punpckldq128", IX86_BUILTIN_PUNPCKLDQ128, 0, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_punpcklqdq, "__builtin_ia32_punpcklqdq128", IX86_BUILTIN_PUNPCKLQDQ128, 0, 0 },
 
   { MASK_SSE2, CODE_FOR_sse2_packsswb, "__builtin_ia32_packsswb128", IX86_BUILTIN_PACKSSWB128, 0, 0 },
   { MASK_SSE2, CODE_FOR_sse2_packssdw, "__builtin_ia32_packssdw128", IX86_BUILTIN_PACKSSDW128, 0, 0 },
@@ -11802,6 +12806,7 @@ static const struct builtin_description bdesc_1arg[] =
   { MASK_SSE2, CODE_FOR_sse2_pmovmskb, 0, IX86_BUILTIN_PMOVMSKB128, 0, 0 },
   { MASK_SSE2, CODE_FOR_sse2_movmskpd, 0, IX86_BUILTIN_MOVMSKPD, 0, 0 },
   { MASK_SSE2, CODE_FOR_sse2_movq2dq, 0, IX86_BUILTIN_MOVQ2DQ, 0, 0 },
+  { MASK_SSE2, CODE_FOR_sse2_movdq2q, 0, IX86_BUILTIN_MOVDQ2Q, 0, 0 },
 
   { MASK_SSE2, CODE_FOR_sqrtv2df2, 0, IX86_BUILTIN_SQRTPD, 0, 0 },
 
@@ -11821,7 +12826,9 @@ static const struct builtin_description bdesc_1arg[] =
 
   { MASK_SSE2, CODE_FOR_cvtps2dq, 0, IX86_BUILTIN_CVTPS2DQ, 0, 0 },
   { MASK_SSE2, CODE_FOR_cvtps2pd, 0, IX86_BUILTIN_CVTPS2PD, 0, 0 },
-  { MASK_SSE2, CODE_FOR_cvttps2dq, 0, IX86_BUILTIN_CVTTPS2DQ, 0, 0 }
+  { MASK_SSE2, CODE_FOR_cvttps2dq, 0, IX86_BUILTIN_CVTTPS2DQ, 0, 0 },
+
+  { MASK_SSE2, CODE_FOR_sse2_movq, 0, IX86_BUILTIN_MOVQ, 0, 0 }
 };
 
 void
@@ -11841,7 +12848,11 @@ ix86_init_mmx_sse_builtins ()
   size_t i;
 
   tree pchar_type_node = build_pointer_type (char_type_node);
+  tree pcchar_type_node = build_pointer_type (
+                            build_type_variant (char_type_node, 1, 0));
   tree pfloat_type_node = build_pointer_type (float_type_node);
+  tree pcfloat_type_node = build_pointer_type (
+                            build_type_variant (float_type_node, 1, 0));
   tree pv2si_type_node = build_pointer_type (V2SI_type_node);
   tree pv2di_type_node = build_pointer_type (V2DI_type_node);
   tree pdi_type_node = build_pointer_type (long_long_unsigned_type_node);
@@ -11914,15 +12925,15 @@ ix86_init_mmx_sse_builtins ()
     = build_function_type_list (void_type_node,
                                V8QI_type_node, V8QI_type_node,
                                pchar_type_node, NULL_TREE);
-  tree v4sf_ftype_pfloat
-    = build_function_type_list (V4SF_type_node, pfloat_type_node, NULL_TREE);
+  tree v4sf_ftype_pcfloat
+    = build_function_type_list (V4SF_type_node, pcfloat_type_node, NULL_TREE);
   /* @@@ the type is bogus */
   tree v4sf_ftype_v4sf_pv2si
     = build_function_type_list (V4SF_type_node,
-                               V4SF_type_node, pv2di_type_node, NULL_TREE);
+                               V4SF_type_node, pv2si_type_node, NULL_TREE);
   tree void_ftype_pv2si_v4sf
     = build_function_type_list (void_type_node,
-                               pv2di_type_node, V4SF_type_node, NULL_TREE);
+                               pv2si_type_node, V4SF_type_node, NULL_TREE);
   tree void_ftype_pfloat_v4sf
     = build_function_type_list (void_type_node,
                                pfloat_type_node, V4SF_type_node, NULL_TREE);
@@ -11970,21 +12981,30 @@ ix86_init_mmx_sse_builtins ()
     = build_function_type_list (V2SI_type_node,
                                V2SF_type_node, V2SF_type_node, NULL_TREE);
   tree pint_type_node    = build_pointer_type (integer_type_node);
+  tree pcint_type_node = build_pointer_type (
+                            build_type_variant (integer_type_node, 1, 0));
   tree pdouble_type_node = build_pointer_type (double_type_node);
+  tree pcdouble_type_node = build_pointer_type (
+                               build_type_variant (double_type_node, 1, 0));
   tree int_ftype_v2df_v2df
     = build_function_type_list (integer_type_node,
                                V2DF_type_node, V2DF_type_node, NULL_TREE);
 
   tree ti_ftype_void
     = build_function_type (intTI_type_node, void_list_node);
+  tree v2di_ftype_void
+    = build_function_type (V2DI_type_node, void_list_node);
   tree ti_ftype_ti_ti
     = build_function_type_list (intTI_type_node,
                                intTI_type_node, intTI_type_node, NULL_TREE);
-  tree void_ftype_pvoid
-    = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
+  tree void_ftype_pcvoid
+    = build_function_type_list (void_type_node, const_ptr_type_node, NULL_TREE);
   tree v2di_ftype_di
     = build_function_type_list (V2DI_type_node,
                                long_long_unsigned_type_node, NULL_TREE);
+  tree di_ftype_v2di
+    = build_function_type_list (long_long_unsigned_type_node,
+                               V2DI_type_node, NULL_TREE);
   tree v4sf_ftype_v4si
     = build_function_type_list (V4SF_type_node, V4SI_type_node, NULL_TREE);
   tree v4si_ftype_v4sf
@@ -12033,8 +13053,8 @@ ix86_init_mmx_sse_builtins ()
     = build_function_type_list (void_type_node,
                                V16QI_type_node, V16QI_type_node,
                                pchar_type_node, NULL_TREE);
-  tree v2df_ftype_pdouble
-    = build_function_type_list (V2DF_type_node, pdouble_type_node, NULL_TREE);
+  tree v2df_ftype_pcdouble
+    = build_function_type_list (V2DF_type_node, pcdouble_type_node, NULL_TREE);
   tree v2df_ftype_v2df_v2df
     = build_function_type_list (V2DF_type_node,
                                V2DF_type_node, V2DF_type_node, NULL_TREE);
@@ -12093,6 +13113,18 @@ ix86_init_mmx_sse_builtins ()
                                V16QI_type_node, V16QI_type_node, NULL_TREE);
   tree int_ftype_v16qi
     = build_function_type_list (integer_type_node, V16QI_type_node, NULL_TREE);
+  tree v16qi_ftype_pcchar
+    = build_function_type_list (V16QI_type_node, pcchar_type_node, NULL_TREE);
+  tree void_ftype_pchar_v16qi
+    = build_function_type_list (void_type_node,
+                               pchar_type_node, V16QI_type_node, NULL_TREE);
+  tree v4si_ftype_pcint
+    = build_function_type_list (V4SI_type_node, pcint_type_node, NULL_TREE);
+  tree void_ftype_pcint_v4si
+    = build_function_type_list (void_type_node,
+                               pcint_type_node, V4SI_type_node, NULL_TREE);
+  tree v2di_ftype_v2di
+    = build_function_type_list (V2DI_type_node, V2DI_type_node, NULL_TREE);
 
   /* Add all builtins that are more or less simple operations on two
      operands.  */
@@ -12166,8 +13198,6 @@ ix86_init_mmx_sse_builtins ()
   /* Add the remaining MMX insns with somewhat more complicated types.  */
   def_builtin (MASK_MMX, "__builtin_ia32_mmx_zero", di_ftype_void, IX86_BUILTIN_MMX_ZERO);
   def_builtin (MASK_MMX, "__builtin_ia32_emms", void_ftype_void, IX86_BUILTIN_EMMS);
-  def_builtin (MASK_MMX, "__builtin_ia32_ldmxcsr", void_ftype_unsigned, IX86_BUILTIN_LDMXCSR);
-  def_builtin (MASK_MMX, "__builtin_ia32_stmxcsr", unsigned_ftype_void, IX86_BUILTIN_STMXCSR);
   def_builtin (MASK_MMX, "__builtin_ia32_psllw", v4hi_ftype_v4hi_di, IX86_BUILTIN_PSLLW);
   def_builtin (MASK_MMX, "__builtin_ia32_pslld", v2si_ftype_v2si_di, IX86_BUILTIN_PSLLD);
   def_builtin (MASK_MMX, "__builtin_ia32_psllq", di_ftype_di_di, IX86_BUILTIN_PSLLQ);
@@ -12193,6 +13223,8 @@ ix86_init_mmx_sse_builtins ()
   def_builtin (MASK_MMX, "__builtin_ia32_packssdw", v4hi_ftype_v2si_v2si, IX86_BUILTIN_PACKSSDW);
   def_builtin (MASK_MMX, "__builtin_ia32_packuswb", v8qi_ftype_v4hi_v4hi, IX86_BUILTIN_PACKUSWB);
 
+  def_builtin (MASK_SSE1, "__builtin_ia32_ldmxcsr", void_ftype_unsigned, IX86_BUILTIN_LDMXCSR);
+  def_builtin (MASK_SSE1, "__builtin_ia32_stmxcsr", unsigned_ftype_void, IX86_BUILTIN_STMXCSR);
   def_builtin (MASK_SSE1, "__builtin_ia32_cvtpi2ps", v4sf_ftype_v4sf_v2si, IX86_BUILTIN_CVTPI2PS);
   def_builtin (MASK_SSE1, "__builtin_ia32_cvtps2pi", v2si_ftype_v4sf, IX86_BUILTIN_CVTPS2PI);
   def_builtin (MASK_SSE1, "__builtin_ia32_cvtsi2ss", v4sf_ftype_v4sf_int, IX86_BUILTIN_CVTSI2SS);
@@ -12200,19 +13232,14 @@ ix86_init_mmx_sse_builtins ()
   def_builtin (MASK_SSE1, "__builtin_ia32_cvttps2pi", v2si_ftype_v4sf, IX86_BUILTIN_CVTTPS2PI);
   def_builtin (MASK_SSE1, "__builtin_ia32_cvttss2si", int_ftype_v4sf, IX86_BUILTIN_CVTTSS2SI);
 
-  def_builtin (MASK_SSE1, "__builtin_ia32_andps", v4sf_ftype_v4sf_v4sf, IX86_BUILTIN_ANDPS);
-  def_builtin (MASK_SSE1, "__builtin_ia32_andnps", v4sf_ftype_v4sf_v4sf, IX86_BUILTIN_ANDNPS);
-  def_builtin (MASK_SSE1, "__builtin_ia32_orps", v4sf_ftype_v4sf_v4sf, IX86_BUILTIN_ORPS);
-  def_builtin (MASK_SSE1, "__builtin_ia32_xorps", v4sf_ftype_v4sf_v4sf, IX86_BUILTIN_XORPS);
-
   def_builtin (MASK_SSE1 | MASK_3DNOW_A, "__builtin_ia32_pextrw", int_ftype_v4hi_int, IX86_BUILTIN_PEXTRW);
   def_builtin (MASK_SSE1 | MASK_3DNOW_A, "__builtin_ia32_pinsrw", v4hi_ftype_v4hi_int_int, IX86_BUILTIN_PINSRW);
 
   def_builtin (MASK_SSE1 | MASK_3DNOW_A, "__builtin_ia32_maskmovq", void_ftype_v8qi_v8qi_pchar, IX86_BUILTIN_MASKMOVQ);
 
-  def_builtin (MASK_SSE1, "__builtin_ia32_loadaps", v4sf_ftype_pfloat, IX86_BUILTIN_LOADAPS);
-  def_builtin (MASK_SSE1, "__builtin_ia32_loadups", v4sf_ftype_pfloat, IX86_BUILTIN_LOADUPS);
-  def_builtin (MASK_SSE1, "__builtin_ia32_loadss", v4sf_ftype_pfloat, IX86_BUILTIN_LOADSS);
+  def_builtin (MASK_SSE1, "__builtin_ia32_loadaps", v4sf_ftype_pcfloat, IX86_BUILTIN_LOADAPS);
+  def_builtin (MASK_SSE1, "__builtin_ia32_loadups", v4sf_ftype_pcfloat, IX86_BUILTIN_LOADUPS);
+  def_builtin (MASK_SSE1, "__builtin_ia32_loadss", v4sf_ftype_pcfloat, IX86_BUILTIN_LOADSS);
   def_builtin (MASK_SSE1, "__builtin_ia32_storeaps", void_ftype_pfloat_v4sf, IX86_BUILTIN_STOREAPS);
   def_builtin (MASK_SSE1, "__builtin_ia32_storeups", void_ftype_pfloat_v4sf, IX86_BUILTIN_STOREUPS);
   def_builtin (MASK_SSE1, "__builtin_ia32_storess", void_ftype_pfloat_v4sf, IX86_BUILTIN_STORESS);
@@ -12278,10 +13305,11 @@ ix86_init_mmx_sse_builtins ()
 
   def_builtin (MASK_SSE2, "__builtin_ia32_maskmovdqu", void_ftype_v16qi_v16qi_pchar, IX86_BUILTIN_MASKMOVDQU);
   def_builtin (MASK_SSE2, "__builtin_ia32_movq2dq", v2di_ftype_di, IX86_BUILTIN_MOVQ2DQ);
+  def_builtin (MASK_SSE2, "__builtin_ia32_movdq2q", di_ftype_v2di, IX86_BUILTIN_MOVDQ2Q);
 
-  def_builtin (MASK_SSE2, "__builtin_ia32_loadapd", v2df_ftype_pdouble, IX86_BUILTIN_LOADAPD);
-  def_builtin (MASK_SSE2, "__builtin_ia32_loadupd", v2df_ftype_pdouble, IX86_BUILTIN_LOADUPD);
-  def_builtin (MASK_SSE2, "__builtin_ia32_loadsd", v2df_ftype_pdouble, IX86_BUILTIN_LOADSD);
+  def_builtin (MASK_SSE2, "__builtin_ia32_loadapd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADAPD);
+  def_builtin (MASK_SSE2, "__builtin_ia32_loadupd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADUPD);
+  def_builtin (MASK_SSE2, "__builtin_ia32_loadsd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADSD);
   def_builtin (MASK_SSE2, "__builtin_ia32_storeapd", void_ftype_pdouble_v2df, IX86_BUILTIN_STOREAPD);
   def_builtin (MASK_SSE2, "__builtin_ia32_storeupd", void_ftype_pdouble_v2df, IX86_BUILTIN_STOREUPD);
   def_builtin (MASK_SSE2, "__builtin_ia32_storesd", void_ftype_pdouble_v2df, IX86_BUILTIN_STORESD);
@@ -12332,15 +13360,25 @@ ix86_init_mmx_sse_builtins ()
   def_builtin (MASK_SSE2, "__builtin_ia32_setpd1", v2df_ftype_double, IX86_BUILTIN_SETPD1);
   def_builtin (MASK_SSE2, "__builtin_ia32_setpd", v2df_ftype_double_double, IX86_BUILTIN_SETPD);
   def_builtin (MASK_SSE2, "__builtin_ia32_setzeropd", ti_ftype_void, IX86_BUILTIN_CLRPD);
-  def_builtin (MASK_SSE2, "__builtin_ia32_loadpd1", v2df_ftype_pdouble, IX86_BUILTIN_LOADPD1);
-  def_builtin (MASK_SSE2, "__builtin_ia32_loadrpd", v2df_ftype_pdouble, IX86_BUILTIN_LOADRPD);
+  def_builtin (MASK_SSE2, "__builtin_ia32_loadpd1", v2df_ftype_pcdouble, IX86_BUILTIN_LOADPD1);
+  def_builtin (MASK_SSE2, "__builtin_ia32_loadrpd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADRPD);
   def_builtin (MASK_SSE2, "__builtin_ia32_storepd1", void_ftype_pdouble_v2df, IX86_BUILTIN_STOREPD1);
   def_builtin (MASK_SSE2, "__builtin_ia32_storerpd", void_ftype_pdouble_v2df, IX86_BUILTIN_STORERPD);
 
-  def_builtin (MASK_SSE2, "__builtin_ia32_clflush", void_ftype_pvoid, IX86_BUILTIN_CLFLUSH);
+  def_builtin (MASK_SSE2, "__builtin_ia32_clflush", void_ftype_pcvoid, IX86_BUILTIN_CLFLUSH);
   def_builtin (MASK_SSE2, "__builtin_ia32_lfence", void_ftype_void, IX86_BUILTIN_LFENCE);
   def_builtin (MASK_SSE2, "__builtin_ia32_mfence", void_ftype_void, IX86_BUILTIN_MFENCE);
 
+  def_builtin (MASK_SSE2, "__builtin_ia32_loaddqa", v16qi_ftype_pcchar, IX86_BUILTIN_LOADDQA);
+  def_builtin (MASK_SSE2, "__builtin_ia32_loaddqu", v16qi_ftype_pcchar, IX86_BUILTIN_LOADDQU);
+  def_builtin (MASK_SSE2, "__builtin_ia32_loadd", v4si_ftype_pcint, IX86_BUILTIN_LOADD);
+  def_builtin (MASK_SSE2, "__builtin_ia32_storedqa", void_ftype_pchar_v16qi, IX86_BUILTIN_STOREDQA);
+  def_builtin (MASK_SSE2, "__builtin_ia32_storedqu", void_ftype_pchar_v16qi, IX86_BUILTIN_STOREDQU);
+  def_builtin (MASK_SSE2, "__builtin_ia32_stored", void_ftype_pcint_v4si, IX86_BUILTIN_STORED);
+  def_builtin (MASK_SSE2, "__builtin_ia32_movq", v2di_ftype_v2di, IX86_BUILTIN_MOVQ);
+
+  def_builtin (MASK_SSE1, "__builtin_ia32_setzero128", v2di_ftype_void, IX86_BUILTIN_CLRTI);
+
   def_builtin (MASK_SSE2, "__builtin_ia32_psllw128", v8hi_ftype_v8hi_v2di, IX86_BUILTIN_PSLLW128);
   def_builtin (MASK_SSE2, "__builtin_ia32_pslld128", v4si_ftype_v4si_v2di, IX86_BUILTIN_PSLLD128);
   def_builtin (MASK_SSE2, "__builtin_ia32_psllq128", v2di_ftype_v2di_v2di, IX86_BUILTIN_PSLLQ128);
@@ -12352,10 +13390,12 @@ ix86_init_mmx_sse_builtins ()
   def_builtin (MASK_SSE2, "__builtin_ia32_psraw128", v8hi_ftype_v8hi_v2di, IX86_BUILTIN_PSRAW128);
   def_builtin (MASK_SSE2, "__builtin_ia32_psrad128", v4si_ftype_v4si_v2di, IX86_BUILTIN_PSRAD128);
 
+  def_builtin (MASK_SSE2, "__builtin_ia32_pslldqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSLLDQI128);
   def_builtin (MASK_SSE2, "__builtin_ia32_psllwi128", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSLLWI128);
   def_builtin (MASK_SSE2, "__builtin_ia32_pslldi128", v4si_ftype_v4si_int, IX86_BUILTIN_PSLLDI128);
   def_builtin (MASK_SSE2, "__builtin_ia32_psllqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSLLQI128);
 
+  def_builtin (MASK_SSE2, "__builtin_ia32_psrldqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSRLDQI128);
   def_builtin (MASK_SSE2, "__builtin_ia32_psrlwi128", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSRLWI128);
   def_builtin (MASK_SSE2, "__builtin_ia32_psrldi128", v4si_ftype_v4si_int, IX86_BUILTIN_PSRLDI128);
   def_builtin (MASK_SSE2, "__builtin_ia32_psrlqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSRLQI128);
@@ -12383,7 +13423,8 @@ safe_vector_operand (x, mode)
                              : gen_rtx_SUBREG (DImode, x, 0)));
   else
     emit_insn (gen_sse_clrv4sf (mode == V4SFmode ? x
-                               : gen_rtx_SUBREG (V4SFmode, x, 0)));
+                               : gen_rtx_SUBREG (V4SFmode, x, 0),
+                               CONST0_RTX (V4SFmode)));
   return x;
 }
 
@@ -12437,45 +13478,6 @@ ix86_expand_binop_builtin (icode, arglist, target)
   return target;
 }
 
-/* In type_for_mode we restrict the ability to create TImode types
-   to hosts with 64-bit H_W_I.  So we've defined the SSE logicals
-   to have a V4SFmode signature.  Convert them in-place to TImode.  */
-
-static rtx
-ix86_expand_timode_binop_builtin (icode, arglist, target)
-     enum insn_code icode;
-     tree arglist;
-     rtx target;
-{
-  rtx pat;
-  tree arg0 = TREE_VALUE (arglist);
-  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
-  rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
-  rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
-
-  op0 = gen_lowpart (TImode, op0);
-  op1 = gen_lowpart (TImode, op1);
-  target = gen_reg_rtx (TImode);
-
-  if (! (*insn_data[icode].operand[1].predicate) (op0, TImode))
-    op0 = copy_to_mode_reg (TImode, op0);
-  if (! (*insn_data[icode].operand[2].predicate) (op1, TImode))
-    op1 = copy_to_mode_reg (TImode, op1);
-
-  /* In the commutative cases, both op0 and op1 are nonimmediate_operand,
-     yet one of the two must not be a memory.  This is normally enforced
-     by expanders, but we didn't bother to create one here.  */
-  if (GET_CODE (op0) == MEM && GET_CODE (op1) == MEM)
-    op0 = copy_to_mode_reg (TImode, op0);
-
-  pat = GEN_FCN (icode) (target, op0, op1);
-  if (! pat)
-    return 0;
-  emit_insn (pat);
-
-  return gen_lowpart (V4SFmode, target);
-}
-
 /* Subroutine of ix86_expand_builtin to take care of stores.  */
 
 static rtx
@@ -12673,14 +13675,14 @@ ix86_expand_sse_comi (d, arglist, target)
     op1 = copy_to_mode_reg (mode1, op1);
 
   op2 = gen_rtx_fmt_ee (comparison, mode0, op0, op1);
-  pat = GEN_FCN (d->icode) (op0, op1, op2);
+  pat = GEN_FCN (d->icode) (op0, op1);
   if (! pat)
     return 0;
   emit_insn (pat);
   emit_insn (gen_rtx_SET (VOIDmode,
                          gen_rtx_STRICT_LOW_PART (VOIDmode, target),
                          gen_rtx_fmt_ee (comparison, QImode,
-                                         gen_rtx_REG (CCmode, FLAGS_REG),
+                                         SET_DEST (pat),
                                          const0_rtx)));
 
   return SUBREG_REG (target);
@@ -12788,9 +13790,11 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
       return target;
 
     case IX86_BUILTIN_MASKMOVQ:
+    case IX86_BUILTIN_MASKMOVDQU:
       icode = (fcode == IX86_BUILTIN_MASKMOVQ
               ? (TARGET_64BIT ? CODE_FOR_mmx_maskmovq_rex : CODE_FOR_mmx_maskmovq)
-              : CODE_FOR_sse2_maskmovdqu);
+              : (TARGET_64BIT ? CODE_FOR_sse2_maskmovdqu_rex64
+                 : CODE_FOR_sse2_maskmovdqu));
       /* Note the arg order is different from the operand order.  */
       arg1 = TREE_VALUE (arglist);
       arg2 = TREE_VALUE (TREE_CHAIN (arglist));
@@ -12821,19 +13825,6 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
     case IX86_BUILTIN_RCPSS:
       return ix86_expand_unop1_builtin (CODE_FOR_vmrcpv4sf2, arglist, target);
 
-    case IX86_BUILTIN_ANDPS:
-      return ix86_expand_timode_binop_builtin (CODE_FOR_sse_andti3,
-                                              arglist, target);
-    case IX86_BUILTIN_ANDNPS:
-      return ix86_expand_timode_binop_builtin (CODE_FOR_sse_nandti3,
-                                              arglist, target);
-    case IX86_BUILTIN_ORPS:
-      return ix86_expand_timode_binop_builtin (CODE_FOR_sse_iorti3,
-                                              arglist, target);
-    case IX86_BUILTIN_XORPS:
-      return ix86_expand_timode_binop_builtin (CODE_FOR_sse_xorti3,
-                                              arglist, target);
-
     case IX86_BUILTIN_LOADAPS:
       return ix86_expand_unop_builtin (CODE_FOR_sse_movaps, arglist, target, 1);
 
@@ -12842,6 +13833,7 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
 
     case IX86_BUILTIN_STOREAPS:
       return ix86_expand_store_builtin (CODE_FOR_sse_movaps, arglist);
+
     case IX86_BUILTIN_STOREUPS:
       return ix86_expand_store_builtin (CODE_FOR_sse_movups, arglist);
 
@@ -12992,6 +13984,35 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
       emit_insn (pat);
       return target;
 
+    case IX86_BUILTIN_PSLLDQI128:
+    case IX86_BUILTIN_PSRLDQI128:
+      icode = (  fcode == IX86_BUILTIN_PSLLDQI128 ? CODE_FOR_sse2_ashlti3
+              : CODE_FOR_sse2_lshrti3);
+      arg0 = TREE_VALUE (arglist);
+      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+      op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+      tmode = insn_data[icode].operand[0].mode;
+      mode1 = insn_data[icode].operand[1].mode;
+      mode2 = insn_data[icode].operand[2].mode;
+
+      if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
+       {
+         op0 = copy_to_reg (op0);
+         op0 = simplify_gen_subreg (mode1, op0, GET_MODE (op0), 0);
+       }
+      if (! (*insn_data[icode].operand[2].predicate) (op1, mode2))
+       {
+         error ("shift must be an immediate");
+         return const0_rtx;
+       }
+      target = gen_reg_rtx (V2DImode);
+      pat = GEN_FCN (icode) (simplify_gen_subreg (tmode, target, V2DImode, 0), op0, op1);
+      if (! pat)
+       return 0;
+      emit_insn (pat);
+      return target;
+
     case IX86_BUILTIN_FEMMS:
       emit_insn (gen_femms ());
       return NULL_RTX;
@@ -13073,7 +14094,7 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
 
     case IX86_BUILTIN_SSE_ZERO:
       target = gen_reg_rtx (V4SFmode);
-      emit_insn (gen_sse_clrv4sf (target));
+      emit_insn (gen_sse_clrv4sf (target, CONST0_RTX (V4SFmode)));
       return target;
 
     case IX86_BUILTIN_MMX_ZERO:
@@ -13081,6 +14102,12 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
       emit_insn (gen_mmx_clrdi (target));
       return target;
 
+    case IX86_BUILTIN_CLRTI:
+      target = gen_reg_rtx (V2DImode);
+      emit_insn (gen_sse2_clrti (simplify_gen_subreg (TImode, target, V2DImode, 0)));
+      return target;
+
+
     case IX86_BUILTIN_SQRTSD:
       return ix86_expand_unop1_builtin (CODE_FOR_vmsqrtv2df2, arglist, target);
     case IX86_BUILTIN_LOADAPD:
@@ -13138,6 +14165,11 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
     case IX86_BUILTIN_STORERPD:
       return ix86_expand_store_builtin (CODE_FOR_sse2_movapd, arglist);
 
+    case IX86_BUILTIN_CLRPD:
+      target = gen_reg_rtx (V2DFmode);
+      emit_insn (gen_sse_clrv2df (target));
+      return target;
+
     case IX86_BUILTIN_MFENCE:
        emit_insn (gen_sse2_mfence ());
        return 0;
@@ -13149,9 +14181,8 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
        arg0 = TREE_VALUE (arglist);
        op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
        icode = CODE_FOR_sse2_clflush;
-       mode0 = insn_data[icode].operand[0].mode;
-       if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
-           op0 = copy_to_mode_reg (mode0, op0);
+       if (! (*insn_data[icode].operand[0].predicate) (op0, Pmode))
+           op0 = copy_to_mode_reg (Pmode, op0);
 
        emit_insn (gen_sse2_clflush (op0));
        return 0;
@@ -13163,6 +14194,20 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
     case IX86_BUILTIN_MOVNTI:
       return ix86_expand_store_builtin (CODE_FOR_sse2_movntsi, arglist);
 
+    case IX86_BUILTIN_LOADDQA:
+      return ix86_expand_unop_builtin (CODE_FOR_sse2_movdqa, arglist, target, 1);
+    case IX86_BUILTIN_LOADDQU:
+      return ix86_expand_unop_builtin (CODE_FOR_sse2_movdqu, arglist, target, 1);
+    case IX86_BUILTIN_LOADD:
+      return ix86_expand_unop_builtin (CODE_FOR_sse2_loadd, arglist, target, 1);
+
+    case IX86_BUILTIN_STOREDQA:
+      return ix86_expand_store_builtin (CODE_FOR_sse2_movdqa, arglist);
+    case IX86_BUILTIN_STOREDQU:
+      return ix86_expand_store_builtin (CODE_FOR_sse2_movdqu, arglist);
+    case IX86_BUILTIN_STORED:
+      return ix86_expand_store_builtin (CODE_FOR_sse2_stored, arglist);
+
     default:
       break;
     }
@@ -13310,6 +14355,8 @@ ix86_preferred_reload_class (x, class)
      rtx x;
      enum reg_class class;
 {
+  if (GET_CODE (x) == CONST_VECTOR && x != CONST0_RTX (GET_MODE (x)))
+    return NO_REGS;
   if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
     {
       /* SSE can't load any constant directly yet.  */
@@ -13385,17 +14432,33 @@ ix86_register_move_cost (mode, class1, class2)
      enum reg_class class1, class2;
 {
   /* In case we require secondary memory, compute cost of the store followed
-     by load.  In case of copying from general_purpose_register we may emit
-     multiple stores followed by single load causing memory size mismatch
-     stall.  Count this as arbitarily high cost of 20.  */
+     by load.  In order to avoid bad register allocation choices, we need 
+     for this to be *at least* as high as the symmetric MEMORY_MOVE_COST.  */
+
   if (ix86_secondary_memory_needed (class1, class2, mode, 0))
     {
-      int add_cost = 0;
+      int cost = 1;
+
+      cost += MAX (MEMORY_MOVE_COST (mode, class1, 0),
+                  MEMORY_MOVE_COST (mode, class1, 1));
+      cost += MAX (MEMORY_MOVE_COST (mode, class2, 0),
+                  MEMORY_MOVE_COST (mode, class2, 1));
+      
+      /* In case of copying from general_purpose_register we may emit multiple
+         stores followed by single load causing memory size mismatch stall.
+         Count this as arbitrarily high cost of 20.  */
       if (CLASS_MAX_NREGS (class1, mode) > CLASS_MAX_NREGS (class2, mode))
-         add_cost = 20;
-      return (MEMORY_MOVE_COST (mode, class1, 0)
-             + MEMORY_MOVE_COST (mode, class2, 1) + add_cost);
+       cost += 20;
+
+      /* In the case of FP/MMX moves, the registers actually overlap, and we
+        have to switch modes in order to treat them differently.  */
+      if ((MMX_CLASS_P (class1) && MAYBE_FLOAT_CLASS_P (class2))
+          || (MMX_CLASS_P (class2) && MAYBE_FLOAT_CLASS_P (class1)))
+       cost += 20;
+
+      return cost;
     }
+
   /* Moves between SSE/MMX and integer unit are expensive.  */
   if (MMX_CLASS_P (class1) != MMX_CLASS_P (class2)
       || SSE_CLASS_P (class1) != SSE_CLASS_P (class2))
@@ -13528,15 +14591,267 @@ ix86_memory_move_cost (mode, class, in)
        if (mode == TFmode)
          mode = XFmode;
        return ((in ? ix86_cost->int_load[2] : ix86_cost->int_store[2])
-               * (int) GET_MODE_SIZE (mode) / 4);
+               * ((int) GET_MODE_SIZE (mode)
+                  + UNITS_PER_WORD -1 ) / UNITS_PER_WORD);
     }
 }
 
-#if defined (DO_GLOBAL_CTORS_BODY) && defined (HAS_INIT_SECTION)
-static void
-ix86_svr3_asm_out_constructor (symbol, priority)
-     rtx symbol;
-     int priority ATTRIBUTE_UNUSED;
+/* Compute a (partial) cost for rtx X.  Return true if the complete
+   cost has been computed, and false if subexpressions should be
+   scanned.  In either case, *TOTAL contains the cost result.  */
+
+static bool
+ix86_rtx_costs (x, code, outer_code, total)
+     rtx x;
+     int code, outer_code;
+     int *total;
+{
+  enum machine_mode mode = GET_MODE (x);
+
+  switch (code)
+    {
+    case CONST_INT:
+    case CONST:
+    case LABEL_REF:
+    case SYMBOL_REF:
+      if (TARGET_64BIT && !x86_64_sign_extended_value (x))
+       *total = 3;
+      else if (TARGET_64BIT && !x86_64_zero_extended_value (x))
+       *total = 2;
+      else if (flag_pic && SYMBOLIC_CONST (x))
+       *total = 1;
+      else
+       *total = 0;
+      return true;
+
+    case CONST_DOUBLE:
+      if (mode == VOIDmode)
+       *total = 0;
+      else
+       switch (standard_80387_constant_p (x))
+         {
+         case 1: /* 0.0 */
+           *total = 1;
+           break;
+         case 2: /* 1.0 */
+           *total = 2;
+           break;
+         default:
+           /* Start with (MEM (SYMBOL_REF)), since that's where
+              it'll probably end up.  Add a penalty for size.  */
+           *total = (COSTS_N_INSNS (1)
+                     + (flag_pic != 0)
+                     + (mode == SFmode ? 0 : mode == DFmode ? 1 : 2));
+           break;
+         }
+      return true;
+
+    case ZERO_EXTEND:
+      /* The zero extensions is often completely free on x86_64, so make
+        it as cheap as possible.  */
+      if (TARGET_64BIT && mode == DImode
+         && GET_MODE (XEXP (x, 0)) == SImode)
+       *total = 1;
+      else if (TARGET_ZERO_EXTEND_WITH_AND)
+       *total = COSTS_N_INSNS (ix86_cost->add);
+      else
+       *total = COSTS_N_INSNS (ix86_cost->movzx);
+      return false;
+
+    case SIGN_EXTEND:
+      *total = COSTS_N_INSNS (ix86_cost->movsx);
+      return false;
+
+    case ASHIFT:
+      if (GET_CODE (XEXP (x, 1)) == CONST_INT
+         && (GET_MODE (XEXP (x, 0)) != DImode || TARGET_64BIT))
+       {
+         HOST_WIDE_INT value = INTVAL (XEXP (x, 1));
+         if (value == 1)
+           {
+             *total = COSTS_N_INSNS (ix86_cost->add);
+             return false;
+           }
+         if ((value == 2 || value == 3)
+             && !TARGET_DECOMPOSE_LEA
+             && ix86_cost->lea <= ix86_cost->shift_const)
+           {
+             *total = COSTS_N_INSNS (ix86_cost->lea);
+             return false;
+           }
+       }
+      /* FALLTHRU */
+
+    case ROTATE:
+    case ASHIFTRT:
+    case LSHIFTRT:
+    case ROTATERT:
+      if (!TARGET_64BIT && GET_MODE (XEXP (x, 0)) == DImode)
+       {
+         if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+           {
+             if (INTVAL (XEXP (x, 1)) > 32)
+               *total = COSTS_N_INSNS(ix86_cost->shift_const + 2);
+             else
+               *total = COSTS_N_INSNS(ix86_cost->shift_const * 2);
+           }
+         else
+           {
+             if (GET_CODE (XEXP (x, 1)) == AND)
+               *total = COSTS_N_INSNS(ix86_cost->shift_var * 2);
+             else
+               *total = COSTS_N_INSNS(ix86_cost->shift_var * 6 + 2);
+           }
+       }
+      else
+       {
+         if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+           *total = COSTS_N_INSNS (ix86_cost->shift_const);
+         else
+           *total = COSTS_N_INSNS (ix86_cost->shift_var);
+       }
+      return false;
+
+    case MULT:
+      if (FLOAT_MODE_P (mode))
+       *total = COSTS_N_INSNS (ix86_cost->fmul);
+      else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+       {
+         unsigned HOST_WIDE_INT value = INTVAL (XEXP (x, 1));
+         int nbits;
+
+         for (nbits = 0; value != 0; value >>= 1)
+           nbits++;
+
+         *total = COSTS_N_INSNS (ix86_cost->mult_init[MODE_INDEX (mode)]
+                                 + nbits * ix86_cost->mult_bit);
+       }
+      else
+       {
+         /* This is arbitrary */
+         *total = COSTS_N_INSNS (ix86_cost->mult_init[MODE_INDEX (mode)]
+                                 + 7 * ix86_cost->mult_bit);
+       }
+      return false;
+
+    case DIV:
+    case UDIV:
+    case MOD:
+    case UMOD:
+      if (FLOAT_MODE_P (mode))
+       *total = COSTS_N_INSNS (ix86_cost->fdiv);
+      else
+       *total = COSTS_N_INSNS (ix86_cost->divide[MODE_INDEX (mode)]);
+      return false;
+
+    case PLUS:
+      if (FLOAT_MODE_P (mode))
+       *total = COSTS_N_INSNS (ix86_cost->fadd);
+      else if (!TARGET_DECOMPOSE_LEA
+              && GET_MODE_CLASS (mode) == MODE_INT
+              && GET_MODE_BITSIZE (mode) <= GET_MODE_BITSIZE (Pmode))
+       {
+         if (GET_CODE (XEXP (x, 0)) == PLUS
+             && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
+             && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
+             && CONSTANT_P (XEXP (x, 1)))
+           {
+             HOST_WIDE_INT val = INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1));
+             if (val == 2 || val == 4 || val == 8)
+               {
+                 *total = COSTS_N_INSNS (ix86_cost->lea);
+                 *total += rtx_cost (XEXP (XEXP (x, 0), 1), outer_code);
+                 *total += rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0),
+                                     outer_code);
+                 *total += rtx_cost (XEXP (x, 1), outer_code);
+                 return true;
+               }
+           }
+         else if (GET_CODE (XEXP (x, 0)) == MULT
+                  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
+           {
+             HOST_WIDE_INT val = INTVAL (XEXP (XEXP (x, 0), 1));
+             if (val == 2 || val == 4 || val == 8)
+               {
+                 *total = COSTS_N_INSNS (ix86_cost->lea);
+                 *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
+                 *total += rtx_cost (XEXP (x, 1), outer_code);
+                 return true;
+               }
+           }
+         else if (GET_CODE (XEXP (x, 0)) == PLUS)
+           {
+             *total = COSTS_N_INSNS (ix86_cost->lea);
+             *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
+             *total += rtx_cost (XEXP (XEXP (x, 0), 1), outer_code);
+             *total += rtx_cost (XEXP (x, 1), outer_code);
+             return true;
+           }
+       }
+      /* FALLTHRU */
+
+    case MINUS:
+      if (FLOAT_MODE_P (mode))
+       {
+         *total = COSTS_N_INSNS (ix86_cost->fadd);
+         return false;
+       }
+      /* FALLTHRU */
+
+    case AND:
+    case IOR:
+    case XOR:
+      if (!TARGET_64BIT && mode == DImode)
+       {
+         *total = (COSTS_N_INSNS (ix86_cost->add) * 2
+                   + (rtx_cost (XEXP (x, 0), outer_code)
+                      << (GET_MODE (XEXP (x, 0)) != DImode))
+                   + (rtx_cost (XEXP (x, 1), outer_code)
+                      << (GET_MODE (XEXP (x, 1)) != DImode)));
+         return true;
+       }
+      /* FALLTHRU */
+
+    case NEG:
+      if (FLOAT_MODE_P (mode))
+       {
+         *total = COSTS_N_INSNS (ix86_cost->fchs);
+         return false;
+       }
+      /* FALLTHRU */
+
+    case NOT:
+      if (!TARGET_64BIT && mode == DImode)
+       *total = COSTS_N_INSNS (ix86_cost->add * 2);
+      else
+       *total = COSTS_N_INSNS (ix86_cost->add);
+      return false;
+
+    case FLOAT_EXTEND:
+      if (!TARGET_SSE_MATH || !VALID_SSE_REG_MODE (mode))
+       *total = 0;
+      return false;
+
+    case ABS:
+      if (FLOAT_MODE_P (mode))
+       *total = COSTS_N_INSNS (ix86_cost->fabs);
+      return false;
+
+    case SQRT:
+      if (FLOAT_MODE_P (mode))
+       *total = COSTS_N_INSNS (ix86_cost->fsqrt);
+      return false;
+
+    default:
+      return false;
+    }
+}
+
+#if defined (DO_GLOBAL_CTORS_BODY) && defined (HAS_INIT_SECTION)
+static void
+ix86_svr3_asm_out_constructor (symbol, priority)
+     rtx symbol;
+     int priority ATTRIBUTE_UNUSED;
 {
   init_section ();
   fputs ("\tpushl $", asm_out_file);
@@ -13545,6 +14860,71 @@ ix86_svr3_asm_out_constructor (symbol, priority)
 }
 #endif
 
+#if TARGET_MACHO
+
+static int current_machopic_label_num;
+
+/* Given a symbol name and its associated stub, write out the
+   definition of the stub.  */
+
+void
+machopic_output_stub (file, symb, stub)
+     FILE *file;
+     const char *symb, *stub;
+{
+  unsigned int length;
+  char *binder_name, *symbol_name, lazy_ptr_name[32];
+  int label = ++current_machopic_label_num;
+
+  /* Lose our funky encoding stuff so it doesn't contaminate the stub.  */
+  symb = (*targetm.strip_name_encoding) (symb);
+
+  length = strlen (stub);
+  binder_name = alloca (length + 32);
+  GEN_BINDER_NAME_FOR_STUB (binder_name, stub, length);
+
+  length = strlen (symb);
+  symbol_name = alloca (length + 32);
+  GEN_SYMBOL_NAME_FOR_SYMBOL (symbol_name, symb, length);
+
+  sprintf (lazy_ptr_name, "L%d$lz", label);
+
+  if (MACHOPIC_PURE)
+    machopic_picsymbol_stub_section ();
+  else
+    machopic_symbol_stub_section ();
+
+  fprintf (file, "%s:\n", stub);
+  fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
+
+  if (MACHOPIC_PURE)
+    {
+      fprintf (file, "\tcall LPC$%d\nLPC$%d:\tpopl %%eax\n", label, label);
+      fprintf (file, "\tmovl %s-LPC$%d(%%eax),%%edx\n", lazy_ptr_name, label);
+      fprintf (file, "\tjmp %%edx\n");
+    }
+  else
+    fprintf (file, "\tjmp *%s\n", lazy_ptr_name);
+  
+  fprintf (file, "%s:\n", binder_name);
+  
+  if (MACHOPIC_PURE)
+    {
+      fprintf (file, "\tlea %s-LPC$%d(%%eax),%%eax\n", lazy_ptr_name, label);
+      fprintf (file, "\tpushl %%eax\n");
+    }
+  else
+    fprintf (file, "\t pushl $%s\n", lazy_ptr_name);
+
+  fprintf (file, "\tjmp dyld_stub_binding_helper\n");
+
+  machopic_lazy_symbol_ptr_section ();
+  fprintf (file, "%s:\n", lazy_ptr_name);
+  fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
+  fprintf (file, "\t.long %s\n", binder_name);
+}
+#endif /* TARGET_MACHO */
+
 /* Order the registers for register allocator.  */
 
 void
@@ -13575,7 +14955,7 @@ x86_order_regs_for_local_alloc ()
    for (i = FIRST_REX_SSE_REG; i <= LAST_REX_SSE_REG; i++)
      reg_alloc_order [pos++] = i;
 
-   /* x87 registerts.  */
+   /* x87 registers.  */
    if (TARGET_SSE_MATH)
      for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
        reg_alloc_order [pos++] = i;
@@ -13589,77 +14969,254 @@ x86_order_regs_for_local_alloc ()
      reg_alloc_order [pos++] = 0;
 }
 
-void
-x86_output_mi_thunk (file, delta, function)
-     FILE *file;
-     int delta;
+#ifndef TARGET_USE_MS_BITFIELD_LAYOUT
+#define TARGET_USE_MS_BITFIELD_LAYOUT 0
+#endif
+
+/* Handle a "ms_struct" or "gcc_struct" attribute; arguments as in
+   struct attribute_spec.handler.  */
+static tree
+ix86_handle_struct_attribute (node, name, args, flags, no_add_attrs)
+     tree *node;
+     tree name;
+     tree args ATTRIBUTE_UNUSED;
+     int flags ATTRIBUTE_UNUSED;
+     bool *no_add_attrs;
+{
+  tree *type = NULL;
+  if (DECL_P (*node))
+    {
+      if (TREE_CODE (*node) == TYPE_DECL)
+       type = &TREE_TYPE (*node);
+    }
+  else
+    type = node;
+
+  if (!(type && (TREE_CODE (*type) == RECORD_TYPE
+                || TREE_CODE (*type) == UNION_TYPE)))
+    {
+      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  else if ((is_attribute_p ("ms_struct", name)
+           && lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (*type)))
+          || ((is_attribute_p ("gcc_struct", name)
+               && lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (*type)))))
+    {
+      warning ("`%s' incompatible attribute ignored",
+               IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+static bool
+ix86_ms_bitfield_layout_p (record_type)
+     tree record_type;
+{
+  return (TARGET_USE_MS_BITFIELD_LAYOUT &&
+      !lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (record_type)))
+    || lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (record_type));
+}
+
+/* Returns an expression indicating where the this parameter is
+   located on entry to the FUNCTION.  */
+
+static rtx
+x86_this_parameter (function)
      tree function;
 {
-  tree parm;
-  rtx xops[3];
+  tree type = TREE_TYPE (function);
 
-  if (ix86_regparm > 0)
-    parm = TYPE_ARG_TYPES (TREE_TYPE (function));
+  if (TARGET_64BIT)
+    {
+      int n = aggregate_value_p (TREE_TYPE (type)) != 0;
+      return gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
+    }
+
+  if (ix86_fntype_regparm (type) > 0)
+    {
+      tree parm;
+
+      parm = TYPE_ARG_TYPES (type);
+      /* Figure out whether or not the function has a variable number of
+        arguments.  */
+      for (; parm; parm = TREE_CHAIN (parm))
+       if (TREE_VALUE (parm) == void_type_node)
+         break;
+      /* If not, the this parameter is in %eax.  */
+      if (parm)
+       return gen_rtx_REG (SImode, 0);
+    }
+
+  if (aggregate_value_p (TREE_TYPE (type)))
+    return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
   else
-    parm = NULL_TREE;
-  for (; parm; parm = TREE_CHAIN (parm))
-    if (TREE_VALUE (parm) == void_type_node)
-      break;
+    return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4));
+}
+
+/* Determine whether x86_output_mi_thunk can succeed.  */
 
-  xops[0] = GEN_INT (delta);
+static bool
+x86_can_output_mi_thunk (thunk, delta, vcall_offset, function)
+     tree thunk ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT delta ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT vcall_offset;
+     tree function;
+{
+  /* 64-bit can handle anything.  */
   if (TARGET_64BIT)
+    return true;
+
+  /* For 32-bit, everything's fine if we have one free register.  */
+  if (ix86_fntype_regparm (TREE_TYPE (function)) < 3)
+    return true;
+
+  /* Need a free register for vcall_offset.  */
+  if (vcall_offset)
+    return false;
+
+  /* Need a free register for GOT references.  */
+  if (flag_pic && !(*targetm.binds_local_p) (function))
+    return false;
+
+  /* Otherwise ok.  */
+  return true;
+}
+
+/* Output the assembler code for a thunk function.  THUNK_DECL is the
+   declaration for the thunk function itself, FUNCTION is the decl for
+   the target function.  DELTA is an immediate constant offset to be
+   added to THIS.  If VCALL_OFFSET is nonzero, the word at
+   *(*this + vcall_offset) should be added to THIS.  */
+
+static void
+x86_output_mi_thunk (file, thunk, delta, vcall_offset, function)
+     FILE *file ATTRIBUTE_UNUSED;
+     tree thunk ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset;
+     tree function;
+{
+  rtx xops[3];
+  rtx this = x86_this_parameter (function);
+  rtx this_reg, tmp;
+
+  /* If VCALL_OFFSET, we'll need THIS in a register.  Might as well
+     pull it in now and let DELTA benefit.  */
+  if (REG_P (this))
+    this_reg = this;
+  else if (vcall_offset)
     {
-      int n = aggregate_value_p (TREE_TYPE (TREE_TYPE (function))) != 0;
-      xops[1] = gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
-      output_asm_insn ("add{q} {%0, %1|%1, %0}", xops);
-      if (flag_pic)
+      /* Put the this parameter into %eax.  */
+      xops[0] = this;
+      xops[1] = this_reg = gen_rtx_REG (Pmode, 0);
+      output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
+    }
+  else
+    this_reg = NULL_RTX;
+
+  /* Adjust the this parameter by a fixed constant.  */
+  if (delta)
+    {
+      xops[0] = GEN_INT (delta);
+      xops[1] = this_reg ? this_reg : this;
+      if (TARGET_64BIT)
        {
-         fprintf (file, "\tjmp *");
-         assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
-         fprintf (file, "@GOTPCREL(%%rip)\n");
+         if (!x86_64_general_operand (xops[0], DImode))
+           {
+             tmp = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 2 /* R10 */);
+             xops[1] = tmp;
+             output_asm_insn ("mov{q}\t{%1, %0|%0, %1}", xops);
+             xops[0] = tmp;
+             xops[1] = this;
+           }
+         output_asm_insn ("add{q}\t{%0, %1|%1, %0}", xops);
        }
       else
-       {
-         fprintf (file, "\tjmp ");
-         assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
-         fprintf (file, "\n");
-       }
+       output_asm_insn ("add{l}\t{%0, %1|%1, %0}", xops);
     }
-  else
+
+  /* Adjust the this parameter by a value stored in the vtable.  */
+  if (vcall_offset)
     {
-      if (parm)
-       xops[1] = gen_rtx_REG (SImode, 0);
-      else if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
-       xops[1] = gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
+      if (TARGET_64BIT)
+       tmp = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 2 /* R10 */);
       else
-       xops[1] = gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4));
-      output_asm_insn ("add{l} {%0, %1|%1, %0}", xops);
+       tmp = gen_rtx_REG (SImode, 2 /* ECX */);
 
-      if (flag_pic)
+      xops[0] = gen_rtx_MEM (Pmode, this_reg);
+      xops[1] = tmp;
+      if (TARGET_64BIT)
+       output_asm_insn ("mov{q}\t{%0, %1|%1, %0}", xops);
+      else
+       output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
+
+      /* Adjust the this parameter.  */
+      xops[0] = gen_rtx_MEM (Pmode, plus_constant (tmp, vcall_offset));
+      if (TARGET_64BIT && !memory_operand (xops[0], Pmode))
        {
-         xops[0] = pic_offset_table_rtx;
-         xops[1] = gen_label_rtx ();
-         xops[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+         rtx tmp2 = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 3 /* R11 */);
+         xops[0] = GEN_INT (vcall_offset);
+         xops[1] = tmp2;
+         output_asm_insn ("mov{q}\t{%0, %1|%1, %0}", xops);
+         xops[0] = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, tmp, tmp2));
+       }
+      xops[1] = this_reg;
+      if (TARGET_64BIT)
+       output_asm_insn ("add{q}\t{%0, %1|%1, %0}", xops);
+      else
+       output_asm_insn ("add{l}\t{%0, %1|%1, %0}", xops);
+    }
 
-         if (ix86_regparm > 2)
-           abort ();
-         output_asm_insn ("push{l}\t%0", xops);
-         output_asm_insn ("call\t%P1", xops);
-         ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (xops[1]));
-         output_asm_insn ("pop{l}\t%0", xops);
-         output_asm_insn
-           ("add{l}\t{%2+[.-%P1], %0|%0, OFFSET FLAT: %2+[.-%P1]}", xops);
-         xops[0] = gen_rtx_MEM (SImode, XEXP (DECL_RTL (function), 0));
-         output_asm_insn
-           ("mov{l}\t{%0@GOT(%%ebx), %%ecx|%%ecx, %0@GOT[%%ebx]}", xops);
-         asm_fprintf (file, "\tpop{l\t%%ebx|\t%%ebx}\n");
-         asm_fprintf (file, "\tjmp\t{*%%ecx|%%ecx}\n");
+  /* If necessary, drop THIS back to its stack slot.  */
+  if (this_reg && this_reg != this)
+    {
+      xops[0] = this_reg;
+      xops[1] = this;
+      output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
+    }
+
+  xops[0] = DECL_RTL (function);
+  if (TARGET_64BIT)
+    {
+      if (!flag_pic || (*targetm.binds_local_p) (function))
+       output_asm_insn ("jmp\t%P0", xops);
+      else
+       {
+         tmp = XEXP (xops[0], 0);
+         tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, tmp), UNSPEC_GOTPCREL);
+         tmp = gen_rtx_CONST (Pmode, tmp);
+         tmp = gen_rtx_MEM (QImode, tmp);
+         xops[0] = tmp;
+         output_asm_insn ("jmp\t%A0", xops);
        }
+    }
+  else
+    {
+      if (!flag_pic || (*targetm.binds_local_p) (function))
+       output_asm_insn ("jmp\t%P0", xops);
       else
+#if TARGET_MACHO
+       if (TARGET_MACHO)
+         {
+           char *ip = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function));
+           tmp = gen_rtx_SYMBOL_REF (Pmode, machopic_stub_name (ip));
+           tmp = gen_rtx_MEM (QImode, tmp);
+           xops[0] = tmp;
+           output_asm_insn ("jmp\t%0", xops);
+         }
+       else
+#endif /* TARGET_MACHO */
        {
-         fprintf (file, "\tjmp ");
-         assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
-         fprintf (file, "\n");
+         tmp = gen_rtx_REG (SImode, 2 /* ECX */);
+         output_set_got (tmp);
+
+         xops[1] = tmp;
+         output_asm_insn ("mov{l}\t{%0@GOT(%1), %1|%1, %0@GOT[%1]}", xops);
+         output_asm_insn ("jmp\t{*}%1", xops);
        }
     }
 }
@@ -13670,20 +15227,62 @@ x86_field_alignment (field, computed)
      int computed;
 {
   enum machine_mode mode;
-  if (TARGET_64BIT || DECL_USER_ALIGN (field) || TARGET_ALIGN_DOUBLE)
+  tree type = TREE_TYPE (field);
+
+  if (TARGET_64BIT || TARGET_ALIGN_DOUBLE)
     return computed;
-  mode = TYPE_MODE (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
-                   ? get_inner_array_type (field) : TREE_TYPE (field));
-  if ((mode == DFmode || mode == DCmode
-      || mode == DImode || mode == CDImode)
-      && !TARGET_ALIGN_DOUBLE)
+  mode = TYPE_MODE (TREE_CODE (type) == ARRAY_TYPE
+                   ? get_inner_array_type (type) : type);
+  if (mode == DFmode || mode == DCmode
+      || GET_MODE_CLASS (mode) == MODE_INT
+      || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
     return MIN (32, computed);
   return computed;
 }
 
+/* Output assembler code to FILE to increment profiler label # LABELNO
+   for profiling a function entry.  */
+void
+x86_function_profiler (file, labelno)
+     FILE *file;
+     int labelno ATTRIBUTE_UNUSED;
+{
+  if (TARGET_64BIT)
+    if (flag_pic)
+      {
+#ifndef NO_PROFILE_COUNTERS
+       fprintf (file, "\tleaq\t%sP%d@(%%rip),%%r11\n", LPREFIX, labelno);
+#endif
+       fprintf (file, "\tcall\t*%s@GOTPCREL(%%rip)\n", MCOUNT_NAME);
+      }
+    else
+      {
+#ifndef NO_PROFILE_COUNTERS
+       fprintf (file, "\tmovq\t$%sP%d,%%r11\n", LPREFIX, labelno);
+#endif
+       fprintf (file, "\tcall\t%s\n", MCOUNT_NAME);
+      }
+  else if (flag_pic)
+    {
+#ifndef NO_PROFILE_COUNTERS
+      fprintf (file, "\tleal\t%sP%d@GOTOFF(%%ebx),%%%s\n",
+              LPREFIX, labelno, PROFILE_COUNT_REGISTER);
+#endif
+      fprintf (file, "\tcall\t*%s@GOT(%%ebx)\n", MCOUNT_NAME);
+    }
+  else
+    {
+#ifndef NO_PROFILE_COUNTERS
+      fprintf (file, "\tmovl\t$%sP%d,%%$%s\n", LPREFIX, labelno,
+              PROFILE_COUNT_REGISTER);
+#endif
+      fprintf (file, "\tcall\t%s\n", MCOUNT_NAME);
+    }
+}
+
 /* Implement machine specific optimizations.  
    At the moment we implement single transformation: AMD Athlon works faster
-   when RET is not destination of conditional jump or directly preceeded
+   when RET is not destination of conditional jump or directly preceded
    by other jump instruction.  We avoid the penalty by inserting NOP just
    before the RET instructions in such cases.  */
 void
@@ -13692,7 +15291,7 @@ x86_machine_dependent_reorg (first)
 {
   edge e;
 
-  if (!TARGET_ATHLON || !optimize || optimize_size)
+  if (!TARGET_ATHLON_K8 || !optimize || optimize_size)
     return;
   for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
   {
@@ -13703,25 +15302,69 @@ x86_machine_dependent_reorg (first)
 
     if (!returnjump_p (ret) || !maybe_hot_bb_p (bb))
       continue;
-    prev = prev_nonnote_insn (ret);
+    for (prev = PREV_INSN (ret); prev; prev = PREV_INSN (prev))
+      if (active_insn_p (prev) || GET_CODE (prev) == CODE_LABEL)
+       break;
     if (prev && GET_CODE (prev) == CODE_LABEL)
       {
        edge e;
        for (e = bb->pred; e; e = e->pred_next)
-         if (EDGE_FREQUENCY (e) && e->src->index > 0
+         if (EDGE_FREQUENCY (e) && e->src->index >= 0
              && !(e->flags & EDGE_FALLTHRU))
            insert = 1;
       }
     if (!insert)
       {
-       prev = prev_real_insn (ret);
+       prev = prev_active_insn (ret);
        if (prev && GET_CODE (prev) == JUMP_INSN
            && any_condjump_p (prev))
          insert = 1;
+       /* Empty functions get branch misspredict even when the jump destination
+          is not visible to us.  */
+       if (!prev && cfun->function_frequency > FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
+         insert = 1;
       }
     if (insert)
       emit_insn_before (gen_nop (), ret);
   }
 }
 
+/* Return nonzero when QImode register that must be represented via REX prefix
+   is used.  */
+bool
+x86_extended_QIreg_mentioned_p (insn)
+     rtx insn;
+{
+  int i;
+  extract_insn_cached (insn);
+  for (i = 0; i < recog_data.n_operands; i++)
+    if (REG_P (recog_data.operand[i])
+       && REGNO (recog_data.operand[i]) >= 4)
+       return true;
+  return false;
+}
+
+/* Return nonzero when P points to register encoded via REX prefix.
+   Called via for_each_rtx.  */
+static int
+extended_reg_mentioned_1 (p, data)
+       rtx *p;
+       void *data ATTRIBUTE_UNUSED;
+{
+   unsigned int regno;
+   if (!REG_P (*p))
+     return 0;
+   regno = REGNO (*p);
+   return REX_INT_REGNO_P (regno) || REX_SSE_REGNO_P (regno);
+}
+
+/* Return true when INSN mentions register that must be encoded using REX
+   prefix.  */
+bool
+x86_extended_reg_mentioned_p (insn)
+     rtx insn;
+{
+  return for_each_rtx (&PATTERN (insn), extended_reg_mentioned_1, NULL);
+}
+
 #include "gt-i386.h"