OSDN Git Service

PR target/44074
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.c
index 5387fae..a54651d 100644 (file)
@@ -819,6 +819,93 @@ struct processor_costs amdfam10_cost = {
   1,                                    /* cond_not_taken_branch_cost.  */
 };
 
+struct processor_costs bdver1_cost = {
+  COSTS_N_INSNS (1),                    /* cost of an add instruction */
+  COSTS_N_INSNS (2),                    /* cost of a lea instruction */
+  COSTS_N_INSNS (1),                    /* variable shift costs */
+  COSTS_N_INSNS (1),                    /* constant shift costs */
+  {COSTS_N_INSNS (3),                   /* cost of starting multiply for QI */
+   COSTS_N_INSNS (4),                   /*                               HI */
+   COSTS_N_INSNS (3),                   /*                               SI */
+   COSTS_N_INSNS (4),                   /*                               DI */
+   COSTS_N_INSNS (5)},                  /*                               other */
+  0,                                    /* cost of multiply per each bit set */
+  {COSTS_N_INSNS (19),                  /* cost of a divide/mod for QI */
+   COSTS_N_INSNS (35),                  /*                          HI */
+   COSTS_N_INSNS (51),                  /*                          SI */
+   COSTS_N_INSNS (83),                  /*                          DI */
+   COSTS_N_INSNS (83)},                 /*                          other */
+  COSTS_N_INSNS (1),                   /* cost of movsx */
+  COSTS_N_INSNS (1),                   /* cost of movzx */
+  8,                                   /* "large" insn */
+  9,                                   /* MOVE_RATIO */
+  4,                                   /* cost for loading QImode using movzbl */
+  {3, 4, 3},                           /* cost of loading integer registers
+                                          in QImode, HImode and SImode.
+                                          Relative to reg-reg move (2).  */
+  {3, 4, 3},                           /* cost of storing integer registers */
+  4,                                   /* cost of reg,reg fld/fst */
+  {4, 4, 12},                          /* cost of loading fp registers
+                                          in SFmode, DFmode and XFmode */
+  {6, 6, 8},                           /* cost of storing fp registers
+                                          in SFmode, DFmode and XFmode */
+  2,                                   /* cost of moving MMX register */
+  {3, 3},                              /* cost of loading MMX registers
+                                          in SImode and DImode */
+  {4, 4},                              /* cost of storing MMX registers
+                                          in SImode and DImode */
+  2,                                   /* cost of moving SSE register */
+  {4, 4, 3},                           /* cost of loading SSE registers
+                                          in SImode, DImode and TImode */
+  {4, 4, 5},                           /* cost of storing SSE registers
+                                          in SImode, DImode and TImode */
+  3,                                   /* MMX or SSE register to integer */
+                                       /* On K8
+                                           MOVD reg64, xmmreg  Double  FSTORE 4
+                                           MOVD reg32, xmmreg  Double  FSTORE 4
+                                          On AMDFAM10
+                                           MOVD reg64, xmmreg  Double  FADD 3
+                                                                1/1  1/1
+                                           MOVD reg32, xmmreg  Double  FADD 3
+                                                                1/1  1/1 */
+  64,                                  /* size of l1 cache.  */
+  1024,                                        /* size of l2 cache.  */
+  64,                                  /* size of prefetch block */
+  /* New AMD processors never drop prefetches; if they cannot be performed
+     immediately, they are queued.  We set number of simultaneous prefetches
+     to a large constant to reflect this (it probably is not a good idea not
+     to limit number of prefetches at all, as their execution also takes some
+     time).  */
+  100,                                 /* number of parallel prefetches */
+  2,                                   /* Branch cost */
+  COSTS_N_INSNS (4),                   /* cost of FADD and FSUB insns.  */
+  COSTS_N_INSNS (4),                   /* cost of FMUL instruction.  */
+  COSTS_N_INSNS (19),                  /* cost of FDIV instruction.  */
+  COSTS_N_INSNS (2),                   /* cost of FABS instruction.  */
+  COSTS_N_INSNS (2),                   /* cost of FCHS instruction.  */
+  COSTS_N_INSNS (35),                  /* cost of FSQRT instruction.  */
+
+  /*  BDVER1 has optimized REP instruction for medium sized blocks, but for
+      very small blocks it is better to use loop. For large blocks, libcall can
+      do nontemporary accesses and beat inline considerably.  */
+  {{libcall, {{6, loop}, {14, unrolled_loop}, {-1, rep_prefix_4_byte}}},
+   {libcall, {{16, loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+  {{libcall, {{8, loop}, {24, unrolled_loop},
+             {2048, rep_prefix_4_byte}, {-1, libcall}}},
+   {libcall, {{48, unrolled_loop}, {8192, rep_prefix_8_byte}, {-1, libcall}}}},
+  4,                                    /* scalar_stmt_cost.  */
+  2,                                    /* scalar load_cost.  */
+  2,                                    /* scalar_store_cost.  */
+  6,                                    /* vec_stmt_cost.  */
+  0,                                    /* vec_to_scalar_cost.  */
+  2,                                    /* scalar_to_vec_cost.  */
+  2,                                    /* vec_align_load_cost.  */
+  2,                                    /* vec_unalign_load_cost.  */
+  2,                                    /* vec_store_cost.  */
+  2,                                    /* cond_taken_branch_cost.  */
+  1,                                    /* cond_not_taken_branch_cost.  */
+};
+
 static const
 struct processor_costs pentium4_cost = {
   COSTS_N_INSNS (1),                   /* cost of an add instruction */
@@ -1276,7 +1363,8 @@ const struct processor_costs *ix86_cost = &pentium_cost;
 #define m_ATHLON  (1<<PROCESSOR_ATHLON)
 #define m_ATHLON_K8  (m_K8 | m_ATHLON)
 #define m_AMDFAM10  (1<<PROCESSOR_AMDFAM10)
-#define m_AMD_MULTIPLE  (m_K8 | m_ATHLON | m_AMDFAM10)
+#define m_BDVER1  (1<<PROCESSOR_BDVER1)
+#define m_AMD_MULTIPLE  (m_K8 | m_ATHLON | m_AMDFAM10 | m_BDVER1)
 
 #define m_GENERIC32 (1<<PROCESSOR_GENERIC32)
 #define m_GENERIC64 (1<<PROCESSOR_GENERIC64)
@@ -1321,7 +1409,7 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
   ~m_386,
 
   /* X86_TUNE_USE_SAHF */
-  m_ATOM | m_PPRO | m_K6_GEODE | m_K8 | m_AMDFAM10 | m_PENT4
+  m_ATOM | m_PPRO | m_K6_GEODE | m_K8 | m_AMDFAM10 | m_BDVER1 | m_PENT4
   | m_NOCONA | m_CORE2 | m_GENERIC,
 
   /* X86_TUNE_MOVX: Enable to zero extend integer registers to avoid
@@ -1425,10 +1513,16 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
      while enabling it on K8 brings roughly 2.4% regression that can be partly
      masked by careful scheduling of moves.  */
   m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 | m_GENERIC
-  | m_AMDFAM10,
+  | m_AMDFAM10 | m_BDVER1,
 
-  /* X86_TUNE_SSE_UNALIGNED_MOVE_OPTIMAL */
-  m_AMDFAM10,
+  /* X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL */
+  m_AMDFAM10 | m_BDVER1,
+
+  /* X86_TUNE_SSE_UNALIGNED_STORE_OPTIMAL */
+  m_BDVER1,
+
+  /* X86_TUNE_SSE_PACKED_SINGLE_INSN_OPTIMAL */
+  m_BDVER1,
 
   /* X86_TUNE_SSE_SPLIT_REGS: Set for machines where the type and dependencies
      are resolved on SSE register parts instead of whole registers, so we may
@@ -1461,7 +1555,7 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
   ~(m_AMD_MULTIPLE | m_GENERIC),
 
   /* X86_TUNE_INTER_UNIT_CONVERSIONS */
-  ~(m_AMDFAM10),
+  ~(m_AMDFAM10 | m_BDVER1),
 
   /* X86_TUNE_FOUR_JUMP_LIMIT: Some CPU cores are not able to predict more
      than 4 branch instructions in the 16 byte window.  */
@@ -1497,11 +1591,11 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
 
   /* X86_TUNE_SLOW_IMUL_IMM32_MEM: Imul of 32-bit constant and memory is
      vector path on AMD machines.  */
-  m_K8 | m_GENERIC64 | m_AMDFAM10,
+  m_K8 | m_GENERIC64 | m_AMDFAM10 | m_BDVER1,
 
   /* X86_TUNE_SLOW_IMUL_IMM8: Imul of 8-bit constant is vector path on AMD
      machines.  */
-  m_K8 | m_GENERIC64 | m_AMDFAM10,
+  m_K8 | m_GENERIC64 | m_AMDFAM10 | m_BDVER1,
 
   /* X86_TUNE_MOVE_M1_VIA_OR: On pentiums, it is faster to load -1 via OR
      than a MOV.  */
@@ -1527,7 +1621,7 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = {
   /* X86_TUNE_FUSE_CMP_AND_BRANCH: Fuse a compare or test instruction
      with a subsequent conditional jump instruction into a single
      compare-and-branch uop.  */
-  m_CORE2,
+  m_CORE2 | m_BDVER1,
 
   /* X86_TUNE_OPT_AGU: Optimize for Address Generation Unit. This flag
      will impact LEA instruction selection. */
@@ -1880,6 +1974,7 @@ static bool ext_80387_constants_init = 0;
 \f
 static struct machine_function * ix86_init_machine_status (void);
 static rtx ix86_function_value (const_tree, const_tree, bool);
+static bool ix86_function_value_regno_p (const unsigned int);
 static rtx ix86_static_chain (const_tree, bool);
 static int ix86_function_regparm (const_tree, const_tree);
 static void ix86_compute_frame_layout (struct ix86_frame *);
@@ -2066,6 +2161,7 @@ static const struct ptt processor_target_table[PROCESSOR_max] =
   {&generic32_cost, 16, 7, 16, 7, 16},
   {&generic64_cost, 16, 10, 16, 10, 16},
   {&amdfam10_cost, 32, 24, 32, 7, 32},
+  {&bdver1_cost, 32, 24, 32, 7, 32},
   {&atom_cost, 16, 7, 16, 7, 16}
 };
 
@@ -2092,7 +2188,8 @@ static const char *const cpu_names[TARGET_CPU_DEFAULT_max] =
   "athlon",
   "athlon-4",
   "k8",
-  "amdfam10"
+  "amdfam10",
+  "bdver1"
 };
 \f
 /* Implement TARGET_HANDLE_OPTION.  */
@@ -2512,7 +2609,7 @@ ix86_target_string (int isa, int flags, const char *arch, const char *tune,
   if (isa && add_nl_p)
     {
       opts[num++][0] = isa_other;
-      sprintf (isa_other, "(other isa: 0x%x)", isa);
+      sprintf (isa_other, "(other isa: %#x)", isa);
     }
 
   /* Add flag options.  */
@@ -2528,7 +2625,7 @@ ix86_target_string (int isa, int flags, const char *arch, const char *tune,
   if (flags && add_nl_p)
     {
       opts[num++][0] = target_other;
-      sprintf (target_other, "(other flags: 0x%x)", isa);
+      sprintf (target_other, "(other flags: %#x)", flags);
     }
 
   /* Add -fpmath= option.  */
@@ -2750,6 +2847,11 @@ override_options (bool main_args_p)
       {"barcelona", PROCESSOR_AMDFAM10, CPU_AMDFAM10,
        PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
        | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM},
+      {"bdver1", PROCESSOR_BDVER1, CPU_BDVER1,
+       PTA_64BIT | PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_SSE
+       | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM
+       | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES 
+       | PTA_PCLMUL | PTA_AVX | PTA_FMA4 | PTA_XOP | PTA_LWP},
       {"generic32", PROCESSOR_GENERIC32, CPU_PENTIUMPRO,
        0 /* flags are only used for -march switch.  */ },
       {"generic64", PROCESSOR_GENERIC64, CPU_GENERIC64,
@@ -4288,6 +4390,10 @@ optimization_options (int level, int size ATTRIBUTE_UNUSED)
     flag_schedule_insns = 0;
 #endif
 
+  /* For -O2 and beyond, turn on -fzee for x86_64 target. */
+  if (level > 1 && TARGET_64BIT)
+    flag_zee = 1;
+
   if (TARGET_MACHO)
     /* The Darwin libraries never set errno, so we might as well
        avoid calling them when that's the only reason we would.  */
@@ -4395,8 +4501,8 @@ ix86_function_ok_for_sibcall (tree decl, tree exp)
   return true;
 }
 
-/* Handle "cdecl", "stdcall", "fastcall", "regparm" and "sseregparm"
-   calling convention attributes;
+/* Handle "cdecl", "stdcall", "fastcall", "regparm", "thiscall",
+   and "sseregparm" calling convention attributes;
    arguments as in struct attribute_spec.handler.  */
 
 static tree
@@ -4426,6 +4532,11 @@ ix86_handle_cconv_attribute (tree *node, tree name,
          error ("fastcall and regparm attributes are not compatible");
        }
 
+      if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (*node)))
+       {
+         error ("regparam and thiscall attributes are not compatible");
+       }
+
       cst = TREE_VALUE (args);
       if (TREE_CODE (cst) != INTEGER_CST)
        {
@@ -4471,6 +4582,10 @@ ix86_handle_cconv_attribute (tree *node, tree name,
         {
          error ("fastcall and regparm attributes are not compatible");
        }
+      if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (*node)))
+       {
+         error ("fastcall and thiscall attributes are not compatible");
+       }
     }
 
   /* Can combine stdcall with fastcall (redundant), regparm and
@@ -4485,6 +4600,10 @@ ix86_handle_cconv_attribute (tree *node, tree name,
         {
          error ("stdcall and fastcall attributes are not compatible");
        }
+      if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (*node)))
+       {
+         error ("stdcall and thiscall attributes are not compatible");
+       }
     }
 
   /* Can combine cdecl with regparm and sseregparm.  */
@@ -4498,6 +4617,28 @@ ix86_handle_cconv_attribute (tree *node, tree name,
         {
          error ("fastcall and cdecl attributes are not compatible");
        }
+      if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (*node)))
+       {
+         error ("cdecl and thiscall attributes are not compatible");
+       }
+    }
+  else if (is_attribute_p ("thiscall", name))
+    {
+      if (TREE_CODE (*node) != METHOD_TYPE && pedantic)
+       warning (OPT_Wattributes, "%qE attribute is used for none class-method",
+                name);
+      if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (*node)))
+       {
+         error ("stdcall and thiscall attributes are not compatible");
+       }
+      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (*node)))
+       {
+         error ("fastcall and thiscall attributes are not compatible");
+       }
+      if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (*node)))
+       {
+         error ("cdecl and thiscall attributes are not compatible");
+       }
     }
 
   /* Can combine sseregparm with all attributes.  */
@@ -4531,6 +4672,11 @@ ix86_comp_type_attributes (const_tree type1, const_tree type2)
       != !lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type2)))
     return 0;
 
+  /* Check for mismatched thiscall types.  */
+  if (!lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type1))
+      != !lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type2)))
+    return 0;
+
   /* Check for mismatched return types (cdecl vs stdcall).  */
   if (!lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type1))
       != !lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type2)))
@@ -4564,6 +4710,9 @@ ix86_function_regparm (const_tree type, const_tree decl)
   if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
     return 2;
 
+  if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type)))
+    return 1;
+
   /* Use register calling convention for local functions when possible.  */
   if (decl
       && TREE_CODE (decl) == FUNCTION_DECL
@@ -4701,7 +4850,8 @@ ix86_return_pops_args (tree fundecl, tree funtype, int size)
       /* Stdcall and fastcall functions will pop the stack if not
          variable args.  */
       if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))
-          || lookup_attribute ("fastcall", TYPE_ATTRIBUTES (funtype)))
+         || lookup_attribute ("fastcall", TYPE_ATTRIBUTES (funtype))
+          || lookup_attribute ("thiscall", TYPE_ATTRIBUTES (funtype)))
        rtd = 1;
 
       if (rtd && ! stdarg_p (funtype))
@@ -4964,7 +5114,12 @@ init_cumulative_args (CUMULATIVE_ARGS *cum,  /* Argument info to initialize */
         else look for regparm information.  */
       if (fntype)
        {
-         if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
+         if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (fntype)))
+           {
+             cum->nregs = 1;
+             cum->fastcall = 1; /* Same first register as in fastcall.  */
+           }
+         else if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
            {
              cum->nregs = 2;
              cum->fastcall = 1;
@@ -6282,8 +6437,8 @@ ix86_function_arg_boundary (enum machine_mode mode, tree type)
 
 /* Return true if N is a possible register number of function value.  */
 
-bool
-ix86_function_value_regno_p (int regno)
+static bool
+ix86_function_value_regno_p (const unsigned int regno)
 {
   switch (regno)
     {
@@ -6741,7 +6896,6 @@ setup_incoming_varargs_64 (CUMULATIVE_ARGS *cum)
 {
   rtx save_area, mem;
   rtx label;
-  rtx label_ref;
   rtx tmp_reg;
   rtx nsse_reg;
   alias_set_type set;
@@ -6792,35 +6946,9 @@ setup_incoming_varargs_64 (CUMULATIVE_ARGS *cum)
         SSE saves.  We need some preparation work to get this working.  */
 
       label = gen_label_rtx ();
-      label_ref = gen_rtx_LABEL_REF (Pmode, label);
 
-      /* Compute address to jump to :
-         label - eax*4 + nnamed_sse_arguments*4 Or
-         label - eax*5 + nnamed_sse_arguments*5 for AVX.  */
-      tmp_reg = gen_reg_rtx (Pmode);
       nsse_reg = gen_reg_rtx (Pmode);
       emit_insn (gen_zero_extendqidi2 (nsse_reg, gen_rtx_REG (QImode, AX_REG)));
-      emit_insn (gen_rtx_SET (VOIDmode, tmp_reg,
-                             gen_rtx_MULT (Pmode, nsse_reg,
-                                           GEN_INT (4))));
-
-      /* vmovaps is one byte longer than movaps.  */
-      if (TARGET_AVX)
-       emit_insn (gen_rtx_SET (VOIDmode, tmp_reg,
-                               gen_rtx_PLUS (Pmode, tmp_reg,
-                                             nsse_reg)));
-
-      if (cum->sse_regno)
-       emit_move_insn
-         (nsse_reg,
-          gen_rtx_CONST (DImode,
-                         gen_rtx_PLUS (DImode,
-                                       label_ref,
-                                       GEN_INT (cum->sse_regno
-                                                * (TARGET_AVX ? 5 : 4)))));
-      else
-       emit_move_insn (nsse_reg, label_ref);
-      emit_insn (gen_subdi3 (nsse_reg, nsse_reg, tmp_reg));
 
       /* Compute address of memory block we save into.  We always use pointer
         pointing 127 bytes after first byte to store - this is needed to keep
@@ -6833,11 +6961,12 @@ setup_incoming_varargs_64 (CUMULATIVE_ARGS *cum)
       mem = gen_rtx_MEM (BLKmode, plus_constant (tmp_reg, -127));
       MEM_NOTRAP_P (mem) = 1;
       set_mem_alias_set (mem, set);
-      set_mem_align (mem, BITS_PER_WORD);
+      set_mem_align (mem, 64);
 
       /* And finally do the dirty job!  */
       emit_insn (gen_sse_prologue_save (mem, nsse_reg,
-                                       GEN_INT (cum->sse_regno), label));
+                                       GEN_INT (cum->sse_regno), label,
+                                       gen_reg_rtx (Pmode)));
     }
 }
 
@@ -6998,7 +7127,7 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
   int indirect_p = 0;
   tree ptrtype;
   enum machine_mode nat_mode;
-  int arg_boundary;
+  unsigned int arg_boundary;
 
   /* Only 64bit target needs something special.  */
   if (!TARGET_64BIT || is_va_list_char_pointer (TREE_TYPE (valist)))
@@ -7230,6 +7359,8 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
       t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
                  size_int (-align));
       t = fold_convert (TREE_TYPE (ovf), t);
+      if (crtl->stack_alignment_needed < arg_boundary)
+       crtl->stack_alignment_needed = arg_boundary;
     }
   gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
   gimplify_assign (addr, t, pre_p);
@@ -7439,15 +7570,27 @@ standard_sse_constant_opcode (rtx insn, rtx x)
        case MODE_V4SF:
          return TARGET_AVX ? "vxorps\t%0, %0, %0" : "xorps\t%0, %0";
        case MODE_V2DF:
-         return TARGET_AVX ? "vxorpd\t%0, %0, %0" : "xorpd\t%0, %0";
+         if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
+           return TARGET_AVX ? "vxorps\t%0, %0, %0" : "xorps\t%0, %0";
+         else
+           return TARGET_AVX ? "vxorpd\t%0, %0, %0" : "xorpd\t%0, %0";     
        case MODE_TI:
-         return TARGET_AVX ? "vpxor\t%0, %0, %0" : "pxor\t%0, %0";
+         if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
+           return TARGET_AVX ? "vxorps\t%0, %0, %0" : "xorps\t%0, %0";
+         else
+           return TARGET_AVX ? "vpxor\t%0, %0, %0" : "pxor\t%0, %0";
        case MODE_V8SF:
          return "vxorps\t%x0, %x0, %x0";
        case MODE_V4DF:
-         return "vxorpd\t%x0, %x0, %x0";
+         if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
+           return "vxorps\t%x0, %x0, %x0";
+         else
+           return "vxorpd\t%x0, %x0, %x0";
        case MODE_OI:
-         return "vpxor\t%x0, %x0, %x0";
+         if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
+           return "vxorps\t%x0, %x0, %x0";
+         else
+           return "vpxor\t%x0, %x0, %x0";
        default:
          break;
        }
@@ -7985,6 +8128,7 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
       && cfun->machine->use_fast_prologue_epilogue_nregs != frame->nregs)
     {
       int count = frame->nregs;
+      struct cgraph_node *node = cgraph_node (current_function_decl);
 
       cfun->machine->use_fast_prologue_epilogue_nregs = count;
       /* The fast prologue uses move instead of push to save registers.  This
@@ -7999,9 +8143,9 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
         slow to use many of them.  */
       if (count)
        count = (count - 1) * FAST_PROLOGUE_INSN_COUNT;
-      if (cfun->function_frequency < FUNCTION_FREQUENCY_NORMAL
+      if (node->frequency < NODE_FREQUENCY_NORMAL
          || (flag_branch_probabilities
-             && cfun->function_frequency < FUNCTION_FREQUENCY_HOT))
+             && node->frequency < NODE_FREQUENCY_HOT))
         cfun->machine->use_fast_prologue_epilogue = false;
       else
         cfun->machine->use_fast_prologue_epilogue
@@ -8303,6 +8447,8 @@ find_drap_reg (void)
          passing.  */
       if (ix86_function_regparm (TREE_TYPE (decl), decl) <= 2
          && !lookup_attribute ("fastcall",
+                               TYPE_ATTRIBUTES (TREE_TYPE (decl)))
+         && !lookup_attribute ("thiscall",
                                TYPE_ATTRIBUTES (TREE_TYPE (decl))))
        return CX_REG;
       else
@@ -9330,6 +9476,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
   rtx base_reg, index_reg;
   HOST_WIDE_INT scale = 1;
   rtx scale_rtx = NULL_RTX;
+  rtx tmp;
   int retval = 1;
   enum ix86_address_seg seg = SEG_DEFAULT;
 
@@ -9365,6 +9512,19 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
              scale_rtx = XEXP (op, 1);
              break;
 
+           case ASHIFT:
+             if (index)
+               return 0;
+             index = XEXP (op, 0);
+             tmp = XEXP (op, 1);
+             if (!CONST_INT_P (tmp))
+               return 0;
+             scale = INTVAL (tmp);
+             if ((unsigned HOST_WIDE_INT) scale > 3)
+               return 0;
+             scale = 1 << scale;
+             break;
+
            case UNSPEC:
              if (XINT (op, 1) == UNSPEC_TP
                  && TARGET_TLS_DIRECT_SEG_REFS
@@ -9405,8 +9565,6 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
     }
   else if (GET_CODE (addr) == ASHIFT)
     {
-      rtx tmp;
-
       /* We're called for lea too, which implements ashift on occasion.  */
       index = XEXP (addr, 0);
       tmp = XEXP (addr, 1);
@@ -10973,7 +11131,10 @@ ix86_delegitimize_address (rtx x)
          || XINT (XEXP (x, 0), 1) != UNSPEC_GOTPCREL
          || !MEM_P (orig_x))
        return orig_x;
-      return XVECEXP (XEXP (x, 0), 0, 0);
+      x = XVECEXP (XEXP (x, 0), 0, 0);
+      if (GET_MODE (orig_x) != Pmode)
+       return simplify_gen_subreg (GET_MODE (orig_x), x, Pmode, 0);
+      return x;
     }
 
   if (GET_CODE (x) != PLUS
@@ -11040,6 +11201,8 @@ ix86_delegitimize_address (rtx x)
       else
        return orig_x;
     }
+  if (GET_MODE (orig_x) != Pmode && MEM_P (orig_x))
+    return simplify_gen_subreg (GET_MODE (orig_x), result, Pmode, 0);
   return result;
 }
 
@@ -11380,7 +11543,7 @@ get_some_local_dynamic_name (void)
     return cfun->machine->some_ld_name;
 
   for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
-    if (INSN_P (insn)
+    if (NONDEBUG_INSN_P (insn)
        && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
       return cfun->machine->some_ld_name;
 
@@ -11893,10 +12056,8 @@ print_operand (FILE *file, rtx x, int code)
          return;
 
        case ';':
-#if TARGET_MACHO
-         fputs (" ; ", file);
-#else
-         putc (' ', file);
+#if TARGET_MACHO || !HAVE_AS_IX86_REP_LOCK_PREFIX
+         fputs (";", file);
 #endif
          return;
 
@@ -13183,6 +13344,14 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
          switch (GET_MODE_SIZE (mode))
            {
            case 16:
+             /*  If we're optimizing for size, movups is the smallest.  */
+             if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
+               {
+                 op0 = gen_lowpart (V4SFmode, op0);
+                 op1 = gen_lowpart (V4SFmode, op1);
+                 emit_insn (gen_avx_movups (op0, op1));
+                 return;
+               }
              op0 = gen_lowpart (V16QImode, op0);
              op1 = gen_lowpart (V16QImode, op1);
              emit_insn (gen_avx_movdqu (op0, op1));
@@ -13209,6 +13378,13 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
              emit_insn (gen_avx_movups256 (op0, op1));
              break;
            case V2DFmode:
+             if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
+               {
+                 op0 = gen_lowpart (V4SFmode, op0);
+                 op1 = gen_lowpart (V4SFmode, op1);
+                 emit_insn (gen_avx_movups (op0, op1));
+                 return;
+               }
              emit_insn (gen_avx_movupd (op0, op1));
              break;
            case V4DFmode:
@@ -13229,7 +13405,8 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
   if (MEM_P (op1))
     {
       /* If we're optimizing for size, movups is the smallest.  */
-      if (optimize_insn_for_size_p ())
+      if (optimize_insn_for_size_p () 
+         || TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
        {
          op0 = gen_lowpart (V4SFmode, op0);
          op1 = gen_lowpart (V4SFmode, op1);
@@ -13252,13 +13429,13 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
         {
           rtx zero;
 
-          if (TARGET_SSE_UNALIGNED_MOVE_OPTIMAL)
-            {
-              op0 = gen_lowpart (V2DFmode, op0);
-              op1 = gen_lowpart (V2DFmode, op1);
-              emit_insn (gen_sse2_movupd (op0, op1));
-              return;
-            }
+         if (TARGET_SSE_UNALIGNED_LOAD_OPTIMAL)
+           {
+             op0 = gen_lowpart (V2DFmode, op0);
+             op1 = gen_lowpart (V2DFmode, op1);
+             emit_insn (gen_sse2_movupd (op0, op1));
+             return;
+           }
 
          /* When SSE registers are split into halves, we can avoid
             writing to the top half twice.  */
@@ -13287,12 +13464,12 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
        }
       else
         {
-          if (TARGET_SSE_UNALIGNED_MOVE_OPTIMAL)
-            {
-              op0 = gen_lowpart (V4SFmode, op0);
-              op1 = gen_lowpart (V4SFmode, op1);
-              emit_insn (gen_sse_movups (op0, op1));
-              return;
+         if (TARGET_SSE_UNALIGNED_LOAD_OPTIMAL)
+           {
+             op0 = gen_lowpart (V4SFmode, op0);
+             op1 = gen_lowpart (V4SFmode, op1);
+             emit_insn (gen_sse_movups (op0, op1));
+             return;
             }
 
          if (TARGET_SSE_PARTIAL_REG_DEPENDENCY)
@@ -13311,7 +13488,8 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
   else if (MEM_P (op0))
     {
       /* If we're optimizing for size, movups is the smallest.  */
-      if (optimize_insn_for_size_p ())
+      if (optimize_insn_for_size_p ()
+         || TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
        {
          op0 = gen_lowpart (V4SFmode, op0);
          op1 = gen_lowpart (V4SFmode, op1);
@@ -13332,19 +13510,37 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
 
       if (TARGET_SSE2 && mode == V2DFmode)
        {
-         m = adjust_address (op0, DFmode, 0);
-         emit_insn (gen_sse2_storelpd (m, op1));
-         m = adjust_address (op0, DFmode, 8);
-         emit_insn (gen_sse2_storehpd (m, op1));
+         if (TARGET_SSE_UNALIGNED_STORE_OPTIMAL)
+           {
+             op0 = gen_lowpart (V2DFmode, op0);
+             op1 = gen_lowpart (V2DFmode, op1);
+             emit_insn (gen_sse2_movupd (op0, op1));         
+           }
+         else
+           {
+             m = adjust_address (op0, DFmode, 0);
+             emit_insn (gen_sse2_storelpd (m, op1));
+             m = adjust_address (op0, DFmode, 8);
+             emit_insn (gen_sse2_storehpd (m, op1));
+           }
        }
       else
        {
          if (mode != V4SFmode)
            op1 = gen_lowpart (V4SFmode, op1);
-         m = adjust_address (op0, V2SFmode, 0);
-         emit_insn (gen_sse_storelps (m, op1));
-         m = adjust_address (op0, V2SFmode, 8);
-         emit_insn (gen_sse_storehps (m, op1));
+
+         if (TARGET_SSE_UNALIGNED_STORE_OPTIMAL)
+           {
+             op0 = gen_lowpart (V4SFmode, op0);
+             emit_insn (gen_sse_movups (op0, op1));          
+           }
+         else
+           {
+             m = adjust_address (op0, V2SFmode, 0);
+             emit_insn (gen_sse_storelps (m, op1));
+             m = adjust_address (op0, V2SFmode, 8);
+             emit_insn (gen_sse_storehps (m, op1));
+           }
        }
     }
   else
@@ -13626,7 +13822,7 @@ distance_non_agu_define (unsigned int regno1, unsigned int regno2,
       rtx prev = PREV_INSN (insn);
       while (prev && distance < LEA_SEARCH_THRESHOLD)
        {
-         if (INSN_P (prev))
+         if (NONDEBUG_INSN_P (prev))
            {
              distance++;
               for (def_rec = DF_INSN_DEFS (prev); *def_rec; def_rec++)
@@ -13666,7 +13862,7 @@ distance_non_agu_define (unsigned int regno1, unsigned int regno2,
                 && prev != insn
                 && distance < LEA_SEARCH_THRESHOLD)
            {
-             if (INSN_P (prev))
+             if (NONDEBUG_INSN_P (prev))
                {
                  distance++;
                  for (def_rec = DF_INSN_DEFS (prev); *def_rec; def_rec++)
@@ -13712,7 +13908,7 @@ distance_agu_use (unsigned int regno0, rtx insn)
       rtx next = NEXT_INSN (insn);
       while (next && distance < LEA_SEARCH_THRESHOLD)
        {
-         if (INSN_P (next))
+         if (NONDEBUG_INSN_P (next))
            {
              distance++;
 
@@ -13761,7 +13957,7 @@ distance_agu_use (unsigned int regno0, rtx insn)
                 && next != insn
                 && distance < LEA_SEARCH_THRESHOLD)
            {
-             if (INSN_P (next))
+             if (NONDEBUG_INSN_P (next))
                {
                  distance++;
 
@@ -17079,20 +17275,22 @@ ix86_split_ashl (rtx *operands, rtx scratch, enum machine_mode mode)
                  : gen_x86_64_shld) (high[0], low[0], operands[2]));
     }
 
-  emit_insn ((mode == DImode ? gen_ashlsi3 : gen_ashldi3) (low[0], low[0], operands[2]));
+  emit_insn ((mode == DImode
+             ? gen_ashlsi3
+             : gen_ashldi3) (low[0], low[0], operands[2]));
 
   if (TARGET_CMOVE && scratch)
     {
       ix86_expand_clear (scratch);
       emit_insn ((mode == DImode
-                 ? gen_x86_shift_adj_1
-                 : gen_x86_64_shift_adj_1) (high[0], low[0], operands[2],
-                                            scratch));
+                 ? gen_x86_shiftsi_adj_1
+                 : gen_x86_shiftdi_adj_1) (high[0], low[0], operands[2],
+                                           scratch));
     }
   else
     emit_insn ((mode == DImode
-               ? gen_x86_shift_adj_2
-               : gen_x86_64_shift_adj_2) (high[0], low[0], operands[2]));
+               ? gen_x86_shiftsi_adj_2
+               : gen_x86_shiftdi_adj_2) (high[0], low[0], operands[2]));
 }
 
 void
@@ -17165,14 +17363,14 @@ ix86_split_ashr (rtx *operands, rtx scratch, enum machine_mode mode)
                      : gen_ashrdi3) (scratch, scratch,
                                      GEN_INT (single_width - 1)));
          emit_insn ((mode == DImode
-                     ? gen_x86_shift_adj_1
-                     : gen_x86_64_shift_adj_1) (low[0], high[0], operands[2],
-                                                scratch));
+                     ? gen_x86_shiftsi_adj_1
+                     : gen_x86_shiftdi_adj_1) (low[0], high[0], operands[2],
+                                               scratch));
        }
       else
        emit_insn ((mode == DImode
-                   ? gen_x86_shift_adj_3
-                   : gen_x86_64_shift_adj_3) (low[0], high[0], operands[2]));
+                   ? gen_x86_shiftsi_adj_3
+                   : gen_x86_shiftdi_adj_3) (low[0], high[0], operands[2]));
     }
 }
 
@@ -17230,14 +17428,14 @@ ix86_split_lshr (rtx *operands, rtx scratch, enum machine_mode mode)
        {
          ix86_expand_clear (scratch);
          emit_insn ((mode == DImode
-                     ? gen_x86_shift_adj_1
-                     : gen_x86_64_shift_adj_1) (low[0], high[0], operands[2],
-                                                scratch));
+                     ? gen_x86_shiftsi_adj_1
+                     : gen_x86_shiftdi_adj_1) (low[0], high[0], operands[2],
+                                               scratch));
        }
       else
        emit_insn ((mode == DImode
-                   ? gen_x86_shift_adj_2
-                   : gen_x86_64_shift_adj_2) (low[0], high[0], operands[2]));
+                   ? gen_x86_shiftsi_adj_2
+                   : gen_x86_shiftdi_adj_2) (low[0], high[0], operands[2]));
     }
 }
 
@@ -19662,6 +19860,7 @@ ix86_issue_rate (void)
     case PROCESSOR_NOCONA:
     case PROCESSOR_GENERIC32:
     case PROCESSOR_GENERIC64:
+    case PROCESSOR_BDVER1:
       return 3;
 
     case PROCESSOR_CORE2:
@@ -19851,6 +20050,7 @@ ix86_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
     case PROCESSOR_ATHLON:
     case PROCESSOR_K8:
     case PROCESSOR_AMDFAM10:
+    case PROCESSOR_BDVER1:
     case PROCESSOR_ATOM:
     case PROCESSOR_GENERIC32:
     case PROCESSOR_GENERIC64:
@@ -20046,10 +20246,26 @@ ix86_local_alignment (tree exp, enum machine_mode mode,
     }
 
   /* x86-64 ABI requires arrays greater than 16 bytes to be aligned
-     to 16byte boundary.  */
-  if (TARGET_64BIT)
+     to 16byte boundary.  Exact wording is:
+
+     An array uses the same alignment as its elements, except that a local or
+     global array variable of length at least 16 bytes or
+     a C99 variable-length array variable always has alignment of at least 16 bytes.
+
+     This was added to allow use of aligned SSE instructions at arrays.  This
+     rule is meant for static storage (where compiler can not do the analysis
+     by itself).  We follow it for automatic variables only when convenient.
+     We fully control everything in the function compiled and functions from
+     other unit can not rely on the alignment.
+
+     Exclude va_list type.  It is the common case of local array where
+     we can not benefit from the alignment.  */
+  if (TARGET_64BIT && optimize_function_for_speed_p (cfun)
+      && TARGET_SSE)
     {
       if (AGGREGATE_TYPE_P (type)
+          && (TYPE_MAIN_VARIANT (type)
+              != TYPE_MAIN_VARIANT (va_list_type_node))
           && TYPE_SIZE (type)
           && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
           && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 16
@@ -20157,6 +20373,12 @@ ix86_static_chain (const_tree fndecl, bool incoming_p)
             us with EAX for the static chain.  */
          regno = AX_REG;
        }
+      else if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (fntype)))
+       {
+         /* Thiscall functions use ecx for arguments, which leaves
+            us with EAX for the static chain.  */
+         regno = AX_REG;
+       }
       else if (ix86_function_regparm (fntype, fndecl) == 3)
        {
          /* For regparm 3, we have no free call-clobbered registers in
@@ -24634,43 +24856,92 @@ ix86_veclibabi_acml (enum built_in_function fn, tree type_out, tree type_in)
 
 
 /* Returns a decl of a function that implements conversion of an integer vector
-   into a floating-point vector, or vice-versa. TYPE is the type of the integer
-   side of the conversion.
+   into a floating-point vector, or vice-versa.  DEST_TYPE and SRC_TYPE
+   are the types involved when converting according to CODE.
    Return NULL_TREE if it is not available.  */
 
 static tree
-ix86_vectorize_builtin_conversion (unsigned int code, tree type)
+ix86_vectorize_builtin_conversion (unsigned int code,
+                                  tree dest_type, tree src_type)
 {
-  if (! (TARGET_SSE2 && TREE_CODE (type) == VECTOR_TYPE))
+  if (! TARGET_SSE2)
     return NULL_TREE;
 
   switch (code)
     {
     case FLOAT_EXPR:
-      switch (TYPE_MODE (type))
+      switch (TYPE_MODE (src_type))
        {
        case V4SImode:
-         return TYPE_UNSIGNED (type)
-           ? ix86_builtins[IX86_BUILTIN_CVTUDQ2PS]
-           : ix86_builtins[IX86_BUILTIN_CVTDQ2PS];
+         switch (TYPE_MODE (dest_type))
+           {
+           case V4SFmode:
+             return (TYPE_UNSIGNED (src_type)
+                     ? ix86_builtins[IX86_BUILTIN_CVTUDQ2PS]
+                     : ix86_builtins[IX86_BUILTIN_CVTDQ2PS]);
+           case V4DFmode:
+             return (TYPE_UNSIGNED (src_type)
+                     ? NULL_TREE
+                     : ix86_builtins[IX86_BUILTIN_CVTDQ2PD256]);
+           default:
+             return NULL_TREE;
+           }
+         break;
+       case V8SImode:
+         switch (TYPE_MODE (dest_type))
+           {
+           case V8SFmode:
+             return (TYPE_UNSIGNED (src_type)
+                     ? NULL_TREE
+                     : ix86_builtins[IX86_BUILTIN_CVTDQ2PS]);
+           default:
+             return NULL_TREE;
+           }
+         break;
        default:
          return NULL_TREE;
        }
 
     case FIX_TRUNC_EXPR:
-      switch (TYPE_MODE (type))
+      switch (TYPE_MODE (dest_type))
        {
        case V4SImode:
-         return TYPE_UNSIGNED (type)
-           ? NULL_TREE
-           : ix86_builtins[IX86_BUILTIN_CVTTPS2DQ];
+         switch (TYPE_MODE (src_type))
+           {
+           case V4SFmode:
+             return (TYPE_UNSIGNED (dest_type)
+                     ? NULL_TREE
+                     : ix86_builtins[IX86_BUILTIN_CVTTPS2DQ]);
+           case V4DFmode:
+             return (TYPE_UNSIGNED (dest_type)
+                     ? NULL_TREE
+                     : ix86_builtins[IX86_BUILTIN_CVTTPD2DQ256]);
+           default:
+             return NULL_TREE;
+           }
+         break;
+
+       case V8SImode:
+         switch (TYPE_MODE (src_type))
+           {
+           case V8SFmode:
+             return (TYPE_UNSIGNED (dest_type)
+                     ? NULL_TREE
+                     : ix86_builtins[IX86_BUILTIN_CVTTPS2DQ256]);
+           default:
+             return NULL_TREE;
+           }
+         break;
+
        default:
          return NULL_TREE;
        }
+
     default:
       return NULL_TREE;
-
     }
+
+  return NULL_TREE;
 }
 
 /* Returns a code for a target-specific builtin that implements
@@ -26124,6 +26395,13 @@ x86_this_parameter (tree function)
 
       if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
        regno = aggr ? DX_REG : CX_REG;
+      else if (lookup_attribute ("thiscall", TYPE_ATTRIBUTES (type)))
+        {
+         regno = CX_REG;
+         if (aggr)
+           return gen_rtx_MEM (SImode,
+                               plus_constant (stack_pointer_rtx, 4));
+       }
       else
         {
          regno = AX_REG;
@@ -26235,7 +26513,9 @@ x86_output_mi_thunk (FILE *file,
        {
          int tmp_regno = CX_REG;
          if (lookup_attribute ("fastcall",
-                               TYPE_ATTRIBUTES (TREE_TYPE (function))))
+                               TYPE_ATTRIBUTES (TREE_TYPE (function)))
+             || lookup_attribute ("thiscall",
+                                  TYPE_ATTRIBUTES (TREE_TYPE (function))))
            tmp_regno = AX_REG;
          tmp = gen_rtx_REG (SImode, tmp_regno);
        }
@@ -26585,7 +26865,7 @@ ix86_pad_returns (void)
            replace = true;
          /* Empty functions get branch mispredict even when the jump destination
             is not visible to us.  */
-         if (!prev && cfun->function_frequency > FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
+         if (!prev && !optimize_function_for_size_p (cfun))
            replace = true;
        }
       if (replace)
@@ -28975,6 +29255,9 @@ static const struct attribute_spec ix86_attribute_table[] =
   /* Fastcall attribute says callee is responsible for popping arguments
      if they are not variable.  */
   { "fastcall",  0, 0, false, true,  true,  ix86_handle_cconv_attribute },
+  /* Thiscall attribute says callee is responsible for popping arguments
+     if they are not variable.  */
+  { "thiscall",  0, 0, false, true,  true,  ix86_handle_cconv_attribute },
   /* Cdecl attribute says the callee is a normal C declaration */
   { "cdecl",     0, 0, false, true,  true,  ix86_handle_cconv_attribute },
   /* Regparm attribute specifies how many integer arguments are to be
@@ -30531,6 +30814,9 @@ ix86_enum_va_list (int idx, const char **pname, tree *ptree)
 #undef TARGET_FUNCTION_VALUE
 #define TARGET_FUNCTION_VALUE ix86_function_value
 
+#undef TARGET_FUNCTION_VALUE_REGNO_P
+#define TARGET_FUNCTION_VALUE_REGNO_P ix86_function_value_regno_p
+
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD ix86_secondary_reload