OSDN Git Service

* config/i386/i386.c (ix86_function_regparm): Ditto. Use REGPARM_MAX
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.md
index 42b3bab..c53ea7f 100644 (file)
 
    ; For SSE4A support
    (UNSPEC_EXTRQI               130)
-   (UNSPEC_EXTRQ                131)   
+   (UNSPEC_EXTRQ                131)
    (UNSPEC_INSERTQI             132)
    (UNSPEC_INSERTQ              133)
 
    (UNSPEC_CRC32               143)
    (UNSPEC_PCMPESTR            144)
    (UNSPEC_PCMPISTR            145)
+
+   ;; For SSE5
+   (UNSPEC_SSE5_INTRINSIC      150)
+   (UNSPEC_SSE5_UNSIGNED_CMP   151)
+   (UNSPEC_SSE5_TRUEFALSE      152)
+   (UNSPEC_SSE5_PERMUTE                153)
+   (UNSPEC_SSE5_ASHIFT         154)
+   (UNSPEC_SSE5_LSHIFT         155)
+   (UNSPEC_FRCZ                        156)
+   (UNSPEC_CVTPH2PS            157)
+   (UNSPEC_CVTPS2PH            158)
   ])
 
 (define_constants
    (UNSPECV_PROLOGUE_USE       14)
   ])
 
+;; Constants to represent pcomtrue/pcomfalse variants
+(define_constants
+  [(PCOM_FALSE                 0)
+   (PCOM_TRUE                  1)
+   (COM_FALSE_S                        2)
+   (COM_FALSE_P                        3)
+   (COM_TRUE_S                 4)
+   (COM_TRUE_P                 5)
+  ])
+
 ;; Registers by name.
 (define_constants
-  [(BP_REG                      6)
+  [(AX_REG                      0)
+   (DX_REG                      1)
+   (CX_REG                      2)
+   (SI_REG                      4)
+   (DI_REG                      5)
+   (BP_REG                      6)
    (SP_REG                      7)
    (FLAGS_REG                  17)
    (FPSR_REG                   18)
    push,pop,call,callv,leave,
    str,bitmanip,
    fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint,
-   sselog,sselog1,sseiadd,sseishft,sseimul,
-   sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv,sseins,
+   sselog,sselog1,sseiadd,sseiadd1,sseishft,sseimul,
+   sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,ssediv,sseins,
+   ssemuladd,sse4arg,
    mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
   (const_string "other"))
 
 (define_attr "unit" "integer,i387,sse,mmx,unknown"
   (cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,fisttp,frndint")
           (const_string "i387")
-        (eq_attr "type" "sselog,sselog1,sseiadd,sseishft,sseimul,
-                         sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv,sseins")
+        (eq_attr "type" "sselog,sselog1,sseiadd,sseiadd1,sseishft,sseimul,
+                         sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,
+                         ssecvt1,sseicvt,ssediv,sseins,ssemuladd,sse4arg")
           (const_string "sse")
         (eq_attr "type" "mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft")
           (const_string "mmx")
                 "!alu1,negnot,ishift1,
                   imov,imovx,icmp,test,bitmanip,
                   fmov,fcmp,fsgn,
-                  sse,ssemov,ssecmp,ssecomi,ssecvt,sseicvt,sselog1,
-                  mmx,mmxmov,mmxcmp,mmxcvt")
+                  sse,ssemov,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,sselog1,
+                  sseiadd1,mmx,mmxmov,mmxcmp,mmxcvt")
              (match_operand 2 "memory_operand" ""))
           (const_string "load")
-        (and (eq_attr "type" "icmov")
+        (and (eq_attr "type" "icmov,ssemuladd,sse4arg")
              (match_operand 3 "memory_operand" ""))
           (const_string "load")
        ]
    (set_attr "mode" "SI")])
 
 ;; Pentium Pro can do steps 1 through 3 in one go.
-;; comi*, ucomi*, fcomi*, ficomi*,fucomi* (i387 instructions set condition codes) 
+;; comi*, ucomi*, fcomi*, ficomi*,fucomi* (i387 instructions set condition codes)
 (define_insn "*cmpfp_i_mixed"
   [(set (reg:CCFP FLAGS_REG)
        (compare:CCFP (match_operand 0 "register_operand" "f,x")
    (set_attr "mode" "SI")
    (set_attr "pent_pair" "np")
    (set_attr "athlon_decode" "vector")
-   (set_attr "amdfam10_decode" "double")])   
+   (set_attr "amdfam10_decode" "double")])
 
 (define_expand "movhi"
   [(set (match_operand:HI 0 "nonimmediate_operand" "")
    (set_attr "mode" "SI")
    (set_attr "pent_pair" "np")
    (set_attr "athlon_decode" "vector")
-   (set_attr "amdfam10_decode" "double")])   
+   (set_attr "amdfam10_decode" "double")])
 
 ;; Not added amdfam10_decode since TARGET_PARTIAL_REG_STALL is disabled for AMDFAM10
 (define_insn "*swaphi_2"
    (set_attr "mode" "SI")
    (set_attr "pent_pair" "np")
    (set_attr "athlon_decode" "vector")
-   (set_attr "amdfam10_decode" "vector")])   
+   (set_attr "amdfam10_decode" "vector")])
 
 ;; Not added amdfam10_decode since TARGET_PARTIAL_REG_STALL is disabled for AMDFAM10
 (define_insn "*swapqi_2"
 
 (define_insn "*movdi_2"
   [(set (match_operand:DI 0 "nonimmediate_operand"
-                       "=r  ,o  ,*y,m*y,*y,*Yt,m  ,*Yt,*Yt,*x,m ,*x,*x")
+                       "=r  ,o  ,*y,m*y,*y,*Y2,m  ,*Y2,*Y2,*x,m ,*x,*x")
        (match_operand:DI 1 "general_operand"
-                       "riFo,riF,C ,*y ,m ,C  ,*Yt,*Yt,m  ,C ,*x,*x,m "))]
+                       "riFo,riF,C ,*y ,m ,C  ,*Y2,*Y2,m  ,C ,*x,*x,m "))]
   "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
   "@
    #
    (set_attr "mode" "DI")
    (set_attr "pent_pair" "np")
    (set_attr "athlon_decode" "vector")
-   (set_attr "amdfam10_decode" "double")])   
+   (set_attr "amdfam10_decode" "double")])
 
 (define_expand "movti"
   [(set (match_operand:TI 0 "nonimmediate_operand" "")
    (set_attr "mode" "SF,SI,SF")])
 
 (define_insn "*pushsf_rex64"
-  [(set (match_operand:SF 0 "push_operand" "=<,<,<")
+  [(set (match_operand:SF 0 "push_operand" "=X,X,X")
        (match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))]
   "TARGET_64BIT"
 {
 
 (define_insn "*pushdf_nointeger"
   [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
-       (match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Yt"))]
+       (match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Y2"))]
   "!TARGET_64BIT && !TARGET_INTEGER_DFMODE_MOVES"
 {
   /* This insn should be already split before reg-stack.  */
 
 (define_insn "*pushdf_integer"
   [(set (match_operand:DF 0 "push_operand" "=<,<,<")
-       (match_operand:DF 1 "general_no_elim_operand" "f,rFo,Yt"))]
+       (match_operand:DF 1 "general_no_elim_operand" "f,rFo,Y2"))]
   "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES"
 {
   /* This insn should be already split before reg-stack.  */
 
 (define_insn "*movdf_nointeger"
   [(set (match_operand:DF 0 "nonimmediate_operand"
-                       "=f,m,f,*r  ,o  ,Yt*x,Yt*x,Yt*x ,m  ")
+                       "=f,m,f,*r  ,o  ,Y2*x,Y2*x,Y2*x ,m  ")
        (match_operand:DF 1 "general_operand"
-                       "fm,f,G,*roF,F*r,C   ,Yt*x,mYt*x,Yt*x"))]
+                       "fm,f,G,*roF,F*r,C   ,Y2*x,mY2*x,Y2*x"))]
   "!(MEM_P (operands[0]) && MEM_P (operands[1]))
    && ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT)
    && (reload_in_progress || reload_completed
 
 (define_insn "*movdf_integer_rex64"
   [(set (match_operand:DF 0 "nonimmediate_operand"
-               "=f,m,f,r  ,m ,Yt*x,Yt*x,Yt*x,m   ,Yi,r ")
+               "=f,m,f,r  ,m ,Y2*x,Y2*x,Y2*x,m   ,Yi,r ")
        (match_operand:DF 1 "general_operand"
-               "fm,f,G,rmF,Fr,C   ,Yt*x,m   ,Yt*x,r ,Yi"))]
+               "fm,f,G,rmF,Fr,C   ,Y2*x,m   ,Y2*x,r ,Yi"))]
   "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))
    && (reload_in_progress || reload_completed
        || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
 
 (define_insn "*movdf_integer"
   [(set (match_operand:DF 0 "nonimmediate_operand"
-               "=f,m,f,r  ,o ,Yt*x,Yt*x,Yt*x,m   ")
+               "=f,m,f,r  ,o ,Y2*x,Y2*x,Y2*x,m   ")
        (match_operand:DF 1 "general_operand"
-               "fm,f,G,roF,Fr,C   ,Yt*x,m   ,Yt*x"))]
+               "fm,f,G,roF,Fr,C   ,Y2*x,m   ,Y2*x"))]
   "!(MEM_P (operands[0]) && MEM_P (operands[1]))
    && !optimize_size && TARGET_INTEGER_DFMODE_MOVES
    && (reload_in_progress || reload_completed
   [(set (match_operand:HI 0 "register_operand" "=r")
      (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
   "(!TARGET_ZERO_EXTEND_WITH_AND || optimize_size) && reload_completed"
-  "movz{bl|x}\t{%1, %k0|%k0, %k1}"
+  "movz{bl|x}\t{%1, %k0|%k0, %1}"
   [(set_attr "type" "imovx")
    (set_attr "mode" "SI")])
 
 })
 
 (define_insn "zero_extendsidi2_32"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?o,?*Ym,?*y,?*Yi,*Yt")
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?o,?*Ym,?*y,?*Yi,*Y2")
        (zero_extend:DI
         (match_operand:SI 1 "nonimmediate_operand" "0,rm,r ,r   ,m  ,r   ,m")))
    (clobber (reg:CC FLAGS_REG))]
    (set_attr "type" "multi,multi,multi,mmxmov,mmxmov,ssemov,ssemov")])
 
 (define_insn "zero_extendsidi2_rex64"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,?*Ym,?*y,?*Yi,*Yt")
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,?*Ym,?*y,?*Yi,*Y2")
      (zero_extend:DI
        (match_operand:SI 1 "nonimmediate_operand"  "rm,0,r   ,m  ,r   ,m")))]
   "TARGET_64BIT"
 
   /* Generate a cltd if possible and doing so it profitable.  */
   if ((optimize_size || TARGET_USE_CLTD)
-      && true_regnum (operands[1]) == 0
-      && true_regnum (operands[2]) == 1)
+      && true_regnum (operands[1]) == AX_REG
+      && true_regnum (operands[2]) == DX_REG)
     {
       emit_insn (gen_ashrsi3_31 (operands[2], operands[1], GEN_INT (31)));
     }
 
   /* Generate a cltd if possible and doing so it profitable.  */
   if ((optimize_size || TARGET_USE_CLTD)
-      && true_regnum (operands[3]) == 0)
+      && true_regnum (operands[3]) == AX_REG)
     {
       emit_insn (gen_ashrsi3_31 (operands[4], operands[3], GEN_INT (31)));
       DONE;
 ;; %%% Kill these when call knows how to work out a DFmode push earlier.
 (define_insn "*dummy_extendsfdf2"
   [(set (match_operand:DF 0 "push_operand" "=<")
-       (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fY")))]
+       (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fY2")))]
   "0"
   "#")
 
     }
 })
 
+/* For converting SF(xmm2) to DF(xmm1), use the following code instead of
+   cvtss2sd:
+      unpcklps xmm2,xmm2   ; packed conversion might crash on signaling NaNs
+      cvtps2pd xmm2,xmm1
+   We do the conversion post reload to avoid producing of 128bit spills
+   that might lead to ICE on 32bit target.  The sequence unlikely combine
+   anyway.  */
+(define_split
+  [(set (match_operand:DF 0 "register_operand" "")
+        (float_extend:DF
+         (match_operand:SF 1 "nonimmediate_operand" "")))]
+  "(TARGET_USE_VECTOR_CONVERTS || TARGET_GENERIC) && !optimize_size
+   && reload_completed && SSE_REG_P (operands[0])"
+   [(set (match_dup 2)
+        (float_extend:V2DF
+          (vec_select:V2SF
+            (match_dup 3)
+            (parallel [(const_int 0) (const_int 1)]))))]
+{
+  operands[2] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0);
+  operands[3] = simplify_gen_subreg (V4SFmode, operands[0], DFmode, 0);
+  /* Use movss for loading from memory, unpcklps reg, reg for registers.
+     Try to avoid move when unpacking can be done in source.  */
+  if (REG_P (operands[1]))
+    {
+      /* If it is unsafe to overwrite upper half of source, we need
+        to move to destination and unpack there.  */
+      if ((ORIGINAL_REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+          || PSEUDO_REGNO_BYTES (ORIGINAL_REGNO (operands[1])) > 4)
+         && true_regnum (operands[0]) != true_regnum (operands[1]))
+       {
+         rtx tmp = gen_rtx_REG (SFmode, true_regnum (operands[0]));
+         emit_move_insn (tmp, operands[1]);
+       }
+      else
+       operands[3] = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
+      emit_insn (gen_sse_unpcklps (operands[3], operands[3], operands[3]));
+    }
+  else
+    emit_insn (gen_vec_setv4sf_0 (operands[3],
+                                 CONST0_RTX (V4SFmode), operands[1]));
+})
+
 (define_insn "*extendsfdf2_mixed"
   [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,x")
         (float_extend:DF
     ;
   else
     {
-      rtx temp = assign_386_stack_local (SFmode, SLOT_VIRTUAL);
+      int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL;
+      rtx temp = assign_386_stack_local (SFmode, slot);
       emit_insn (gen_truncdfsf2_with_temp (operands[0], operands[1], temp));
       DONE;
     }
 })
 
+/* For converting DF(xmm2) to SF(xmm1), use the following code instead of
+   cvtsd2ss:
+      unpcklpd xmm2,xmm2   ; packed conversion might crash on signaling NaNs
+      cvtpd2ps xmm2,xmm1
+   We do the conversion post reload to avoid producing of 128bit spills
+   that might lead to ICE on 32bit target.  The sequence unlikely combine
+   anyway.  */
+(define_split
+  [(set (match_operand:SF 0 "register_operand" "")
+        (float_truncate:SF
+         (match_operand:DF 1 "nonimmediate_operand" "")))]
+  "(TARGET_USE_VECTOR_CONVERTS || TARGET_GENERIC) && !optimize_size
+   && reload_completed && SSE_REG_P (operands[0])"
+   [(set (match_dup 2)
+        (vec_concat:V4SF
+          (float_truncate:V2SF
+            (match_dup 4))
+          (match_dup 3)))]
+{
+  operands[2] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0);
+  operands[3] = CONST0_RTX (V2SFmode);
+  operands[4] = simplify_gen_subreg (V2DFmode, operands[0], SFmode, 0);
+  /* Use movsd for loading from memory, unpcklpd for registers.
+     Try to avoid move when unpacking can be done in source, or SSE3
+     movddup is available.  */
+  if (REG_P (operands[1]))
+    {
+      if (!TARGET_SSE3
+         && true_regnum (operands[0]) != true_regnum (operands[1])
+         && (ORIGINAL_REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+             || PSEUDO_REGNO_BYTES (ORIGINAL_REGNO (operands[1])) > 8))
+       {
+         rtx tmp = simplify_gen_subreg (DFmode, operands[0], SFmode, 0);
+         emit_move_insn (tmp, operands[1]);
+         operands[1] = tmp;
+       }
+      else if (!TARGET_SSE3)
+       operands[4] = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0);
+      emit_insn (gen_vec_dupv2df (operands[4], operands[1]));
+    }
+  else
+    emit_insn (gen_sse2_loadlpd (operands[4],
+                                CONST0_RTX (V2DFmode), operands[1]));
+})
+
 (define_expand "truncdfsf2_with_temp"
   [(parallel [(set (match_operand:SF 0 "" "")
                   (float_truncate:SF (match_operand:DF 1 "" "")))
    (set_attr "mode" "SF")])
 
 (define_insn "*truncdfsf_mixed"
-  [(set (match_operand:SF 0 "nonimmediate_operand"   "=m,?fx*r,Yt")
+  [(set (match_operand:SF 0 "nonimmediate_operand"   "=m,?fx*r,Y2")
        (float_truncate:SF
-         (match_operand:DF 1 "nonimmediate_operand" "f ,f    ,Ytm")))
+         (match_operand:DF 1 "nonimmediate_operand" "f ,f    ,Y2m")))
    (clobber (match_operand:SF 2 "memory_operand"     "=X,m    ,X"))]
   "TARGET_MIX_SSE_I387"
 {
       DONE;
     }
   else
-    operands[2] = assign_386_stack_local (<MODE>mode, SLOT_VIRTUAL);
+    {
+      int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL;
+      operands[2] = assign_386_stack_local (<MODE>mode, slot);
+    }
 })
 
 (define_insn "*truncxfsf2_mixed"
    (set_attr "mode" "SF")])
 
 (define_insn "*truncxfdf2_mixed"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?fYt*r")
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?fY2*r")
        (float_truncate:DF
          (match_operand:XF 1 "register_operand" "f,f")))
    (clobber (match_operand:DF 2 "memory_operand" "=X,m"))]
 
 ;; Avoid vector decoded forms of the instruction.
 (define_peephole2
-  [(match_scratch:DF 2 "Yt")
+  [(match_scratch:DF 2 "Y2")
    (set (match_operand:SSEMODEI24 0 "register_operand" "")
        (fix:SSEMODEI24 (match_operand:DF 1 "memory_operand" "")))]
   "TARGET_AVOID_VECTOR_DECODE && !optimize_size"
    (set_attr "mode" "HI")
    (set_attr "unit" "i387")
    (set_attr "athlon_decode" "vector")
-   (set_attr "amdfam10_decode" "vector")])   
+   (set_attr "amdfam10_decode" "vector")])
 \f
 ;; Conversion between fixed point and floating point.
 
   [(set (match_operand:MODEF 0 "register_operand" "")
        (float:MODEF (match_operand:SI 1 "nonimmediate_operand" "")))]
   "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
-  "")
+  "
+   /* When we use vector converts, we can't have input in memory.  */
+   if (GET_MODE (operands[0]) == DFmode
+       && TARGET_USE_VECTOR_CONVERTS && !optimize_size && TARGET_SSE_MATH
+       && SSE_FLOAT_MODE_P (DFmode))
+     operands[1] = force_reg (SImode, operands[1]);
+   else if (GET_MODE (operands[0]) == SFmode
+            && !optimize_size && TARGET_USE_VECTOR_CONVERTS && TARGET_SSE_MATH
+            && SSE_FLOAT_MODE_P (SFmode))
+     {
+       /* When !flag_trapping_math, we handle SImode->SFmode vector
+         conversions same way as SImode->DFmode.
+
+         For flat_trapping_math we can't safely use vector conversion without
+         clearing upper half, otherwise precision exception might occur.
+         However we can still generate the common sequence converting value
+         from general register to XMM register as:
+
+           mov         reg32, mem32
+           movd        mem32, xmm
+           cvtdq2pd xmm,xmm
+
+         because we know that movd clears the upper half.
+
+         Sadly in this case we can't rely on reload moving the value to XMM
+         register, since we need to know if upper half is OK, so we need
+         to do reloading by hand.  We force operand to memory unless target
+         supports inter unit moves.  */
+       if (!flag_trapping_math)
+         operands[1] = force_reg (SImode, operands[1]);
+       else if (!MEM_P (operands[1]))
+        {
+          int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL;
+          rtx tmp = assign_386_stack_local (SImode, slot);
+          emit_move_insn (tmp, operands[1]);
+          operands[1] = tmp;
+        }
+     }
+   /* Offload operand of cvtsi2ss and cvtsi2sd into memory for
+      !TARGET_INTER_UNIT_CONVERSIONS
+      It is necessary for the patterns to not accept nonmemory operands
+      as we would optimize out later.  */
+   else if (!TARGET_INTER_UNIT_CONVERSIONS
+           && TARGET_SSE_MATH && SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
+           && !optimize_size
+           && !MEM_P (operands[1]))
+     {
+       int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL;
+       rtx tmp = assign_386_stack_local (GET_MODE (operands[1]), slot);
+       emit_move_insn (tmp, operands[1]);
+       operands[1] = tmp;
+     }
+  ")
+
+(define_insn "*floatsisf2_mixed_vector"
+  [(set (match_operand:SF 0 "register_operand" "=x,f,?f")
+       (float:SF (match_operand:SI 1 "nonimmediate_operand" "x,m,r")))]
+  "TARGET_MIX_SSE_I387 && !flag_trapping_math
+   && TARGET_USE_VECTOR_CONVERTS && !optimize_size"
+  "@
+   cvtdq2ps\t{%1, %0|%0, %1}
+   fild%z1\t%1
+   #"
+  [(set_attr "type" "sseicvt,fmov,multi")
+   (set_attr "mode" "SF")
+   (set_attr "unit" "*,i387,*")
+   (set_attr "athlon_decode" "double,*,*")
+   (set_attr "amdfam10_decode" "double,*,*")
+   (set_attr "fp_int_src" "false,true,true")])
 
 (define_insn "*floatsisf2_mixed"
   [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
        (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,m")))]
-  "TARGET_MIX_SSE_I387"
+  "TARGET_MIX_SSE_I387
+   && ((!TARGET_USE_VECTOR_CONVERTS && TARGET_INTER_UNIT_CONVERSIONS)
+       || optimize_size)"
   "@
    fild%z1\t%1
    #
    (set_attr "amdfam10_decode" "*,*,vector,double")
    (set_attr "fp_int_src" "true")])
 
+(define_insn "*floatsisf2_mixed_memory"
+  [(set (match_operand:SF 0 "register_operand" "=f,x")
+       (float:SF (match_operand:SI 1 "memory_operand" "m,m")))]
+  "TARGET_MIX_SSE_I387
+   && !TARGET_INTER_UNIT_CONVERSIONS && !optimize_size"
+  "@
+   fild%z1\t%1
+   cvtsi2ss\t{%1, %0|%0, %1}"
+  [(set_attr "type" "fmov,sseicvt")
+   (set_attr "mode" "SF")
+   (set_attr "athlon_decode" "*,double")
+   (set_attr "amdfam10_decode" "*,double")
+   (set_attr "fp_int_src" "true")])
+
+(define_insn "*floatsisf2_sse_vector_nointernunit"
+  [(set (match_operand:SF 0 "register_operand" "=x")
+       (float:SF (match_operand:SI 1 "memory_operand" "m")))]
+  "TARGET_SSE_MATH && flag_trapping_math
+   && TARGET_USE_VECTOR_CONVERTS && !optimize_size
+   && !TARGET_INTER_UNIT_MOVES"
+  "#"
+  [(set_attr "type" "multi")])
+
+(define_insn "*floatsisf2_sse_vector_internunit"
+  [(set (match_operand:SF 0 "register_operand" "=x,x")
+       (float:SF (match_operand:SI 1 "nonimmediate_operand" "rm,x")))]
+  "TARGET_SSE_MATH && flag_trapping_math
+   && TARGET_USE_VECTOR_CONVERTS && !optimize_size
+   && TARGET_INTER_UNIT_MOVES"
+  "#"
+  [(set_attr "type" "multi")])
+
+(define_split
+  [(set (match_operand:SF 0 "register_operand" "")
+       (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
+  "flag_trapping_math
+   && TARGET_USE_VECTOR_CONVERTS && reload_completed
+   && (TARGET_INTER_UNIT_MOVES || MEM_P (operands[1]))
+   && !SSE_REG_P (operands[1]) && SSE_REG_P (operands[0])"
+  [(set (match_dup 0)
+       (float:V4SF (match_dup 2)))]
+{
+  operands[2] = simplify_gen_subreg (V4SImode, operands[0], SFmode, 0);
+  operands[0] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0);
+  emit_insn (gen_sse2_loadld (operands[2], CONST0_RTX (V4SImode), operands[1]));
+})
+
+(define_split
+  [(set (match_operand:SF 0 "register_operand" "")
+       (float:SF (match_operand:SI 1 "register_operand" "")))]
+  "flag_trapping_math
+   && TARGET_USE_VECTOR_CONVERTS && reload_completed
+   && SSE_REG_P (operands[1]) && SSE_REG_P (operands[0])"
+  [(set (match_dup 2) (vec_duplicate:V4SI (match_dup 1)))
+   (set (match_dup 0)
+       (float:V4SF (match_dup 2)))]
+{
+  operands[2] = simplify_gen_subreg (V4SImode, operands[0], SFmode, 0);
+  operands[0] = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0);
+})
+
+(define_insn "*floatsisf2_sse_vector"
+  [(set (match_operand:SF 0 "register_operand" "=x")
+       (float:SF (match_operand:SI 1 "register_operand" "x")))]
+  "TARGET_SSE_MATH && !flag_trapping_math
+   && TARGET_USE_VECTOR_CONVERTS && !optimize_size
+   && !TARGET_INTER_UNIT_MOVES"
+  "cvtdq2ps\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseicvt")
+   (set_attr "mode" "SF")
+   (set_attr "athlon_decode" "double")
+   (set_attr "amdfam10_decode" "double")
+   (set_attr "fp_int_src" "true")])
+
 (define_insn "*floatsisf2_sse"
   [(set (match_operand:SF 0 "register_operand" "=x,x")
        (float:SF (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
-  "TARGET_SSE_MATH"
+  "TARGET_SSE_MATH
+   && ((!TARGET_USE_VECTOR_CONVERTS && TARGET_INTER_UNIT_CONVERSIONS)
+       || optimize_size)"
   "cvtsi2ss\t{%1, %0|%0, %1}"
   [(set_attr "type" "sseicvt")
    (set_attr "mode" "SF")
    (set_attr "amdfam10_decode" "vector,double")
    (set_attr "fp_int_src" "true")])
 
+(define_insn "*floatsisf2_sse_memory"
+  [(set (match_operand:SF 0 "register_operand" "=x")
+       (float:SF (match_operand:SI 1 "memory_operand" "m")))]
+  "TARGET_SSE_MATH
+   && !TARGET_INTER_UNIT_CONVERSIONS && !optimize_size"
+  "cvtsi2ss\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseicvt")
+   (set_attr "mode" "SF")
+   (set_attr "athlon_decode" "double")
+   (set_attr "amdfam10_decode" "double")
+   (set_attr "fp_int_src" "true")])
+
+(define_insn "*floatsidf2_mixed_vector"
+  [(set (match_operand:DF 0 "register_operand" "=x,f,f")
+       (float:DF (match_operand:SI 1 "nonimmediate_operand" "x,m,r")))]
+  "TARGET_SSE2 && TARGET_MIX_SSE_I387
+   && TARGET_USE_VECTOR_CONVERTS && !optimize_size"
+  "@
+   cvtdq2pd\t{%1, %0|%0, %1}
+   fild%z1\t%1
+   #"
+  [(set_attr "type" "sseicvt,fmov,multi")
+   (set_attr "mode" "V2DF,DF,DF")
+   (set_attr "unit" "*,*,i387")
+   (set_attr "athlon_decode" "double,*,*")
+   (set_attr "amdfam10_decode" "double,*,*")
+   (set_attr "fp_int_src" "false,true,true")])
+
 (define_insn "*floatsidf2_mixed"
-  [(set (match_operand:DF 0 "register_operand" "=f,?f,x,x")
-       (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,m")))]
-  "TARGET_SSE2 && TARGET_MIX_SSE_I387"
+  [(set (match_operand:DF 0 "register_operand" "=f,?f,x,x,!x")
+       (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,m,x")))]
+  "TARGET_SSE2 && TARGET_MIX_SSE_I387
+   && ((!TARGET_USE_VECTOR_CONVERTS && TARGET_INTER_UNIT_CONVERSIONS)
+       || optimize_size)"
   "@
    fild%z1\t%1
    #
    cvtsi2sd\t{%1, %0|%0, %1}
+   cvtsi2sd\t{%1, %0|%0, %1}
+   cvtdq2pd\t{%1, %0|%0, %1}"
+  [(set_attr "type" "fmov,multi,sseicvt,sseicvt,sseicvt")
+   (set_attr "mode" "DF,DF,DF,DF,V2DF")
+   (set_attr "unit" "*,i387,*,*,*")
+   (set_attr "athlon_decode" "*,*,double,direct,double")
+   (set_attr "amdfam10_decode" "*,*,vector,double,double")
+   (set_attr "fp_int_src" "true,true,true,true,false")])
+
+(define_insn "*floatsidf2_mixed_memory"
+  [(set (match_operand:DF 0 "register_operand" "=f,x")
+       (float:DF (match_operand:SI 1 "memory_operand" "m,m")))]
+  "TARGET_SSE2 && TARGET_MIX_SSE_I387
+   && !TARGET_INTER_UNIT_CONVERSIONS && !optimize_size"
+  "@
+   fild%z1\t%1
    cvtsi2sd\t{%1, %0|%0, %1}"
-  [(set_attr "type" "fmov,multi,sseicvt,sseicvt")
+  [(set_attr "type" "fmov,sseicvt")
    (set_attr "mode" "DF")
-   (set_attr "unit" "*,i387,*,*")
-   (set_attr "athlon_decode" "*,*,double,direct")
-   (set_attr "amdfam10_decode" "*,*,vector,double")
+   (set_attr "athlon_decode" "*,direct")
+   (set_attr "amdfam10_decode" "*,double")
+   (set_attr "fp_int_src" "true")])
+
+(define_insn "*floatsidf2_sse_vector"
+  [(set (match_operand:DF 0 "register_operand" "=x")
+       (float:DF (match_operand:SI 1 "register_operand" "x")))]
+  "TARGET_SSE2 && TARGET_SSE_MATH
+   && TARGET_USE_VECTOR_CONVERTS && !optimize_size"
+  "cvtdq2pd\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseicvt")
+   (set_attr "mode" "V2DF")
+   (set_attr "athlon_decode" "double")
+   (set_attr "amdfam10_decode" "double")
    (set_attr "fp_int_src" "true")])
 
+(define_split
+  [(set (match_operand:DF 0 "register_operand" "")
+       (float:DF (match_operand:SI 1 "memory_operand" "")))]
+  "TARGET_USE_VECTOR_CONVERTS && reload_completed
+   && SSE_REG_P (operands[0])"
+  [(set (match_dup 0)
+       (float:V2DF
+         (vec_select:V2SI
+           (match_dup 2)
+           (parallel [(const_int 0) (const_int 1)]))))]
+{
+  operands[2] = simplify_gen_subreg (V4SImode, operands[0], DFmode, 0);
+  operands[0] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0);
+  emit_insn (gen_sse2_loadld (operands[2], CONST0_RTX (V4SImode), operands[1]));
+})
+
 (define_insn "*floatsidf2_sse"
-  [(set (match_operand:DF 0 "register_operand" "=x,x")
-       (float:DF (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
-  "TARGET_SSE2 && TARGET_SSE_MATH"
+  [(set (match_operand:DF 0 "register_operand" "=x,x,!x")
+       (float:DF (match_operand:SI 1 "nonimmediate_operand" "r,m,x")))]
+  "TARGET_SSE2 && TARGET_SSE_MATH
+   && ((!TARGET_USE_VECTOR_CONVERTS && TARGET_INTER_UNIT_CONVERSIONS)
+       || optimize_size)"
+  "@
+   cvtsi2sd\t{%1, %0|%0, %1}
+   cvtsi2sd\t{%1, %0|%0, %1}
+   cvtdq2pd\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseicvt")
+   (set_attr "mode" "DF,DF,V2DF")
+   (set_attr "athlon_decode" "double,direct,double")
+   (set_attr "amdfam10_decode" "vector,double,double")
+   (set_attr "fp_int_src" "true")])
+
+(define_insn "*floatsidf2_memory"
+  [(set (match_operand:DF 0 "register_operand" "=x")
+       (float:DF (match_operand:SI 1 "memory_operand" "x")))]
+  "TARGET_SSE2 && TARGET_SSE_MATH
+   && ((!TARGET_USE_VECTOR_CONVERTS && TARGET_INTER_UNIT_CONVERSIONS)
+       || optimize_size)"
   "cvtsi2sd\t{%1, %0|%0, %1}"
   [(set_attr "type" "sseicvt")
    (set_attr "mode" "DF")
-   (set_attr "athlon_decode" "double,direct")
-   (set_attr "amdfam10_decode" "vector,double")
+   (set_attr "athlon_decode" "direct")
+   (set_attr "amdfam10_decode" "double")
    (set_attr "fp_int_src" "true")])
 
 (define_insn "*floatsi<mode>2_i387"
   [(set (match_operand:MODEF 0 "register_operand" "=f,f")
        (float:MODEF
          (match_operand:SI 1 "nonimmediate_operand" "m,?r")))]
-  "TARGET_80387"
+  "TARGET_80387
+   && (!TARGET_SSE_MATH || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))"
   "@
    fild%z1\t%1
    #"
   [(set (match_operand:SF 0 "register_operand" "")
        (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))]
   "TARGET_80387 || (TARGET_64BIT && TARGET_SSE_MATH)"
-  "")
+{
+  if (!TARGET_INTER_UNIT_CONVERSIONS && TARGET_64BIT
+      && TARGET_SSE_MATH && SSE_FLOAT_MODE_P (SFmode)
+      && !optimize_size
+      && !MEM_P (operands[1]))
+    {
+      int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL;
+      rtx tmp = assign_386_stack_local (GET_MODE (operands[1]), slot);
+      emit_move_insn (tmp, operands[1]);
+      operands[1] = tmp;
+    }
+})
 
 (define_insn "*floatdisf2_mixed"
   [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x")
        (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,m")))]
-  "TARGET_64BIT && TARGET_MIX_SSE_I387"
+  "TARGET_64BIT && TARGET_MIX_SSE_I387
+   && (TARGET_INTER_UNIT_CONVERSIONS || optimize_size)"
   "@
    fild%z1\t%1
    #
    (set_attr "amdfam10_decode" "*,*,vector,double")
    (set_attr "fp_int_src" "true")])
 
+(define_insn "*floatdisf2_mixed"
+  [(set (match_operand:SF 0 "register_operand" "=f,x")
+       (float:SF (match_operand:DI 1 "memory_operand" "m,m")))]
+  "TARGET_64BIT && TARGET_MIX_SSE_I387
+   && !TARGET_INTER_UNIT_CONVERSIONS && !optimize_size"
+  "@
+   fild%z1\t%1
+   cvtsi2ss{q}\t{%1, %0|%0, %1}"
+  [(set_attr "type" "fmov,sseicvt")
+   (set_attr "mode" "SF")
+   (set_attr "athlon_decode" "*,double")
+   (set_attr "amdfam10_decode" "*,double")
+   (set_attr "fp_int_src" "true")])
+
 (define_insn "*floatdisf2_sse"
   [(set (match_operand:SF 0 "register_operand" "=x,x")
        (float:SF (match_operand:DI 1 "nonimmediate_operand" "r,m")))]
-  "TARGET_64BIT && TARGET_SSE_MATH"
+  "TARGET_64BIT && TARGET_SSE_MATH
+   && (TARGET_INTER_UNIT_CONVERSIONS || optimize_size)"
   "cvtsi2ss{q}\t{%1, %0|%0, %1}"
   [(set_attr "type" "sseicvt")
    (set_attr "mode" "SF")
    (set_attr "amdfam10_decode" "vector,double")
    (set_attr "fp_int_src" "true")])
 
+(define_insn "*floatdisf2_memory"
+  [(set (match_operand:SF 0 "register_operand" "=x")
+       (float:SF (match_operand:DI 1 "memory_operand" "m")))]
+  "TARGET_64BIT && TARGET_SSE_MATH
+   && !TARGET_INTER_UNIT_CONVERSIONS && !optimize_size"
+  "cvtsi2ss{q}\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseicvt")
+   (set_attr "mode" "SF")
+   (set_attr "athlon_decode" "double")
+   (set_attr "amdfam10_decode" "double")
+   (set_attr "fp_int_src" "true")])
+
 (define_expand "floatdidf2"
   [(set (match_operand:DF 0 "register_operand" "")
        (float:DF (match_operand:DI 1 "nonimmediate_operand" "")))]
       ix86_expand_convert_sign_didf_sse (operands[0], operands[1]);
       DONE;
     }
+  if (!TARGET_INTER_UNIT_CONVERSIONS && TARGET_64BIT
+      && TARGET_SSE_MATH && SSE_FLOAT_MODE_P (DFmode)
+      && !optimize_size
+      && !MEM_P (operands[1]))
+    {
+      int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL;
+      rtx tmp = assign_386_stack_local (GET_MODE (operands[1]), slot);
+      emit_move_insn (tmp, operands[1]);
+      operands[1] = tmp;
+    }
 })
 
 (define_insn "*floatdidf2_mixed"
   [(set (match_operand:DF 0 "register_operand" "=f,?f,x,x")
        (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,m")))]
-  "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387"
+  "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387
+   && (TARGET_INTER_UNIT_CONVERSIONS || optimize_size)"
   "@
    fild%z1\t%1
    #
    (set_attr "amdfam10_decode" "*,*,vector,double")
    (set_attr "fp_int_src" "true")])
 
+(define_insn "*floatdidf2_mixed_memory"
+  [(set (match_operand:DF 0 "register_operand" "=f,x")
+       (float:DF (match_operand:DI 1 "memory_operand" "m,m")))]
+  "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387
+   && !TARGET_INTER_UNIT_CONVERSIONS && !optimize_size"
+  "@
+   fild%z1\t%1
+   cvtsi2sd{q}\t{%1, %0|%0, %1}"
+  [(set_attr "type" "fmov,sseicvt")
+   (set_attr "mode" "DF")
+   (set_attr "athlon_decode" "*,direct")
+   (set_attr "amdfam10_decode" "*,double")
+   (set_attr "fp_int_src" "true")])
+
 (define_insn "*floatdidf2_sse"
   [(set (match_operand:DF 0 "register_operand" "=x,x")
        (float:DF (match_operand:DI 1 "nonimmediate_operand" "r,m")))]
-  "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH"
+  "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH
+   && (TARGET_INTER_UNIT_CONVERSIONS || optimize_size)"
   "cvtsi2sd{q}\t{%1, %0|%0, %1}"
   [(set_attr "type" "sseicvt")
    (set_attr "mode" "DF")
    (set_attr "amdfam10_decode" "vector,double")
    (set_attr "fp_int_src" "true")])
 
+(define_insn "*floatdidf2_sse_memory"
+  [(set (match_operand:DF 0 "register_operand" "=x")
+       (float:DF (match_operand:DI 1 "memory_operand" "m")))]
+  "TARGET_64BIT && TARGET_SSE2 && TARGET_SSE_MATH
+   && !TARGET_INTER_UNIT_CONVERSIONS && !optimize_size"
+  "cvtsi2sd{q}\t{%1, %0|%0, %1}"
+  [(set_attr "type" "sseicvt")
+   (set_attr "mode" "DF")
+   (set_attr "athlon_decode" "direct")
+   (set_attr "amdfam10_decode" "double")
+   (set_attr "fp_int_src" "true")])
+
 (define_insn "*floatdi<mode>2_i387"
   [(set (match_operand:MODEF 0 "register_operand" "=f,f")
        (float:MODEF
          (match_operand:DI 1 "nonimmediate_operand" "m,?r")))]
-  "TARGET_80387"
+  "TARGET_80387
+   && (!TARGET_SSE_MATH || !TARGET_64BIT
+       || !SSE_FLOAT_MODE_P (GET_MODE (operands[0])))"
   "@
    fild%z1\t%1
    #"
   "TARGET_64BIT"
   "")
 
-;; On AMDFAM10 
+;; On AMDFAM10
 ;; IMUL reg64, reg64, imm8     Direct
 ;; IMUL reg64, mem64, imm8     VectorPath
 ;; IMUL reg64, reg64, imm32    Direct
-;; IMUL reg64, mem64, imm32    VectorPath 
+;; IMUL reg64, mem64, imm32    VectorPath
 ;; IMUL reg64, reg64           Direct
 ;; IMUL reg64, mem64           Direct
 
        (cond [(and (eq_attr "alternative" "0,1")
                    (match_operand 1 "memory_operand" ""))
                  (const_string "vector")]
-             (const_string "direct")))       
+             (const_string "direct")))
    (set_attr "mode" "DI")])
 
 (define_expand "mulsi3"
   ""
   "")
 
-;; On AMDFAM10 
+;; On AMDFAM10
 ;; IMUL reg32, reg32, imm8     Direct
 ;; IMUL reg32, mem32, imm8     VectorPath
 ;; IMUL reg32, reg32, imm32    Direct
        (cond [(and (eq_attr "alternative" "0,1")
                    (match_operand 1 "memory_operand" ""))
                  (const_string "vector")]
-             (const_string "direct")))       
+             (const_string "direct")))
    (set_attr "mode" "SI")])
 
 (define_insn "*mulsi3_1_zext"
        (cond [(and (eq_attr "alternative" "0,1")
                    (match_operand 1 "memory_operand" ""))
                  (const_string "vector")]
-             (const_string "direct")))       
+             (const_string "direct")))
    (set_attr "mode" "SI")])
 
 (define_expand "mulhi3"
      (if_then_else (eq_attr "cpu" "athlon")
         (const_string "vector")
         (const_string "direct")))
-   (set_attr "amdfam10_decode" "direct")        
+   (set_attr "amdfam10_decode" "direct")
    (set_attr "mode" "QI")])
 
 (define_expand "umulqihi3"
      (if_then_else (eq_attr "cpu" "athlon")
         (const_string "vector")
         (const_string "direct")))
-   (set_attr "amdfam10_decode" "direct")        
+   (set_attr "amdfam10_decode" "direct")
    (set_attr "mode" "QI")])
 
 (define_expand "mulqihi3"
      (if_then_else (eq_attr "cpu" "athlon")
         (const_string "vector")
         (const_string "direct")))
-   (set_attr "amdfam10_decode" "direct")        
+   (set_attr "amdfam10_decode" "direct")
    (set_attr "mode" "QI")])
 
 (define_expand "umulditi3"
      (if_then_else (eq_attr "cpu" "athlon")
         (const_string "vector")
         (const_string "double")))
-   (set_attr "amdfam10_decode" "double")        
+   (set_attr "amdfam10_decode" "double")
    (set_attr "mode" "DI")])
 
 ;; We can't use this pattern in 64bit mode, since it results in two separate 32bit registers
      (if_then_else (eq_attr "cpu" "athlon")
         (const_string "vector")
         (const_string "double")))
-   (set_attr "amdfam10_decode" "double")        
+   (set_attr "amdfam10_decode" "double")
    (set_attr "mode" "SI")])
 
 (define_expand "mulditi3"
      (if_then_else (eq_attr "cpu" "athlon")
         (const_string "vector")
         (const_string "double")))
-   (set_attr "amdfam10_decode" "double")        
+   (set_attr "amdfam10_decode" "double")
    (set_attr "mode" "SI")])
 
 (define_expand "umuldi3_highpart"
      (if_then_else (eq_attr "cpu" "athlon")
         (const_string "vector")
         (const_string "double")))
-   (set_attr "amdfam10_decode" "double")        
+   (set_attr "amdfam10_decode" "double")
    (set_attr "mode" "DI")])
 
 (define_expand "umulsi3_highpart"
                    (match_operand:MODEF 2 "nonimmediate_operand" "")))]
   "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
   "")
+
+;; SSE5 scalar multiply/add instructions are defined in sse.md.
+
 \f
 ;; Divide instructions
 
    (set_attr "prefix_0f" "1")
    (set_attr "mode" "DI")
    (set_attr "athlon_decode" "vector")
-   (set_attr "amdfam10_decode" "vector")])   
+   (set_attr "amdfam10_decode" "vector")])
 
 (define_expand "x86_64_shift_adj"
   [(set (reg:CCZ FLAGS_REG)
    (set_attr "mode" "SI")
    (set_attr "pent_pair" "np")
    (set_attr "athlon_decode" "vector")
-   (set_attr "amdfam10_decode" "vector")])   
+   (set_attr "amdfam10_decode" "vector")])
 
 (define_expand "x86_shift_adj_1"
   [(set (reg:CCZ FLAGS_REG)
    (set_attr "prefix_0f" "1")
    (set_attr "mode" "DI")
    (set_attr "athlon_decode" "vector")
-   (set_attr "amdfam10_decode" "vector")])   
+   (set_attr "amdfam10_decode" "vector")])
 
 (define_expand "ashrdi3"
   [(set (match_operand:DI 0 "shiftdi_operand" "")
        (match_operator:SF 1 "sse_comparison_operator"
          [(match_operand:SF 2 "register_operand" "0")
           (match_operand:SF 3 "nonimmediate_operand" "xm")]))]
-  "TARGET_SSE"
+  "TARGET_SSE && !TARGET_SSE5"
   "cmp%D1ss\t{%3, %0|%0, %3}"
   [(set_attr "type" "ssecmp")
    (set_attr "mode" "SF")])
        (match_operator:DF 1 "sse_comparison_operator"
          [(match_operand:DF 2 "register_operand" "0")
           (match_operand:DF 3 "nonimmediate_operand" "xm")]))]
-  "TARGET_SSE2"
+  "TARGET_SSE2 && !TARGET_SSE5"
   "cmp%D1sd\t{%3, %0|%0, %3}"
   [(set_attr "type" "ssecmp")
    (set_attr "mode" "DF")])
+
+(define_insn "*sse5_setcc<mode>"
+  [(set (match_operand:MODEF 0 "register_operand" "=x")
+       (match_operator:MODEF 1 "sse5_comparison_float_operator"
+         [(match_operand:MODEF 2 "register_operand" "x")
+          (match_operand:MODEF 3 "nonimmediate_operand" "xm")]))]
+  "TARGET_SSE5"
+  "com%Y1s<ssemodefsuffix>\t{%3, %2, %0|%0, %2, %3}"
+  [(set_attr "type" "sse4arg")
+   (set_attr "mode" "<MODE>")])
+
 \f
 ;; Basic conditional jump instructions.
 ;; We ignore the overflow flag for signed branch instructions.
   [(call (mem:QI (reg:DI R11_REG))
         (match_operand 0 "" ""))]
   "SIBLING_CALL_P (insn) && TARGET_64BIT"
-  "jmp\t*%%r11"
+  "jmp\t{*%%}r11"
   [(set_attr "type" "call")])
 
 
   [(return)
    (unspec [(const_int 0)] UNSPEC_REP)]
   "reload_completed"
-  "rep{\;| }ret"
+  "rep\;ret"
   [(set_attr "length" "1")
    (set_attr "length_immediate" "0")
    (set_attr "prefix_rep" "1")
   [(set (match_operand:DI 0 "register_operand" "=r")
        (unspec:DI [(const_int 0)] UNSPEC_SET_GOT))]
   "TARGET_64BIT"
-  "lea{q}\t_GLOBAL_OFFSET_TABLE_(%%rip), %0"
+  "lea{q}\t{_GLOBAL_OFFSET_TABLE_(%%rip), %0|%0, _GLOBAL_OFFSET_TABLE_[rip]}"
   [(set_attr "type" "lea")
    (set_attr "length" "6")])
 
   [(set (match_operand:DI 0 "register_operand" "=r")
        (unspec:DI [(match_operand:DI 1 "" "")] UNSPEC_SET_RIP))]
   "TARGET_64BIT"
-  "lea{q}\t%l1(%%rip), %0"
+  "lea{q}\t{%l1(%%rip), %0|%0, %l1[rip]}"
   [(set_attr "type" "lea")
    (set_attr "length" "6")])
 
   [(set (match_operand:DI 0 "register_operand" "=r")
        (unspec:DI [(match_operand:DI 1 "" "")] UNSPEC_SET_GOT_OFFSET))]
   "TARGET_64BIT"
-  "movabs{q}\t$_GLOBAL_OFFSET_TABLE_-%l1, %0"
+  "movabs{q}\t{$_GLOBAL_OFFSET_TABLE_-%l1, %0|%0, OFFSET FLAT:_GLOBAL_OFFSET_TABLE_-%l1}"
   [(set_attr "type" "imov")
    (set_attr "length" "11")])
 
    (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
              UNSPEC_TLS_GD)]
   "TARGET_64BIT"
-  ".byte\t0x66\;lea{q}\t{%a1@TLSGD(%%rip), %%rdi|%%rdi, %a1@TLSGD[%%rip]}\;.word\t0x6666\;rex64\;call\t%P2"
+  ".byte\t0x66\;lea{q}\t{%a1@TLSGD(%%rip), %%rdi|rdi, %a1@TLSGD[rip]}\;.word\t0x6666\;rex64\;call\t%P2"
   [(set_attr "type" "multi")
    (set_attr "length" "16")])
 
                 (match_operand:DI 2 "" "")))
    (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)]
   "TARGET_64BIT"
-  "lea{q}\t{%&@TLSLD(%%rip), %%rdi|%%rdi, %&@TLSLD[%%rip]}\;call\t%P1"
+  "lea{q}\t{%&@TLSLD(%%rip), %%rdi|rdi, %&@TLSLD[rip]}\;call\t%P1"
   [(set_attr "type" "multi")
    (set_attr "length" "12")])
 
   [(set (match_operand:SI 0 "register_operand" "=r")
        (unspec:SI [(const_int 0)] UNSPEC_TP))]
   "!TARGET_64BIT"
-  "mov{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}"
+  "mov{l}\t{%%gs:0, %0|%0, DWORD PTR gs:0}"
   [(set_attr "type" "imov")
    (set_attr "modrm" "0")
    (set_attr "length" "7")
                 (match_operand:SI 1 "register_operand" "0")))
    (clobber (reg:CC FLAGS_REG))]
   "!TARGET_64BIT"
-  "add{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}"
+  "add{l}\t{%%gs:0, %0|%0, DWORD PTR gs:0}"
   [(set_attr "type" "alu")
    (set_attr "modrm" "0")
    (set_attr "length" "7")
   [(set (match_operand:DI 0 "register_operand" "=r")
        (unspec:DI [(const_int 0)] UNSPEC_TP))]
   "TARGET_64BIT"
-  "mov{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}"
+  "mov{q}\t{%%fs:0, %0|%0, QWORD PTR fs:0}"
   [(set_attr "type" "imov")
    (set_attr "modrm" "0")
    (set_attr "length" "7")
                 (match_operand:DI 1 "register_operand" "0")))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT"
-  "add{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}"
+  "add{q}\t{%%fs:0, %0|%0, QWORD PTR fs:0}"
   [(set_attr "type" "alu")
    (set_attr "modrm" "0")
    (set_attr "length" "7")
        (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
                   UNSPEC_TLSDESC))]
   "TARGET_64BIT && TARGET_GNU2_TLS"
-  "lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[%%rip]}"
+  "lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[rip]}"
   [(set_attr "type" "lea")
    (set_attr "mode" "DI")
    (set_attr "length" "7")
   "fsqrt"
   [(set_attr "type" "fpspc")
    (set_attr "mode" "XF")
-   (set_attr "athlon_decode" "direct")   
+   (set_attr "athlon_decode" "direct")
    (set_attr "amdfam10_decode" "direct")])
 
 (define_insn "*rsqrtsf2_sse"
 {
   rtx label = gen_label_rtx ();
 
-  emit_label (label);
+  rtx op2;
 
-  emit_insn (gen_fpremxf4_i387 (operands[1], operands[2],
-                               operands[1], operands[2]));
+  if (rtx_equal_p (operands[1], operands[2]))
+    {
+      op2 = gen_reg_rtx (XFmode);
+      emit_move_insn (op2, operands[2]);
+    }
+  else
+    op2 = operands[2];
+
+  emit_label (label);
+  emit_insn (gen_fpremxf4_i387 (operands[1], op2, operands[1], op2));
   ix86_emit_fp_unordered_jump (label);
   LABEL_NUSES (label) = 1;
 
 {
   rtx label = gen_label_rtx ();
 
-  emit_label (label);
+  rtx op2;
+
+  if (rtx_equal_p (operands[1], operands[2]))
+    {
+      op2 = gen_reg_rtx (XFmode);
+      emit_move_insn (op2, operands[2]);
+    }
+  else
+    op2 = operands[2];
 
-  emit_insn (gen_fprem1xf4_i387 (operands[1], operands[2],
-                                operands[1], operands[2]));
+  emit_label (label);
+  emit_insn (gen_fprem1xf4_i387 (operands[1], op2, operands[1], op2));
   ix86_emit_fp_unordered_jump (label);
   LABEL_NUSES (label) = 1;
 
        (unspec:MODEF [(match_operand:MODEF 1 "register_operand" "x")
                       (match_operand:SI 2 "const_0_to_15_operand" "n")]
                      UNSPEC_ROUND))]
-  "TARGET_SSE4_1"
+  "TARGET_ROUND"
   "rounds<ssemodefsuffix>\t{%2, %1, %0|%0, %1, %2}"
   [(set_attr "type" "ssecvt")
    (set_attr "prefix_extra" "1")
     && flag_unsafe_math_optimizations)
    || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
        && !flag_trapping_math
-       && (TARGET_SSE4_1 || !optimize_size))"
+       && (TARGET_ROUND || !optimize_size))"
 {
   if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
       && !flag_trapping_math
-      && (TARGET_SSE4_1 || !optimize_size))
+      && (TARGET_ROUND || !optimize_size))
     {
-      if (TARGET_SSE4_1)
+      if (TARGET_ROUND)
        emit_insn (gen_sse4_1_round<mode>2
                   (operands[0], operands[1], GEN_INT (0x04)));
       else
     && flag_unsafe_math_optimizations && !optimize_size)
    || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
        && !flag_trapping_math
-       && (TARGET_SSE4_1 || !optimize_size))"
+       && (TARGET_ROUND || !optimize_size))"
 {
   if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
       && !flag_trapping_math
-      && (TARGET_SSE4_1 || !optimize_size))
+      && (TARGET_ROUND || !optimize_size))
     {
-      if (TARGET_SSE4_1)
+      if (TARGET_ROUND)
        emit_insn (gen_sse4_1_round<mode>2
                   (operands[0], operands[1], GEN_INT (0x01)));
       else if (TARGET_64BIT || (<MODE>mode != DFmode))
     && flag_unsafe_math_optimizations && !optimize_size)
    || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
        && !flag_trapping_math
-       && (TARGET_SSE4_1 || !optimize_size))"
+       && (TARGET_ROUND || !optimize_size))"
 {
   if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
       && !flag_trapping_math
-      && (TARGET_SSE4_1 || !optimize_size))
+      && (TARGET_ROUND || !optimize_size))
     {
-      if (TARGET_SSE4_1)
+      if (TARGET_ROUND)
        emit_insn (gen_sse4_1_round<mode>2
                   (operands[0], operands[1], GEN_INT (0x02)));
       else if (TARGET_64BIT || (<MODE>mode != DFmode))
     && flag_unsafe_math_optimizations && !optimize_size)
    || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
        && !flag_trapping_math
-       && (TARGET_SSE4_1 || !optimize_size))"
+       && (TARGET_ROUND || !optimize_size))"
 {
   if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
       && !flag_trapping_math
-      && (TARGET_SSE4_1 || !optimize_size))
+      && (TARGET_ROUND || !optimize_size))
     {
-      if (TARGET_SSE4_1)
+      if (TARGET_ROUND)
        emit_insn (gen_sse4_1_round<mode>2
                   (operands[0], operands[1], GEN_INT (0x03)));
       else if (TARGET_64BIT || (<MODE>mode != DFmode))
   operands[5] = gen_rtx_PLUS (Pmode, operands[0], adjust);
   operands[6] = gen_rtx_PLUS (Pmode, operands[2], adjust);
 
-  if (TARGET_SINGLE_STRINGOP || optimize_size)
+  /* Can't use this if the user has appropriated esi or edi.  */
+  if ((TARGET_SINGLE_STRINGOP || optimize_size)
+      && !(fixed_regs[SI_REG] || fixed_regs[DI_REG]))
     {
       emit_insn (gen_strmov_singleop (operands[0], operands[1],
                                      operands[2], operands[3],
   rtx addr1, addr2, out, outlow, count, countreg, align;
 
   /* Can't use this if the user has appropriated esi or edi.  */
-  if (global_regs[4] || global_regs[5])
+  if (fixed_regs[SI_REG] || fixed_regs[DI_REG])
     FAIL;
 
   out = operands[0];
   [(set_attr "type" "fcmov")
    (set_attr "mode" "XF")])
 
+;; All moves in SSE5 pcmov instructions are 128 bits and hence we restrict
+;; the scalar versions to have only XMM registers as operands.
+
+;; SSE5 conditional move
+(define_insn "*sse5_pcmov_<mode>"
+  [(set (match_operand:MODEF 0 "register_operand" "=x,x")
+       (if_then_else:MODEF
+         (match_operand:MODEF 1 "register_operand" "x,0")
+         (match_operand:MODEF 2 "register_operand" "0,x")
+         (match_operand:MODEF 3 "register_operand" "x,x")))]
+  "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
+  "pcmov\t{%1, %3, %2, %0|%0, %2, %3, %1}"
+  [(set_attr "type" "sse4arg")])
+
 ;; These versions of the min/max patterns are intentionally ignorant of
 ;; their behavior wrt -0.0 and NaN (via the commutative operand mark).
 ;; Since both the tree-level MAX_EXPR and the rtl-level SMAX operator
                   (match_operand:SI 3 "immediate_operand" ""))
           (const_int 0)]))]
   "ix86_match_ccmode (insn, CCNOmode)
-   && (true_regnum (operands[2]) != 0
+   && (true_regnum (operands[2]) != AX_REG
        || satisfies_constraint_K (operands[3]))
    && peep2_reg_dead_p (1, operands[2])"
   [(parallel
           (const_int 0)]))]
   "! TARGET_PARTIAL_REG_STALL
    && ix86_match_ccmode (insn, CCNOmode)
-   && true_regnum (operands[2]) != 0
+   && true_regnum (operands[2]) != AX_REG
    && peep2_reg_dead_p (1, operands[2])"
   [(parallel
      [(set (match_dup 0)
           (const_int 0)]))]
   "! TARGET_PARTIAL_REG_STALL
    && ix86_match_ccmode (insn, CCNOmode)
-   && true_regnum (operands[2]) != 0
+   && true_regnum (operands[2]) != AX_REG
    && peep2_reg_dead_p (1, operands[2])"
   [(parallel [(set (match_dup 0)
                   (match_op_dup 1
        (call (mem:QI (reg:DI R11_REG))
              (match_operand:DI 1 "" "")))]
   "SIBLING_CALL_P (insn) && TARGET_64BIT"
-  "jmp\t*%%r11"
+  "jmp\t{*%%}r11"
   [(set_attr "type" "callv")])
 \f
 ;; We used to use "int $5", in honor of #BR which maps to interrupt vector 5.
    (set (match_scratch:SI 2 "=&r") (const_int 0))
    (clobber (reg:CC FLAGS_REG))]
   ""
-  "mov{l}\t{%%gs:%P1, %2|%2, DWORD PTR %%gs:%P1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2"
+  "mov{l}\t{%%gs:%P1, %2|%2, DWORD PTR gs:%P1}\;mov{l}\t{%2, %0|%0, %2}\;xor{l}\t%2, %2"
   [(set_attr "type" "multi")])
 
 (define_insn "stack_tls_protect_set_di"
         system call would not have to trash the userspace segment register,
         which would be expensive */
      if (ix86_cmodel != CM_KERNEL)
-        return "mov{q}\t{%%fs:%P1, %2|%2, QWORD PTR %%fs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
+        return "mov{q}\t{%%fs:%P1, %2|%2, QWORD PTR fs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
      else
-        return "mov{q}\t{%%gs:%P1, %2|%2, QWORD PTR %%gs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
+        return "mov{q}\t{%%gs:%P1, %2|%2, QWORD PTR gs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2";
   }
   [(set_attr "type" "multi")])
 
                    UNSPEC_SP_TLS_TEST))
    (clobber (match_scratch:SI 3 "=r"))]
   ""
-  "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%%gs:%P2, %3|%3, DWORD PTR %%gs:%P2}"
+  "mov{l}\t{%1, %3|%3, %1}\;xor{l}\t{%%gs:%P2, %3|%3, DWORD PTR gs:%P2}"
   [(set_attr "type" "multi")])
 
 (define_insn "stack_tls_protect_test_di"
         system call would not have to trash the userspace segment register,
         which would be expensive */
      if (ix86_cmodel != CM_KERNEL)
-        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%fs:%P2, %3|%3, QWORD PTR %%fs:%P2}";
+        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%fs:%P2, %3|%3, QWORD PTR fs:%P2}";
      else
-        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%gs:%P2, %3|%3, QWORD PTR %%gs:%P2}";
+        return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%gs:%P2, %3|%3, QWORD PTR gs:%P2}";
   }
   [(set_attr "type" "multi")])