OSDN Git Service

2003-02-28 Joel Sherrill <joel@OARcorp.com>
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.c
index f912fa9..81d6437 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,9 +330,9 @@ 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 */
@@ -306,17 +359,68 @@ struct processor_costs athlon_cost = {
   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,68 @@ 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;
+const int x86_inter_unit_moves = ~(m_ATHLON_K8);
+const int x86_ext_80387_constants = m_K6 | m_ATHLON | m_PENT4 | m_PPRO;
+
+/* 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 +661,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
@@ -553,17 +680,15 @@ static char const tls_model_chars[] = " GLil";
 #define X86_64_VARARGS_SIZE (REGPARM_MAX * UNITS_PER_WORD + SSE_REGPARM_MAX * 16)
 
 /* Define the structure for the machine field in struct function.  */
-struct machine_function GTY(())
+
+struct stack_local_entry GTY(())
 {
-  rtx stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
-  const char *some_ld_name;
-  int save_varrargs_registers;
-  int accesses_prev_frame;
+  unsigned short mode;
+  unsigned short n;
+  rtx rtl;
+  struct stack_local_entry *next;
 };
 
-#define ix86_stack_locals (cfun->machine->stack_locals)
-#define ix86_save_varrargs_registers (cfun->machine->save_varrargs_registers)
-
 /* Structure describing stack frame layout.
    Stack grows downward:
 
@@ -617,12 +742,12 @@ enum tls_dialect ix86_tls_dialect = TLS_DIALECT_GNU;
 enum fpmath_unit ix86_fpmath;
 
 /* Which cpu are we scheduling for.  */
-enum processor_type ix86_cpu;
+enum processor_type ix86_tune;
 /* Which instruction set architecture to use.  */
 enum processor_type ix86_arch;
 
 /* Strings to hold which cpu and instruction set architecture  to use.  */
-const char *ix86_cpu_string;           /* for -mcpu=<xxx> */
+const char *ix86_tune_string;          /* for -mtune=<xxx> */
 const char *ix86_arch_string;          /* for -march=<xxx> */
 const char *ix86_fpmath_string;                /* for -mfpmath=<xxx> */
 
@@ -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,9 @@ 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 rtx ix86_delegitimize_address 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 +856,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,10 +873,17 @@ 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 contains_128bit_aligned_vector_p PARAMS ((tree));
+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));
@@ -753,9 +892,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
@@ -784,6 +923,11 @@ static rtx construct_container PARAMS ((enum machine_mode, tree, int, int, int,
                                        const int *, int));
 static enum x86_64_reg_class merge_classes PARAMS ((enum x86_64_reg_class,
                                                    enum x86_64_reg_class));
+
+/* Table of constants used by fldpi, fldln2, etc...  */
+static REAL_VALUE_TYPE ext_80387_constants_table [5];
+static bool ext_80387_constants_init = 0;
+static void init_ext_80387_constants PARAMS ((void));
 \f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ATTRIBUTE_TABLE
@@ -843,13 +987,40 @@ 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_DELEGITIMIZE_ADDRESS
+#define TARGET_DELEGITIMIZE_ADDRESS ix86_delegitimize_address
+
+#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
+/* The svr4 ABI for the i386 says that records and unions are returned
+   in memory.  */
+#ifndef DEFAULT_PCC_STRUCT_RETURN
+#define DEFAULT_PCC_STRUCT_RETURN 1
+#endif
+
 /* Sometimes certain combinations of command options do not make
    sense on a particular target machine.  You can define a macro
    `OVERRIDE_OPTIONS' to take account of this.  This macro, if
@@ -876,17 +1047,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;
@@ -901,7 +1072,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[] =
@@ -914,6 +1086,7 @@ override_options ()
       {"winchip-c6", PROCESSOR_I486, PTA_MMX},
       {"winchip2", PROCESSOR_I486, PTA_MMX | PTA_3DNOW},
       {"c3", PROCESSOR_I486, PTA_MMX | PTA_3DNOW},
+      {"c3-2", PROCESSOR_PENTIUMPRO, PTA_MMX | PTA_PREFETCH_SSE | PTA_SSE},
       {"i686", PROCESSOR_PENTIUMPRO, 0},
       {"pentiumpro", PROCESSOR_PENTIUMPRO, 0},
       {"pentium2", PROCESSOR_PENTIUMPRO, PTA_MMX},
@@ -933,6 +1106,8 @@ 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);
@@ -942,16 +1117,37 @@ override_options ()
   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
 
-  if (!ix86_cpu_string && ix86_arch_string)
-    ix86_cpu_string = ix86_arch_string;
-  if (!ix86_cpu_string)
-    ix86_cpu_string = cpu_names [TARGET_CPU_DEFAULT];
+  if (!ix86_tune_string && ix86_arch_string)
+    ix86_tune_string = ix86_arch_string;
+  if (!ix86_tune_string)
+    ix86_tune_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)
     {
@@ -999,7 +1195,7 @@ override_options ()
       {
        ix86_arch = processor_alias_table[i].processor;
        /* Default cpu tuning to the architecture.  */
-       ix86_cpu = ix86_arch;
+       ix86_tune = ix86_arch;
        if (processor_alias_table[i].flags & PTA_MMX
            && !(target_flags_explicit & MASK_MMX))
          target_flags |= MASK_MMX;
@@ -1017,6 +1213,8 @@ override_options ()
          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;
       }
 
@@ -1024,22 +1222,24 @@ override_options ()
     error ("bad value (%s) for -march= switch", ix86_arch_string);
 
   for (i = 0; i < pta_size; i++)
-    if (! strcmp (ix86_cpu_string, processor_alias_table[i].name))
+    if (! strcmp (ix86_tune_string, processor_alias_table[i].name))
       {
-       ix86_cpu = processor_alias_table[i].processor;
+       ix86_tune = 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)
     x86_prefetch_sse = true;
   if (i == pta_size)
-    error ("bad value (%s) for -mcpu= switch", ix86_cpu_string);
+    error ("bad value (%s) for -mtune= switch", ix86_tune_string);
 
   if (optimize_size)
     ix86_cost = &size_cost;
   else
-    ix86_cost = processor_target_table[ix86_cpu].cost;
-  target_flags |= processor_target_table[ix86_cpu].target_enable;
-  target_flags &= ~processor_target_table[ix86_cpu].target_disable;
+    ix86_cost = processor_target_table[ix86_tune].cost;
+  target_flags |= processor_target_table[ix86_tune].target_enable;
+  target_flags &= ~processor_target_table[ix86_tune].target_disable;
 
   /* Arrange to set up i386_stack_locals for all functions.  */
   init_machine_status = ix86_init_machine_status;
@@ -1102,17 +1302,17 @@ override_options ()
   /* Default align_* from the processor table.  */
   if (align_loops == 0)
     {
-      align_loops = processor_target_table[ix86_cpu].align_loop;
-      align_loops_max_skip = processor_target_table[ix86_cpu].align_loop_max_skip;
+      align_loops = processor_target_table[ix86_tune].align_loop;
+      align_loops_max_skip = processor_target_table[ix86_tune].align_loop_max_skip;
     }
   if (align_jumps == 0)
     {
-      align_jumps = processor_target_table[ix86_cpu].align_jump;
-      align_jumps_max_skip = processor_target_table[ix86_cpu].align_jump_max_skip;
+      align_jumps = processor_target_table[ix86_tune].align_jump;
+      align_jumps_max_skip = processor_target_table[ix86_tune].align_jump_max_skip;
     }
   if (align_functions == 0)
     {
-      align_functions = processor_target_table[ix86_cpu].align_func;
+      align_functions = processor_target_table[ix86_tune].align_func;
     }
 
   /* Validate -mpreferred-stack-boundary= value, or provide default.
@@ -1133,7 +1333,7 @@ override_options ()
     }
 
   /* Validate -mbranch-cost= value, or provide default.  */
-  ix86_branch_cost = processor_target_table[ix86_cpu].branch_cost;
+  ix86_branch_cost = processor_target_table[ix86_tune].cost->branch_cost;
   if (ix86_branch_cost_string)
     {
       i = atoi (ix86_branch_cost_string);
@@ -1154,9 +1354,6 @@ override_options ()
               ix86_tls_dialect_string);
     }
 
-  if (profile_flag)
-    target_flags &= ~MASK_OMIT_LEAF_FRAME_POINTER;
-
   /* Keep nonleaf frame pointers.  */
   if (TARGET_OMIT_LEAF_FRAME_POINTER)
     flag_omit_frame_pointer = 1;
@@ -1230,12 +1427,12 @@ 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)
+  if ((x86_accumulate_outgoing_args & TUNEMASK)
       && !(target_flags_explicit & MASK_ACCUMULATE_OUTGOING_ARGS)
       && !optimize_size)
     target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS;
@@ -1261,15 +1458,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;
-    }
-  if (profile_flag)
-    flag_omit_frame_pointer = 0;
+
+  /* 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.  */
@@ -1279,6 +1476,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
@@ -1289,10 +1489,65 @@ 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;
+/* Decide whether we can make a sibling call to a function.  DECL is the
+   declaration of the function being targeted by the call and EXP is the
+   CALL_EXPR representing the call.  */
+
+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 or, conversely, from a function that does return
+     a float to a function that doesn't; the necessary stack adjustment
+     would 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)
@@ -1311,6 +1566,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)
     {
@@ -1357,6 +1633,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;
@@ -1377,6 +1658,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)))
@@ -1384,6 +1670,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),
@@ -1412,8 +1713,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
@@ -1427,15 +1729,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);
@@ -1507,6 +1801,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
@@ -1521,7 +1826,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;
            }
        }
@@ -1536,7 +1844,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.  */
 
@@ -1862,8 +2170,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;
@@ -2001,7 +2308,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)
@@ -2031,14 +2338,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:
@@ -2139,7 +2448,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)
@@ -2165,12 +2474,30 @@ function_arg (cum, mode, type, named)
        break;
 
       case BLKmode:
+       if (bytes < 0)
+         break;
+       /* FALLTHRU */
       case DImode:
       case SImode:
       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)
@@ -2195,6 +2522,90 @@ 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;
+}
+
+/* Return true when TYPE should be 128bit aligned for 32bit argument passing
+   ABI  */
+static bool
+contains_128bit_aligned_vector_p (type)
+     tree type;
+{
+  enum machine_mode mode = TYPE_MODE (type);
+  if (SSE_REG_MODE_P (mode)
+      && (!TYPE_USER_ALIGN (type) || TYPE_ALIGN (type) > 128))
+    return true;
+  if (TYPE_ALIGN (type) < 128)
+    return false;
+
+  if (AGGREGATE_TYPE_P (type))
+    {
+      /* Walk the agregates recursivly.  */
+      if (TREE_CODE (type) == RECORD_TYPE
+         || TREE_CODE (type) == UNION_TYPE
+         || TREE_CODE (type) == QUAL_UNION_TYPE)
+       {
+         tree field;
+
+         if (TYPE_BINFO (type) != NULL
+             && TYPE_BINFO_BASETYPES (type) != NULL)
+           {
+             tree bases = TYPE_BINFO_BASETYPES (type);
+             int n_bases = TREE_VEC_LENGTH (bases);
+             int i;
+
+             for (i = 0; i < n_bases; ++i)
+               {
+                 tree binfo = TREE_VEC_ELT (bases, i);
+                 tree type = BINFO_TYPE (binfo);
+
+                 if (contains_128bit_aligned_vector_p (type))
+                   return true;
+               }
+           }
+         /* And now merge the fields of structure.   */
+         for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+           {
+             if (TREE_CODE (field) == FIELD_DECL
+                 && contains_128bit_aligned_vector_p (TREE_TYPE (field)))
+               return true;
+           }
+       }
+      /* Just for use if some languages passes arrays by value.  */
+      else if (TREE_CODE (type) == ARRAY_TYPE)
+       {
+         if (contains_128bit_aligned_vector_p (TREE_TYPE (type)))
+           return true;
+       }
+      else
+       abort ();
+    }
+  return false;
+}
+
 /* Gives the alignment boundary, in bits, of an argument with the specified mode
    and type.   */
 
@@ -2204,14 +2615,34 @@ ix86_function_arg_boundary (mode, type)
      tree type;
 {
   int align;
-  if (!TARGET_64BIT)
-    return PARM_BOUNDARY;
   if (type)
     align = TYPE_ALIGN (type);
   else
     align = GET_MODE_ALIGNMENT (mode);
   if (align < PARM_BOUNDARY)
     align = PARM_BOUNDARY;
+  if (!TARGET_64BIT)
+    {
+      /* i386 ABI defines all arguments to be 4 byte aligned.  We have to
+        make an exception for SSE modes since these require 128bit
+        alignment.  
+
+        The handling here differs from field_alignment.  ICC aligns MMX
+        arguments to 4 byte boundaries, while structure fields are aligned
+        to 8 byte boundaries.  */
+      if (!type)
+       {
+         if (!SSE_REG_MODE_P (mode))
+           align = PARM_BOUNDARY;
+       }
+      else
+       {
+         if (!contains_128bit_aligned_vector_p (type))
+           align = PARM_BOUNDARY;
+       }
+      if (align != PARM_BOUNDARY && !TARGET_SSE)
+       abort();
+    }
   if (align > 128)
     align = 128;
   return align;
@@ -2246,8 +2677,8 @@ 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;
@@ -2270,12 +2701,18 @@ ix86_return_in_memory (type)
     }
   else
     {
-      if (TYPE_MODE (type) == BLKmode
-         || (VECTOR_MODE_P (TYPE_MODE (type))
-             && int_size_in_bytes (type) == 8)
-         || (int_size_in_bytes (type) > 12 && TYPE_MODE (type) != TImode
-             && TYPE_MODE (type) != TFmode
-             && !VECTOR_MODE_P (TYPE_MODE (type))))
+      if (TYPE_MODE (type) == BLKmode)
+       return 1;
+      else if (MS_AGGREGATE_RETURN
+              && AGGREGATE_TYPE_P (type)
+              && int_size_in_bytes(type) <= 8)
+       return 0;
+      else if ((VECTOR_MODE_P (TYPE_MODE (type))
+               && int_size_in_bytes (type) == 8)
+              || (int_size_in_bytes (type) > 12
+                  && TYPE_MODE (type) != TImode
+                  && TYPE_MODE (type) != TFmode
+                  && !VECTOR_MODE_P (TYPE_MODE (type))))
        return 1;
       return 0;
     }
@@ -2429,7 +2866,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.  */
 
@@ -2550,6 +2987,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)
@@ -2569,6 +3007,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,
@@ -2595,11 +3040,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;
@@ -2759,6 +3204,13 @@ 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
@@ -2789,7 +3241,7 @@ register_and_not_any_fp_reg_operand (op, mode)
   return register_operand (op, mode) && !ANY_FP_REG_P (op);
 }
 
-/* Return nonzero of OP is a register operand other than an
+/* Return nonzero if OP is a register operand other than an
    i387 fp register.  */
 int
 register_and_not_fp_reg_operand (op, mode)
@@ -2999,14 +3451,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;
 
@@ -3122,6 +3574,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;
@@ -3163,7 +3641,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)
@@ -3300,6 +3778,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
@@ -3314,6 +3804,44 @@ 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 when OP is operand acceptable for standard SSE move.  */
+int
+vector_move_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  if (nonimmediate_operand (op, mode))
+    return 1;
+  if (GET_MODE (op) != mode && mode != VOIDmode)
+    return 0;
+  return (op == CONST0_RTX (GET_MODE (op)));
+}
+
 /* Return 1 if OP is a comparison that can be used in the CMPSS/CMPPS
    insns.  */
 int
@@ -3388,29 +3916,65 @@ 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.  */
+  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:
@@ -3437,7 +4001,7 @@ promotable_binary_operator (op, mode)
     case MULT:
       /* Modern CPUs have same latency for HImode and SImode multiply,
          but 386 and 486 do HImode multiply faster.  */
-      return ix86_cpu > PROCESSOR_I486;
+      return ix86_tune > PROCESSOR_I486;
     case PLUS:
     case AND:
     case IOR:
@@ -3480,7 +4044,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);
 }
@@ -3653,9 +4217,34 @@ aligned_operand (op, mode)
   return 1;
 }
 \f
+/* Initialize the table of extra 80387 mathematical constants.  */
+
+static void
+init_ext_80387_constants ()
+{
+  static const char * cst[5] =
+  {
+    "0.3010299956639811952256464283594894482",  /* 0: fldlg2  */
+    "0.6931471805599453094286904741849753009",  /* 1: fldln2  */
+    "1.4426950408889634073876517827983434472",  /* 2: fldl2e  */
+    "3.3219280948873623478083405569094566090",  /* 3: fldl2t  */
+    "3.1415926535897932385128089594061862044",  /* 4: fldpi   */
+  };
+  int i;
+
+  for (i = 0; i < 5; i++)
+    {
+      real_from_string (&ext_80387_constants_table[i], cst[i]);
+      /* Ensure each constant is rounded to XFmode precision.  */
+      real_convert (&ext_80387_constants_table[i], XFmode,
+                   &ext_80387_constants_table[i]);
+    }
+
+  ext_80387_constants_init = 1;
+}
+
 /* Return true if the constant is something that can be loaded with
-   a special instruction.  Only handle 0.0 and 1.0; others are less
-   worthwhile.  */
+   a special instruction.  */
 
 int
 standard_80387_constant_p (x)
@@ -3663,24 +4252,97 @@ standard_80387_constant_p (x)
 {
   if (GET_CODE (x) != CONST_DOUBLE || !FLOAT_MODE_P (GET_MODE (x)))
     return -1;
-  /* Note that on the 80387, other constants, such as pi, that we should support
-     too.  On some machines, these are much slower to load as standard constant,
-     than to load from doubles in memory.  */
+
   if (x == CONST0_RTX (GET_MODE (x)))
     return 1;
   if (x == CONST1_RTX (GET_MODE (x)))
     return 2;
+
+  /* For XFmode constants, try to find a special 80387 instruction on
+     those CPUs that benefit from them.  */
+  if (GET_MODE (x) == XFmode
+      && x86_ext_80387_constants & TUNEMASK)
+    {
+      REAL_VALUE_TYPE r;
+      int i;
+
+      if (! ext_80387_constants_init)
+       init_ext_80387_constants ();
+
+      REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+      for (i = 0; i < 5; i++)
+        if (real_identical (&r, &ext_80387_constants_table[i]))
+         return i + 3;
+    }
+
   return 0;
 }
 
+/* Return the opcode of the special instruction to be used to load
+   the constant X.  */
+
+const char *
+standard_80387_constant_opcode (x)
+     rtx x;
+{
+  switch (standard_80387_constant_p (x))
+    {
+    case 1: 
+      return "fldz";
+    case 2:
+      return "fld1";
+    case 3: 
+      return "fldlg2";
+    case 4:
+      return "fldln2";
+    case 5: 
+      return "fldl2e";
+    case 6:
+      return "fldl2t";
+    case 7: 
+      return "fldpi";
+    }
+  abort ();
+}
+
+/* Return the CONST_DOUBLE representing the 80387 constant that is
+   loaded by the specified special instruction.  The argument IDX
+   matches the return value from standard_80387_constant_p.  */
+
+rtx
+standard_80387_constant_rtx (idx)
+     int idx;
+{
+  int i;
+
+  if (! ext_80387_constants_init)
+    init_ext_80387_constants ();
+
+  switch (idx)
+    {
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+      i = idx - 3;
+      break;
+
+    default:
+      abort ();
+    }
+
+  return CONST_DOUBLE_FROM_REAL_VALUE (ext_80387_constants_table[i], XFmode);
+}
+
 /* Return 1 if X is FP constant we can load to SSE register w/o using memory.
  */
 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)));
 }
 
@@ -3770,21 +4432,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);
@@ -3798,12 +4472,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
@@ -3819,7 +4493,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
@@ -3827,6 +4501,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;
              }
@@ -3935,7 +4619,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;
@@ -4048,7 +4735,7 @@ output_set_got (dest)
          is what will be referred to by the Mach-O PIC subsystem.  */
       ASM_OUTPUT_LABEL (asm_out_file, machopic_function_base_name ());
 #endif
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+      (*targetm.asm_out.internal_label) (asm_out_file, "L",
                                 CODE_LABEL_NUMBER (XEXP (xops[2], 0)));
 
       if (flag_pic)
@@ -4344,14 +5031,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.  */
@@ -4404,6 +5109,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)
     {
@@ -4438,7 +5147,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);
@@ -4500,7 +5209,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
@@ -4756,7 +5465,7 @@ ix86_decompose_address (addr, out)
 
   /* Special case: on K6, [%esi] makes the instruction vector decoded.
      Avoid this by transforming to [%esi+0].  */
-  if (ix86_cpu == PROCESSOR_K6 && !optimize_size
+  if (ix86_tune == PROCESSOR_K6 && !optimize_size
       && base && !index && !disp
       && REG_P (base)
       && REGNO_REG_CLASS (REGNO (base)) == SIREG)
@@ -4783,7 +5492,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;
 {
@@ -4873,21 +5582,7 @@ ix86_find_base_term (x)
       return term;
     }
 
-  if (GET_CODE (x) != PLUS
-      || XEXP (x, 0) != pic_offset_table_rtx
-      || GET_CODE (XEXP (x, 1)) != CONST)
-    return x;
-
-  term = XEXP (XEXP (x, 1), 0);
-
-  if (GET_CODE (term) == PLUS && GET_CODE (XEXP (term, 1)) == CONST_INT)
-    term = XEXP (term, 0);
-
-  if (GET_CODE (term) != UNSPEC
-      || XINT (term, 1) != UNSPEC_GOTOFF)
-    return x;
-
-  term = XVECEXP (term, 0, 0);
+  term = ix86_delegitimize_address (x);
 
   if (GET_CODE (term) != SYMBOL_REF
       && GET_CODE (term) != LABEL_REF)
@@ -4941,6 +5636,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
@@ -5017,17 +5723,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)
@@ -5236,23 +5951,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))
@@ -5285,10 +5983,19 @@ legitimate_address_p (mode, addr, strict)
        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;
@@ -5321,6 +6028,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.  */
@@ -5382,28 +6099,24 @@ legitimize_pic_address (orig, reg)
   return machopic_legitimize_pic_address (orig, GET_MODE (orig), reg);
 #endif
 
-  if (local_symbolic_operand (addr, Pmode))
+  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)
     {
@@ -5486,7 +6199,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
@@ -5544,6 +6259,21 @@ ix86_encode_section_info (decl, first)
       size_t len;
       enum tls_model kind = decl_tls_model (decl);
 
+      if (TARGET_64BIT && ! flag_pic)
+       {
+         /* 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;
+           }
+       }
+
       symbol_str = XSTR (symbol, 0);
 
       if (symbol_str[0] == '%')
@@ -5633,17 +6363,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);
@@ -5651,36 +6408,42 @@ 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 if (!TARGET_GNU_TLS)
            {
              pic = gen_reg_rtx (Pmode);
              emit_insn (gen_set_got (pic));
+             type = UNSPEC_GOTTPOFF;
            }
          else
-           pic = NULL;
+           {
+             pic = NULL;
+             type = UNSPEC_INDNTPOFF;
+           }
 
          base = get_thread_pointer ();
 
-         off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
-                               !TARGET_GNU_TLS
-                               ? UNSPEC_GOTTPOFF
-                               : flag_pic ? UNSPEC_GOTNTPOFF
-                                          : UNSPEC_INDNTPOFF);
+         off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), type);
          off = gen_rtx_CONST (Pmode, off);
-         if (flag_pic || !TARGET_GNU_TLS)
+         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 ());
          dest = gen_reg_rtx (Pmode);
 
-         if (TARGET_GNU_TLS)
+         if (TARGET_64BIT || TARGET_GNU_TLS)
            {
              emit_move_insn (dest, off);
              return gen_rtx_PLUS (Pmode, base, dest);
@@ -5693,10 +6456,11 @@ legitimize_address (x, oldx, mode)
          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
            {
@@ -5974,13 +6738,19 @@ output_pic_addr_const (file, x, code)
          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:
-         fputs ("@GOTNTPOFF", file);
+         if (TARGET_64BIT)
+           fputs ("@GOTTPOFF(%rip)", file);
+         else
+           fputs ("@GOTNTPOFF", file);
          break;
        case UNSPEC_INDNTPOFF:
          fputs ("@INDNTPOFF", file);
@@ -6027,30 +6797,27 @@ i386_output_dwarf_dtprel (file, size, x)
      int size;
      rtx x;
 {
+  fputs (ASM_LONG, file);
+  output_addr_const (file, x);
+  fputs ("@DTPOFF", file);
   switch (size)
     {
     case 4:
-      fputs (ASM_LONG, file);
       break;
     case 8:
-#ifdef ASM_QUAD
-      fputs (ASM_QUAD, file);
+      fputs (", 0", file);
       break;
-#endif
     default:
       abort ();
    }
-  
-  output_addr_const (file, x);
-  fputs ("@DTPOFF", file);
 }
 
 /* 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.  */
 
-rtx
-i386_simplify_dwarf_addr (orig_x)
+static rtx
+ix86_delegitimize_address (orig_x)
      rtx orig_x;
 {
   rtx x = orig_x, y;
@@ -6612,7 +7379,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
@@ -6695,22 +7462,18 @@ 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, dstr, -1);
+      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, dstr, -1);
+      real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (x), sizeof (dstr), 0, 1);
       fprintf (file, "%s", dstr);
     }
 
@@ -6758,7 +7521,10 @@ print_operand_address (file, addr)
        fputs ("DWORD PTR ", file);
       if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0)
        putc ('%', file);
-      fputs ("gs:0", file);
+      if (TARGET_64BIT)
+       fputs ("fs:0", file);
+      else
+       fputs ("gs:0", file);
       return;
     }
 
@@ -6791,7 +7557,8 @@ 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
@@ -6904,7 +7671,10 @@ 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);
@@ -6912,7 +7682,10 @@ output_addr_const_extra (file, x)
       break;
     case UNSPEC_GOTNTPOFF:
       output_addr_const (file, op);
-      fputs ("@GOTNTPOFF", file);
+      if (TARGET_64BIT)
+       fputs ("@GOTTPOFF(%rip)", file);
+      else
+       fputs ("@GOTNTPOFF", file);
       break;
     case UNSPEC_INDNTPOFF:
       output_addr_const (file, op);
@@ -7294,12 +8067,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))
@@ -7474,24 +8247,7 @@ static rtx
 maybe_get_pool_constant (x)
      rtx x;
 {
-  x = XEXP (x, 0);
-
-  if (flag_pic)
-    {
-      if (GET_CODE (x) != PLUS)
-       return NULL_RTX;
-      if (XEXP (x, 0) != pic_offset_table_rtx)
-       return NULL_RTX;
-      x = XEXP (x, 1);
-      if (GET_CODE (x) != CONST)
-       return NULL_RTX;
-      x = XEXP (x, 0);
-      if (GET_CODE (x) != UNSPEC)
-       return NULL_RTX;
-      if (XINT (x, 1) != UNSPEC_GOTOFF)
-       return NULL_RTX;
-      x = XVECEXP (x, 0, 0);
-    }
+  x = ix86_delegitimize_address (XEXP (x, 0));
 
   if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
     return get_pool_constant (x);
@@ -7510,29 +8266,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);
@@ -7632,18 +8365,13 @@ ix86_expand_vector_move (mode, operands)
      to handle some of them more efficiently.  */
   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);
-    }
+      && CONSTANT_P (operands[1]) && operands[1] != CONST0_RTX (mode))
+    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);
@@ -7971,7 +8699,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 */
@@ -8002,7 +8730,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)
@@ -8173,7 +8901,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
@@ -8217,7 +8945,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;
@@ -8232,7 +8960,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;
@@ -8798,85 +9526,228 @@ 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)
+      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)
     {
-      rtx out = operands[0];
-      HOST_WIDE_INT ct = INTVAL (operands[2]);
-      HOST_WIDE_INT cf = INTVAL (operands[3]);
+    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;
+                 diff = ct - cf;
+               }
+             tmp = emit_store_flag (tmp, code, ix86_compare_op0,
+                                    ix86_compare_op1, VOIDmode, 0, -1);
+           }
 
          if (diff == 1)
            {
@@ -8890,7 +9761,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)
            {
@@ -8903,7 +9774,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)
            {
@@ -8915,11 +9786,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
            {
@@ -8937,26 +9808,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;
@@ -9032,8 +9902,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))))
        {
          /*
@@ -9057,11 +9929,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)
@@ -9075,24 +9947,14 @@ 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])
+         if (!rtx_equal_p (out, operands[0]))
            emit_move_insn (operands[0], copy_rtx (out));
 
          return 1; /* DONE */
@@ -9112,12 +9974,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)
            {
@@ -9171,31 +10031,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
@@ -9204,9 +10064,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 */
@@ -9214,9 +10074,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 */
@@ -9235,8 +10095,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 */
     }
@@ -9269,27 +10129,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 */
 }
@@ -9330,8 +10196,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);
@@ -9342,8 +10214,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);
@@ -9368,7 +10246,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])
@@ -9448,6 +10326,91 @@ 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;
+  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
@@ -9995,17 +10958,23 @@ 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);
 
+  /* Can't use any of this if the user has appropriated esi or edi.  */
+  if (global_regs[4] || global_regs[5])
+    return 0;
+
   /* This simple hack avoids all inlining code and simplifies code below.  */
   if (!TARGET_ALIGN_STRINGOPS)
     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.
@@ -10016,6 +10985,8 @@ ix86_expand_movstr (dst, src, count_exp, align_exp)
   else
     counter_mode = DImode;
 
+  start_sequence ();
+
   if (counter_mode != SImode && counter_mode != DImode)
     abort ();
 
@@ -10089,8 +11060,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;
@@ -10108,11 +11083,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)
@@ -10224,12 +11199,20 @@ ix86_expand_clrstr (src, count_exp, align_exp)
   if (GET_CODE (align_exp) == CONST_INT)
     align = INTVAL (align_exp);
 
+  /* Can't use any of this if the user has appropriated esi.  */
+  if (global_regs[4])
+    return 0;
+
   /* This simple hack avoids all inlining code and simplifies code below.  */
   if (!TARGET_ALIGN_STRINGOPS)
     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.  */
@@ -10304,8 +11287,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)
@@ -10508,6 +11495,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)
@@ -10666,17 +11654,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;
 
@@ -10708,6 +11698,15 @@ ix86_expand_call (retval, fnaddr, callarg1, callarg2, pop)
       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)
@@ -10746,14 +11745,24 @@ assign_386_stack_local (mode, n)
      enum machine_mode mode;
      int n;
 {
+  struct stack_local_entry *s;
+
   if (n < 0 || n >= MAX_386_STACK_LOCALS)
     abort ();
 
-  if (ix86_stack_locals[(int) mode][n] == NULL_RTX)
-    ix86_stack_locals[(int) mode][n]
-      = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
+  for (s = ix86_stack_locals; s; s = s->next)
+    if (s->mode == mode && s->n == n)
+      return s->rtl;
 
-  return ix86_stack_locals[(int) mode][n];
+  s = (struct stack_local_entry *)
+    ggc_alloc (sizeof (struct stack_local_entry));
+  s->n = n;
+  s->mode = mode;
+  s->rtl = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
+
+  s->next = ix86_stack_locals;
+  ix86_stack_locals = s;
+  return s->rtl;
 }
 
 /* Construct the SYMBOL_REF for the tls_get_addr function.  */
@@ -10765,9 +11774,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;
@@ -10897,7 +11907,7 @@ ix86_attr_length_address_default (insn)
 static int
 ix86_issue_rate ()
 {
-  switch (ix86_cpu)
+  switch (ix86_tune)
     {
     case PROCESSOR_PENTIUM:
     case PROCESSOR_K6:
@@ -10906,6 +11916,7 @@ ix86_issue_rate ()
     case PROCESSOR_PENTIUMPRO:
     case PROCESSOR_PENTIUM4:
     case PROCESSOR_ATHLON:
+    case PROCESSOR_K8:
       return 3;
 
     default:
@@ -11010,7 +12021,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;
 
@@ -11023,7 +12034,7 @@ ix86_adjust_cost (insn, link, dep_insn, cost)
   insn_type = get_attr_type (insn);
   dep_insn_type = get_attr_type (dep_insn);
 
-  switch (ix86_cpu)
+  switch (ix86_tune)
     {
     case PROCESSOR_PENTIUM:
       /* Address Generation Interlock adds a cycle of latency.  */
@@ -11034,7 +12045,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))
@@ -11117,16 +12128,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.  */
@@ -11320,7 +12325,7 @@ ix86_sched_reorder (dump, sched_verbose, ready, n_readyp, clock_var)
       goto out;
     }
 
-  switch (ix86_cpu)
+  switch (ix86_tune)
     {
     default:
       break;
@@ -11345,7 +12350,7 @@ ix86_variable_issue (dump, sched_verbose, insn, can_issue_more)
      int can_issue_more;
 {
   int i;
-  switch (ix86_cpu)
+  switch (ix86_tune)
     {
     default:
       return can_issue_more - 1;
@@ -11400,7 +12405,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;
 }
@@ -11412,7 +12417,7 @@ ia32_use_dfa_pipeline_interface ()
 static int
 ia32_multipass_dfa_lookahead ()
 {
-  if (ix86_cpu == PROCESSOR_PENTIUM)
+  if (ix86_tune == PROCESSOR_PENTIUM)
     return 2;
   else
    return 0;
@@ -11671,11 +12676,17 @@ 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)                    \
 do {                                                           \
-  if ((MASK) & target_flags)                                   \
+  if ((MASK) & target_flags                                    \
+      && (!((MASK) & MASK_64BIT) || TARGET_64BIT))             \
     builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD,     \
                      NULL, NULL_TREE);                         \
 } while (0)
@@ -11692,33 +12703,35 @@ struct builtin_description
 
 /* Used for builtins that are enabled both by -msse and -msse2.  */
 #define MASK_SSE1 (MASK_SSE | MASK_SSE2)
+#define MASK_SSE164 (MASK_SSE | MASK_SSE2 | MASK_64BIT)
+#define MASK_SSE264 (MASK_SSE2 | MASK_64BIT)
 
 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[] =
@@ -11748,14 +12761,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 },
@@ -11763,6 +12772,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 },
@@ -11773,9 +12787,11 @@ static const struct builtin_description bdesc_2arg[] =
   { MASK_MMX, CODE_FOR_addv8qi3, "__builtin_ia32_paddb", IX86_BUILTIN_PADDB, 0, 0 },
   { MASK_MMX, CODE_FOR_addv4hi3, "__builtin_ia32_paddw", IX86_BUILTIN_PADDW, 0, 0 },
   { MASK_MMX, CODE_FOR_addv2si3, "__builtin_ia32_paddd", IX86_BUILTIN_PADDD, 0, 0 },
+  { MASK_MMX, CODE_FOR_mmx_adddi3, "__builtin_ia32_paddq", IX86_BUILTIN_PADDQ, 0, 0 },
   { MASK_MMX, CODE_FOR_subv8qi3, "__builtin_ia32_psubb", IX86_BUILTIN_PSUBB, 0, 0 },
   { MASK_MMX, CODE_FOR_subv4hi3, "__builtin_ia32_psubw", IX86_BUILTIN_PSUBW, 0, 0 },
   { MASK_MMX, CODE_FOR_subv2si3, "__builtin_ia32_psubd", IX86_BUILTIN_PSUBD, 0, 0 },
+  { MASK_MMX, CODE_FOR_mmx_subdi3, "__builtin_ia32_psubq", IX86_BUILTIN_PSUBQ, 0, 0 },
 
   { MASK_MMX, CODE_FOR_ssaddv8qi3, "__builtin_ia32_paddsb", IX86_BUILTIN_PADDSB, 0, 0 },
   { MASK_MMX, CODE_FOR_ssaddv4hi3, "__builtin_ia32_paddsw", IX86_BUILTIN_PADDSW, 0, 0 },
@@ -11824,6 +12840,7 @@ static const struct builtin_description bdesc_2arg[] =
 
   { MASK_SSE1, CODE_FOR_cvtpi2ps, 0, IX86_BUILTIN_CVTPI2PS, 0, 0 },
   { MASK_SSE1, CODE_FOR_cvtsi2ss, 0, IX86_BUILTIN_CVTSI2SS, 0, 0 },
+  { MASK_SSE164, CODE_FOR_cvtsi2ssq, 0, IX86_BUILTIN_CVTSI642SS, 0, 0 },
 
   { MASK_MMX, CODE_FOR_ashlv4hi3, 0, IX86_BUILTIN_PSLLW, 0, 0 },
   { MASK_MMX, CODE_FOR_ashlv4hi3, 0, IX86_BUILTIN_PSLLWI, 0, 0 },
@@ -11872,14 +12889,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 },
@@ -11887,10 +12900,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 },
@@ -11900,11 +12913,11 @@ static const struct builtin_description bdesc_2arg[] =
   { MASK_SSE2, CODE_FOR_addv16qi3, "__builtin_ia32_paddb128", IX86_BUILTIN_PADDB128, 0, 0 },
   { MASK_SSE2, CODE_FOR_addv8hi3, "__builtin_ia32_paddw128", IX86_BUILTIN_PADDW128, 0, 0 },
   { MASK_SSE2, CODE_FOR_addv4si3, "__builtin_ia32_paddd128", IX86_BUILTIN_PADDD128, 0, 0 },
-  { MASK_SSE2, CODE_FOR_addv4si3, "__builtin_ia32_paddq128", IX86_BUILTIN_PADDQ128, 0, 0 },
+  { MASK_SSE2, CODE_FOR_addv2di3, "__builtin_ia32_paddq128", IX86_BUILTIN_PADDQ128, 0, 0 },
   { MASK_SSE2, CODE_FOR_subv16qi3, "__builtin_ia32_psubb128", IX86_BUILTIN_PSUBB128, 0, 0 },
   { MASK_SSE2, CODE_FOR_subv8hi3, "__builtin_ia32_psubw128", IX86_BUILTIN_PSUBW128, 0, 0 },
   { MASK_SSE2, CODE_FOR_subv4si3, "__builtin_ia32_psubd128", IX86_BUILTIN_PSUBD128, 0, 0 },
-  { MASK_SSE2, CODE_FOR_subv4si3, "__builtin_ia32_psubq128", IX86_BUILTIN_PSUBQ128, 0, 0 },
+  { MASK_SSE2, CODE_FOR_subv2di3, "__builtin_ia32_psubq128", IX86_BUILTIN_PSUBQ128, 0, 0 },
 
   { MASK_MMX, CODE_FOR_ssaddv16qi3, "__builtin_ia32_paddsb128", IX86_BUILTIN_PADDSB128, 0, 0 },
   { MASK_MMX, CODE_FOR_ssaddv8hi3, "__builtin_ia32_paddsw128", IX86_BUILTIN_PADDSW128, 0, 0 },
@@ -11943,9 +12956,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 },
@@ -11976,6 +12991,7 @@ static const struct builtin_description bdesc_2arg[] =
   { MASK_SSE2, CODE_FOR_sse2_pmaddwd, 0, IX86_BUILTIN_PMADDWD128, 0, 0 },
 
   { MASK_SSE2, CODE_FOR_cvtsi2sd, 0, IX86_BUILTIN_CVTSI2SD, 0, 0 },
+  { MASK_SSE264, CODE_FOR_cvtsi2sdq, 0, IX86_BUILTIN_CVTSI642SD, 0, 0 },
   { MASK_SSE2, CODE_FOR_cvtsd2ss, 0, IX86_BUILTIN_CVTSD2SS, 0, 0 },
   { MASK_SSE2, CODE_FOR_cvtss2sd, 0, IX86_BUILTIN_CVTSS2SD, 0, 0 }
 };
@@ -11991,12 +13007,15 @@ static const struct builtin_description bdesc_1arg[] =
 
   { MASK_SSE1, CODE_FOR_cvtps2pi, 0, IX86_BUILTIN_CVTPS2PI, 0, 0 },
   { MASK_SSE1, CODE_FOR_cvtss2si, 0, IX86_BUILTIN_CVTSS2SI, 0, 0 },
+  { MASK_SSE164, CODE_FOR_cvtss2siq, 0, IX86_BUILTIN_CVTSS2SI64, 0, 0 },
   { MASK_SSE1, CODE_FOR_cvttps2pi, 0, IX86_BUILTIN_CVTTPS2PI, 0, 0 },
   { MASK_SSE1, CODE_FOR_cvttss2si, 0, IX86_BUILTIN_CVTTSS2SI, 0, 0 },
+  { MASK_SSE164, CODE_FOR_cvttss2siq, 0, IX86_BUILTIN_CVTTSS2SI64, 0, 0 },
 
   { 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 },
 
@@ -12013,10 +13032,14 @@ static const struct builtin_description bdesc_1arg[] =
 
   { MASK_SSE2, CODE_FOR_cvtsd2si, 0, IX86_BUILTIN_CVTSD2SI, 0, 0 },
   { MASK_SSE2, CODE_FOR_cvttsd2si, 0, IX86_BUILTIN_CVTTSD2SI, 0, 0 },
+  { MASK_SSE264, CODE_FOR_cvtsd2siq, 0, IX86_BUILTIN_CVTSD2SI64, 0, 0 },
+  { MASK_SSE264, CODE_FOR_cvttsd2siq, 0, IX86_BUILTIN_CVTTSD2SI64, 0, 0 },
 
   { 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
@@ -12036,7 +13059,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);
@@ -12052,11 +13079,18 @@ ix86_init_mmx_sse_builtins ()
   tree int_ftype_v4sf
     = build_function_type_list (integer_type_node,
                                V4SF_type_node, NULL_TREE);
+  tree int64_ftype_v4sf
+    = build_function_type_list (long_long_integer_type_node,
+                               V4SF_type_node, NULL_TREE);
   tree int_ftype_v8qi
     = build_function_type_list (integer_type_node, V8QI_type_node, NULL_TREE);
   tree v4sf_ftype_v4sf_int
     = build_function_type_list (V4SF_type_node,
                                V4SF_type_node, integer_type_node, NULL_TREE);
+  tree v4sf_ftype_v4sf_int64
+    = build_function_type_list (V4SF_type_node,
+                               V4SF_type_node, long_long_integer_type_node,
+                               NULL_TREE);
   tree v4sf_ftype_v4sf_v2si
     = build_function_type_list (V4SF_type_node,
                                V4SF_type_node, V2SI_type_node, NULL_TREE);
@@ -12109,15 +13143,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);
@@ -12165,21 +13199,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
@@ -12198,9 +13241,16 @@ ix86_init_mmx_sse_builtins ()
     = build_function_type_list (V2DF_type_node, V4SF_type_node, NULL_TREE);
   tree int_ftype_v2df
     = build_function_type_list (integer_type_node, V2DF_type_node, NULL_TREE);
+  tree int64_ftype_v2df
+    = build_function_type_list (long_long_integer_type_node,
+                               V2DF_type_node, NULL_TREE);
   tree v2df_ftype_v2df_int
     = build_function_type_list (V2DF_type_node,
                                V2DF_type_node, integer_type_node, NULL_TREE);
+  tree v2df_ftype_v2df_int64
+    = build_function_type_list (V2DF_type_node,
+                               V2DF_type_node, long_long_integer_type_node,
+                               NULL_TREE);
   tree v4sf_ftype_v4sf_v2df
     = build_function_type_list (V4SF_type_node,
                                V4SF_type_node, V2DF_type_node, NULL_TREE);
@@ -12228,8 +13278,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);
@@ -12288,6 +13338,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.  */
@@ -12361,8 +13423,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);
@@ -12388,26 +13448,26 @@ 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);
+  def_builtin (MASK_SSE164, "__builtin_ia32_cvtsi642ss", v4sf_ftype_v4sf_int64, IX86_BUILTIN_CVTSI642SS);
   def_builtin (MASK_SSE1, "__builtin_ia32_cvtss2si", int_ftype_v4sf, IX86_BUILTIN_CVTSS2SI);
+  def_builtin (MASK_SSE164, "__builtin_ia32_cvtss2si64", int64_ftype_v4sf, IX86_BUILTIN_CVTSS2SI64);
   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_SSE164, "__builtin_ia32_cvttss2si64", int64_ftype_v4sf, IX86_BUILTIN_CVTTSS2SI64);
 
   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);
@@ -12473,10 +13533,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);
@@ -12515,27 +13576,40 @@ ix86_init_mmx_sse_builtins ()
 
   def_builtin (MASK_SSE2, "__builtin_ia32_cvtsd2si", int_ftype_v2df, IX86_BUILTIN_CVTSD2SI);
   def_builtin (MASK_SSE2, "__builtin_ia32_cvttsd2si", int_ftype_v2df, IX86_BUILTIN_CVTTSD2SI);
+  def_builtin (MASK_SSE264, "__builtin_ia32_cvtsd2si64", int64_ftype_v2df, IX86_BUILTIN_CVTSD2SI64);
+  def_builtin (MASK_SSE264, "__builtin_ia32_cvttsd2si64", int64_ftype_v2df, IX86_BUILTIN_CVTTSD2SI64);
 
   def_builtin (MASK_SSE2, "__builtin_ia32_cvtps2dq", v4si_ftype_v4sf, IX86_BUILTIN_CVTPS2DQ);
   def_builtin (MASK_SSE2, "__builtin_ia32_cvtps2pd", v2df_ftype_v4sf, IX86_BUILTIN_CVTPS2PD);
   def_builtin (MASK_SSE2, "__builtin_ia32_cvttps2dq", v4si_ftype_v4sf, IX86_BUILTIN_CVTTPS2DQ);
 
   def_builtin (MASK_SSE2, "__builtin_ia32_cvtsi2sd", v2df_ftype_v2df_int, IX86_BUILTIN_CVTSI2SD);
+  def_builtin (MASK_SSE264, "__builtin_ia32_cvtsi642sd", v2df_ftype_v2df_int64, IX86_BUILTIN_CVTSI642SD);
   def_builtin (MASK_SSE2, "__builtin_ia32_cvtsd2ss", v4sf_ftype_v4sf_v2df, IX86_BUILTIN_CVTSD2SS);
   def_builtin (MASK_SSE2, "__builtin_ia32_cvtss2sd", v2df_ftype_v2df_v4sf, IX86_BUILTIN_CVTSS2SD);
 
   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);
@@ -12547,10 +13621,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);
@@ -12578,7 +13654,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;
 }
 
@@ -12609,6 +13686,13 @@ ix86_expand_binop_builtin (icode, arglist, target)
       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
     target = gen_reg_rtx (tmode);
 
+  if (GET_MODE (op1) == SImode && mode1 == TImode)
+    {
+      rtx x = gen_reg_rtx (V4SImode);
+      emit_insn (gen_sse2_loadd (x, op1));
+      op1 = gen_lowpart (TImode, x);
+    }
+
   /* In case the insn wants input operands in modes different from
      the result, abort.  */
   if (GET_MODE (op0) != mode0 || GET_MODE (op1) != mode1)
@@ -12632,45 +13716,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
@@ -12690,9 +13735,7 @@ ix86_expand_store_builtin (icode, arglist)
     op1 = safe_vector_operand (op1, mode1);
 
   op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
-
-  if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
-    op1 = copy_to_mode_reg (mode1, op1);
+  op1 = copy_to_mode_reg (mode1, op1);
 
   pat = GEN_FCN (icode) (op0, op1);
   if (pat)
@@ -12868,14 +13911,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);
@@ -12983,9 +14026,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));
@@ -13016,19 +14061,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);
 
@@ -13037,6 +14069,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);
 
@@ -13187,6 +14220,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;
@@ -13268,7 +14330,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:
@@ -13276,6 +14338,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:
@@ -13333,6 +14401,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;
@@ -13344,9 +14417,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;
@@ -13358,6 +14430,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;
     }
@@ -13505,6 +14591,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.  */
@@ -13563,10 +14651,10 @@ ix86_secondary_memory_needed (class1, class2, mode, strict)
        return 1;
     }
   return (FLOAT_CLASS_P (class1) != FLOAT_CLASS_P (class2)
-         || (SSE_CLASS_P (class1) != SSE_CLASS_P (class2)
-             && (mode) != SImode)
-         || (MMX_CLASS_P (class1) != MMX_CLASS_P (class2)
-             && (mode) != SImode));
+         || ((SSE_CLASS_P (class1) != SSE_CLASS_P (class2)
+              || MMX_CLASS_P (class1) != MMX_CLASS_P (class2))
+             && ((mode != SImode && (mode != DImode || !TARGET_64BIT))
+                 || (!TARGET_INTER_UNIT_MOVES && !optimize_size))));
 }
 /* Return the cost of moving data from a register in class CLASS1 to
    one in class CLASS2.
@@ -13594,7 +14682,7 @@ ix86_register_move_cost (mode, class1, class2)
       
       /* 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.  */
+         Count this as arbitrarily high cost of 20.  */
       if (CLASS_MAX_NREGS (class1, mode) > CLASS_MAX_NREGS (class2, mode))
        cost += 20;
 
@@ -13739,13 +14827,266 @@ 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)
+/* 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;
+         default: /* Other constants */
+           *total = 2;
+           break;
+         case 0:
+         case -1:
+           /* 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;
 {
@@ -13851,7 +15192,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;
@@ -13865,77 +15206,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));
+}
 
-  xops[0] = GEN_INT (delta);
+/* Determine whether x86_output_mi_thunk can succeed.  */
+
+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, GOT_SYMBOL_NAME);
+         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);
        }
     }
 }
@@ -13959,9 +15477,49 @@ x86_field_alignment (field, 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
@@ -13970,7 +15528,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)
   {
@@ -13981,25 +15539,104 @@ 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);
+}
+
+/* Generate an unsigned DImode to FP conversion.  This is the same code
+   optabs would emit if we didn't have TFmode patterns.  */
+
+void
+x86_emit_floatuns (operands)
+     rtx operands[2];
+{
+  rtx neglab, donelab, i0, i1, f0, in, out;
+  enum machine_mode mode;
+
+  out = operands[0];
+  in = force_reg (DImode, operands[1]);
+  mode = GET_MODE (out);
+  neglab = gen_label_rtx ();
+  donelab = gen_label_rtx ();
+  i1 = gen_reg_rtx (Pmode);
+  f0 = gen_reg_rtx (mode);
+
+  emit_cmp_and_jump_insns (in, const0_rtx, LT, const0_rtx, Pmode, 0, neglab);
+
+  emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_FLOAT (mode, in)));
+  emit_jump_insn (gen_jump (donelab));
+  emit_barrier ();
+
+  emit_label (neglab);
+
+  i0 = expand_simple_binop (Pmode, LSHIFTRT, in, const1_rtx, NULL, 1, OPTAB_DIRECT);
+  i1 = expand_simple_binop (Pmode, AND, in, const1_rtx, NULL, 1, OPTAB_DIRECT);
+  i0 = expand_simple_binop (Pmode, IOR, i0, i1, i0, 1, OPTAB_DIRECT);
+  expand_float (f0, i0, 0);
+  emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_PLUS (mode, f0, f0)));
+
+  emit_label (donelab);
+}
+
 #include "gt-i386.h"