OSDN Git Service

* config/i386/i386.c (ix86_print_operand): Handle 'q' and 'x'
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / sse.md
index 372f8ee..25854e4 100644 (file)
    (V8SI "TARGET_AVX2") V4SI
    (V4DI "TARGET_AVX2") V2DI])
 
-(define_mode_iterator VI48_AVX2
-  [V8SI V4SI V4DI V2DI])
-
 (define_mode_iterator VI4SD_AVX2
   [V4SI V4DI])
 
 
 ;; Random 256bit vector integer mode combinations
 (define_mode_iterator VI124_256 [V32QI V16HI V8SI])
-(define_mode_iterator VI248_256 [V16HI V8SI V4DI])
 
 ;; Int-float size matches
 (define_mode_iterator VI4F_128 [V4SI V4SF])
    (V8SI "V8SI") (V4DI "V4DI")
    (V4SI "V4SI") (V2DI "V2DI")
    (V16HI "V16HI") (V8HI "V8HI")
-   (V32QI "V32QI") (V16QI "V16QI")
-  ])
+   (V32QI "V32QI") (V16QI "V16QI")])
 
 ;; Mapping of vector modes to a vector mode of double size
 (define_mode_attr ssedoublevecmode
    (V8SF "8") (V4DF "4")
    (V4SF "4") (V2DF "2")])
 
+;; SSE prefix for integer vector modes
+(define_mode_attr sseintprefix
+  [(V2DI "p") (V2DF "")
+   (V4DI "p") (V4DF "")
+   (V4SI "p") (V4SF "")
+   (V8SI "p") (V8SF "")])
+
 ;; SSE scalar suffix for vector modes
 (define_mode_attr ssescalarmodesuffix
   [(SF "ss") (DF "sd")
                       (V4DI "V4DI") (V4DF "V4DI")
                       (V4SI "V2DI") (V4SF "V2DI")
                       (V8SI "V4DI") (V8SF "V4DI")])
-(define_mode_attr gthrfirstp
-                     [(V2DI "p") (V2DF "")
-                      (V4DI "p") (V4DF "")
-                      (V4SI "p") (V4SF "")
-                      (V8SI "p") (V8SF "")])
-(define_mode_attr gthrlastp
-                     [(V2DI "q") (V2DF "pd")
-                      (V4DI "q") (V4DF "pd")
-                      (V4SI "d") (V4SF "ps")
-                      (V8SI "d") (V8SF "ps")])
 
 (define_mode_iterator FMAMODE [SF DF V4SF V2DF V8SF V4DF])
 
            (match_operand:V4SI 1 "nonimmediate_operand" "xm")
            (parallel [(const_int 0) (const_int 1)]))))]
   "TARGET_SSE2"
-  "%vcvtdq2pd\t{%1, %0|%0, %1}"
+  "%vcvtdq2pd\t{%1, %0|%0, %q1}"
   [(set_attr "type" "ssecvt")
    (set_attr "prefix" "maybe_vex")
    (set_attr "mode" "V2DF")])
            (match_operand:V4SF 1 "nonimmediate_operand" "xm")
            (parallel [(const_int 0) (const_int 1)]))))]
   "TARGET_SSE2"
-  "%vcvtps2pd\t{%1, %0|%0, %1}"
+  "%vcvtps2pd\t{%1, %0|%0, %q1}"
   [(set_attr "type" "ssecvt")
    (set_attr "amdfam10_decode" "direct")
    (set_attr "athlon_decode" "double")
   DONE;
 })
 
+(define_insn_and_split "*sse4_1_extractps"
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=rm,x,x")
+       (vec_select:SF
+         (match_operand:V4SF 1 "register_operand" "x,0,x")
+         (parallel [(match_operand:SI 2 "const_0_to_3_operand" "n,n,n")])))]
+  "TARGET_SSE4_1"
+  "@
+   %vextractps\t{%2, %1, %0|%0, %1, %2}
+   #
+   #"
+  "&& reload_completed && SSE_REG_P (operands[0])"
+  [(const_int 0)]
+{
+  rtx dest = gen_rtx_REG (V4SFmode, REGNO (operands[0]));
+  switch (INTVAL (operands[2]))
+    {
+    case 1:
+    case 3:
+      emit_insn (gen_sse_shufps_v4sf (dest, operands[1], operands[1],
+                                     operands[2], operands[2],
+                                     GEN_INT (INTVAL (operands[2]) + 4),
+                                     GEN_INT (INTVAL (operands[2]) + 4)));
+      break;
+    case 2:
+      emit_insn (gen_vec_interleave_highv4sf (dest, operands[1], operands[1]));
+      break;
+    default:
+      /* 0 should be handled by the *vec_extractv4sf_0 pattern above.  */
+      gcc_unreachable ();
+    }
+  DONE;
+}
+  [(set_attr "isa" "*,noavx,avx")
+   (set_attr "type" "sselog,*,*")
+   (set_attr "prefix_data16" "1,*,*")
+   (set_attr "prefix_extra" "1,*,*")
+   (set_attr "length_immediate" "1,*,*")
+   (set_attr "prefix" "maybe_vex,*,*")
+   (set_attr "mode" "V4SF,*,*")])
+
+(define_insn_and_split "*vec_extract_v4sf_mem"
+  [(set (match_operand:SF 0 "register_operand" "=x,*r,f")
+       (vec_select:SF
+        (match_operand:V4SF 1 "memory_operand" "o,o,o")
+        (parallel [(match_operand 2 "const_0_to_3_operand" "n,n,n")])))]
+  "TARGET_SSE"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+{
+  int i = INTVAL (operands[2]);
+
+  emit_move_insn (operands[0], adjust_address (operands[1], SFmode, i*4));
+  DONE;
+})
+
 (define_expand "avx_vextractf128<mode>"
   [(match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "")
    (match_operand:V_256 1 "register_operand" "")
    (set_attr "prefix" "vex")
    (set_attr "mode" "OI")])
 
-(define_insn_and_split "*sse4_1_extractps"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=rm,x,x")
-       (vec_select:SF
-         (match_operand:V4SF 1 "register_operand" "x,0,x")
-         (parallel [(match_operand:SI 2 "const_0_to_3_operand" "n,n,n")])))]
-  "TARGET_SSE4_1"
-  "@
-   %vextractps\t{%2, %1, %0|%0, %1, %2}
-   #
-   #"
-  "&& reload_completed && SSE_REG_P (operands[0])"
-  [(const_int 0)]
-{
-  rtx dest = gen_rtx_REG (V4SFmode, REGNO (operands[0]));
-  switch (INTVAL (operands[2]))
-    {
-    case 1:
-    case 3:
-      emit_insn (gen_sse_shufps_v4sf (dest, operands[1], operands[1],
-                                     operands[2], operands[2],
-                                     GEN_INT (INTVAL (operands[2]) + 4),
-                                     GEN_INT (INTVAL (operands[2]) + 4)));
-      break;
-    case 2:
-      emit_insn (gen_vec_interleave_highv4sf (dest, operands[1], operands[1]));
-      break;
-    default:
-      /* 0 should be handled by the *vec_extractv4sf_0 pattern above.  */
-      gcc_unreachable ();
-    }
-  DONE;
-}
-  [(set_attr "isa" "*,noavx,avx")
-   (set_attr "type" "sselog,*,*")
-   (set_attr "prefix_data16" "1,*,*")
-   (set_attr "prefix_extra" "1,*,*")
-   (set_attr "length_immediate" "1,*,*")
-   (set_attr "prefix" "maybe_vex,*,*")
-   (set_attr "mode" "V4SF,*,*")])
-
-(define_insn_and_split "*vec_extract_v4sf_mem"
-  [(set (match_operand:SF 0 "register_operand" "=x*rf")
-       (vec_select:SF
-        (match_operand:V4SF 1 "memory_operand" "o")
-        (parallel [(match_operand 2 "const_0_to_3_operand" "n")])))]
-  "TARGET_SSE"
-  "#"
-  "&& reload_completed"
-  [(const_int 0)]
-{
-  int i = INTVAL (operands[2]);
-
-  emit_move_insn (operands[0], adjust_address (operands[1], SFmode, i*4));
-  DONE;
-})
-
 ;; Modes handled by vec_extract patterns.
 (define_mode_iterator VEC_EXTRACT_MODE
   [(V32QI "TARGET_AVX") V16QI
   [(set (match_operand:V4DF 0 "register_operand"         "=x,x")
        (vec_select:V4DF
          (vec_concat:V8DF
-           (match_operand:V4DF 1 "nonimmediate_operand" "xm,x")
-           (match_operand:V4DF 2 "nonimmediate_operand" " 1,xm"))
+           (match_operand:V4DF 1 "nonimmediate_operand" " x,m")
+           (match_operand:V4DF 2 "nonimmediate_operand" "xm,1"))
          (parallel [(const_int 0) (const_int 4)
                     (const_int 2) (const_int 6)])))]
-  "TARGET_AVX
-   && (!MEM_P (operands[1]) || rtx_equal_p (operands[1], operands[2]))"
+  "TARGET_AVX"
   "@
-   vmovddup\t{%1, %0|%0, %1}
-   vunpcklpd\t{%2, %1, %0|%0, %1, %2}"
+   vunpcklpd\t{%2, %1, %0|%0, %1, %2}
+   vmovddup\t{%1, %0|%0, %1}"
   [(set_attr "type" "sselog")
    (set_attr "prefix" "vex")
    (set_attr "mode" "V4DF")])
   DONE;
 })
 
-;; Modes handled by vec_extract_even/odd pattern.
-(define_mode_iterator VEC_EXTRACT_EVENODD_MODE
-  [(V32QI "TARGET_AVX2") (V16QI "TARGET_SSE2")
-   (V16HI "TARGET_AVX2") (V8HI "TARGET_SSE2")
-   (V8SI "TARGET_AVX2") (V4SI "TARGET_SSE2")
-   (V4DI "TARGET_AVX2") (V2DI "TARGET_SSE2")
-   (V8SF "TARGET_AVX") V4SF
-   (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
-
-(define_expand "vec_extract_even<mode>"
-  [(match_operand:VEC_EXTRACT_EVENODD_MODE 0 "register_operand" "")
-   (match_operand:VEC_EXTRACT_EVENODD_MODE 1 "register_operand" "")
-   (match_operand:VEC_EXTRACT_EVENODD_MODE 2 "register_operand" "")]
-  "TARGET_SSE"
-{
-  ix86_expand_vec_extract_even_odd (operands[0], operands[1], operands[2], 0);
-  DONE;
-})
-
-(define_expand "vec_extract_odd<mode>"
-  [(match_operand:VEC_EXTRACT_EVENODD_MODE 0 "register_operand" "")
-   (match_operand:VEC_EXTRACT_EVENODD_MODE 1 "register_operand" "")
-   (match_operand:VEC_EXTRACT_EVENODD_MODE 2 "register_operand" "")]
-  "TARGET_SSE"
-{
-  ix86_expand_vec_extract_even_odd (operands[0], operands[1], operands[2], 1);
-  DONE;
-})
-
 ;; punpcklqdq and punpckhqdq are shorter than shufpd.
 (define_insn "avx2_interleave_highv4di"
   [(set (match_operand:V4DI 0 "register_operand" "=x")
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define_expand "neg<mode>2"
-  [(set (match_operand:VI_128 0 "register_operand" "")
-       (minus:VI_128
+  [(set (match_operand:VI_AVX2 0 "register_operand" "")
+       (minus:VI_AVX2
          (match_dup 2)
-         (match_operand:VI_128 1 "nonimmediate_operand" "")))]
+         (match_operand:VI_AVX2 1 "nonimmediate_operand" "")))]
   "TARGET_SSE2"
   "operands[2] = force_reg (<MODE>mode, CONST0_RTX (<MODE>mode));")
 
   DONE;
 })
 
-(define_expand "vec_widen_smult_hi_v8hi"
-  [(match_operand:V4SI 0 "register_operand" "")
-   (match_operand:V8HI 1 "register_operand" "")
-   (match_operand:V8HI 2 "register_operand" "")]
+(define_expand "vec_widen_<s>mult_hi_<mode>"
+  [(match_operand:<sseunpackmode> 0 "register_operand" "")
+   (any_extend:<sseunpackmode>
+     (match_operand:VI2_AVX2 1 "register_operand" ""))
+   (match_operand:VI2_AVX2 2 "register_operand" "")]
   "TARGET_SSE2"
 {
   rtx op1, op2, t1, t2, dest;
 
   op1 = operands[1];
   op2 = operands[2];
-  t1 = gen_reg_rtx (V8HImode);
-  t2 = gen_reg_rtx (V8HImode);
-  dest = gen_lowpart (V8HImode, operands[0]);
+  t1 = gen_reg_rtx (<MODE>mode);
+  t2 = gen_reg_rtx (<MODE>mode);
+  dest = gen_lowpart (<MODE>mode, operands[0]);
 
-  emit_insn (gen_mulv8hi3 (t1, op1, op2));
-  emit_insn (gen_smulv8hi3_highpart (t2, op1, op2));
-  emit_insn (gen_vec_interleave_highv8hi (dest, t1, t2));
+  emit_insn (gen_mul<mode>3 (t1, op1, op2));
+  emit_insn (gen_<s>mul<mode>3_highpart (t2, op1, op2));
+  emit_insn (gen_vec_interleave_high<mode> (dest, t1, t2));
   DONE;
 })
 
-(define_expand "vec_widen_smult_lo_v8hi"
-  [(match_operand:V4SI 0 "register_operand" "")
-   (match_operand:V8HI 1 "register_operand" "")
-   (match_operand:V8HI 2 "register_operand" "")]
+(define_expand "vec_widen_<s>mult_lo_<mode>"
+  [(match_operand:<sseunpackmode> 0 "register_operand" "")
+   (any_extend:<sseunpackmode>
+     (match_operand:VI2_AVX2 1 "register_operand" ""))
+   (match_operand:VI2_AVX2 2 "register_operand" "")]
   "TARGET_SSE2"
 {
   rtx op1, op2, t1, t2, dest;
 
   op1 = operands[1];
   op2 = operands[2];
-  t1 = gen_reg_rtx (V8HImode);
-  t2 = gen_reg_rtx (V8HImode);
-  dest = gen_lowpart (V8HImode, operands[0]);
+  t1 = gen_reg_rtx (<MODE>mode);
+  t2 = gen_reg_rtx (<MODE>mode);
+  dest = gen_lowpart (<MODE>mode, operands[0]);
 
-  emit_insn (gen_mulv8hi3 (t1, op1, op2));
-  emit_insn (gen_smulv8hi3_highpart (t2, op1, op2));
-  emit_insn (gen_vec_interleave_lowv8hi (dest, t1, t2));
+  emit_insn (gen_mul<mode>3 (t1, op1, op2));
+  emit_insn (gen_<s>mul<mode>3_highpart (t2, op1, op2));
+  emit_insn (gen_vec_interleave_low<mode> (dest, t1, t2));
   DONE;
 })
 
-(define_expand "vec_widen_umult_hi_v8hi"
-  [(match_operand:V4SI 0 "register_operand" "")
-   (match_operand:V8HI 1 "register_operand" "")
-   (match_operand:V8HI 2 "register_operand" "")]
-  "TARGET_SSE2"
+(define_expand "vec_widen_<s>mult_hi_v8si"
+  [(match_operand:V4DI 0 "register_operand" "")
+   (any_extend:V4DI (match_operand:V8SI 1 "nonimmediate_operand" ""))
+   (match_operand:V8SI 2 "nonimmediate_operand" "")]
+  "TARGET_AVX2"
 {
-  rtx op1, op2, t1, t2, dest;
-
-  op1 = operands[1];
-  op2 = operands[2];
-  t1 = gen_reg_rtx (V8HImode);
-  t2 = gen_reg_rtx (V8HImode);
-  dest = gen_lowpart (V8HImode, operands[0]);
+  rtx t1, t2, t3, t4;
 
-  emit_insn (gen_mulv8hi3 (t1, op1, op2));
-  emit_insn (gen_umulv8hi3_highpart (t2, op1, op2));
-  emit_insn (gen_vec_interleave_highv8hi (dest, t1, t2));
+  t1 = gen_reg_rtx (V4DImode);
+  t2 = gen_reg_rtx (V4DImode);
+  t3 = gen_reg_rtx (V8SImode);
+  t4 = gen_reg_rtx (V8SImode);
+  emit_insn (gen_avx2_permv4di_1 (t1, gen_lowpart (V4DImode, operands[1]),
+                                 const0_rtx, const2_rtx,
+                                 const1_rtx, GEN_INT (3)));
+  emit_insn (gen_avx2_permv4di_1 (t2, gen_lowpart (V4DImode, operands[2]),
+                                 const0_rtx, const2_rtx,
+                                 const1_rtx, GEN_INT (3)));
+  emit_insn (gen_avx2_pshufdv3 (t3, gen_lowpart (V8SImode, t1),
+                               GEN_INT (2 + (2 << 2) + (3 << 4) + (3 << 6))));
+  emit_insn (gen_avx2_pshufdv3 (t4, gen_lowpart (V8SImode, t2),
+                               GEN_INT (2 + (2 << 2) + (3 << 4) + (3 << 6))));
+  emit_insn (gen_avx2_<u>mulv4siv4di3 (operands[0], t3, t4));
   DONE;
 })
 
-(define_expand "vec_widen_umult_lo_v8hi"
-  [(match_operand:V4SI 0 "register_operand" "")
-   (match_operand:V8HI 1 "register_operand" "")
-   (match_operand:V8HI 2 "register_operand" "")]
-  "TARGET_SSE2"
+(define_expand "vec_widen_<s>mult_lo_v8si"
+  [(match_operand:V4DI 0 "register_operand" "")
+   (any_extend:V4DI (match_operand:V8SI 1 "nonimmediate_operand" ""))
+   (match_operand:V8SI 2 "nonimmediate_operand" "")]
+  "TARGET_AVX2"
 {
-  rtx op1, op2, t1, t2, dest;
-
-  op1 = operands[1];
-  op2 = operands[2];
-  t1 = gen_reg_rtx (V8HImode);
-  t2 = gen_reg_rtx (V8HImode);
-  dest = gen_lowpart (V8HImode, operands[0]);
+  rtx t1, t2, t3, t4;
 
-  emit_insn (gen_mulv8hi3 (t1, op1, op2));
-  emit_insn (gen_umulv8hi3_highpart (t2, op1, op2));
-  emit_insn (gen_vec_interleave_lowv8hi (dest, t1, t2));
+  t1 = gen_reg_rtx (V4DImode);
+  t2 = gen_reg_rtx (V4DImode);
+  t3 = gen_reg_rtx (V8SImode);
+  t4 = gen_reg_rtx (V8SImode);
+  emit_insn (gen_avx2_permv4di_1 (t1, gen_lowpart (V4DImode, operands[1]),
+                                 const0_rtx, const2_rtx,
+                                 const1_rtx, GEN_INT (3)));
+  emit_insn (gen_avx2_permv4di_1 (t2,  gen_lowpart (V4DImode, operands[2]),
+                                 const0_rtx, const2_rtx,
+                                 const1_rtx, GEN_INT (3)));
+  emit_insn (gen_avx2_pshufdv3 (t3, gen_lowpart (V8SImode, t1),
+                               GEN_INT (0 + (0 << 2) + (1 << 4) + (1 << 6))));
+  emit_insn (gen_avx2_pshufdv3 (t4, gen_lowpart (V8SImode, t2),
+                               GEN_INT (0 + (0 << 2) + (1 << 4) + (1 << 6))));
+  emit_insn (gen_avx2_<u>mulv4siv4di3 (operands[0], t3, t4));
   DONE;
 })
 
   [(match_operand:V2DI 0 "register_operand" "")
    (match_operand:V4SI 1 "register_operand" "")
    (match_operand:V4SI 2 "register_operand" "")]
-  "TARGET_XOP"
+  "TARGET_SSE4_1"
 {
-  rtx t1, t2;
+  rtx op1, op2, t1, t2;
 
+  op1 = operands[1];
+  op2 = operands[2];
   t1 = gen_reg_rtx (V4SImode);
   t2 = gen_reg_rtx (V4SImode);
 
-  emit_insn (gen_sse2_pshufd_1 (t1, operands[1],
-                               GEN_INT (0),
-                               GEN_INT (2),
-                               GEN_INT (1),
-                               GEN_INT (3)));
-  emit_insn (gen_sse2_pshufd_1 (t2, operands[2],
-                               GEN_INT (0),
-                               GEN_INT (2),
-                               GEN_INT (1),
-                               GEN_INT (3)));
-  emit_insn (gen_xop_mulv2div2di3_high (operands[0], t1, t2));
+  if (TARGET_XOP)
+    {
+      emit_insn (gen_sse2_pshufd_1 (t1, op1, GEN_INT (0), GEN_INT (2),
+                                   GEN_INT (1), GEN_INT (3)));
+      emit_insn (gen_sse2_pshufd_1 (t2, op2, GEN_INT (0), GEN_INT (2),
+                                   GEN_INT (1), GEN_INT (3)));
+      emit_insn (gen_xop_mulv2div2di3_high (operands[0], t1, t2));
+      DONE;
+    }
+
+  emit_insn (gen_vec_interleave_highv4si (t1, op1, op1));
+  emit_insn (gen_vec_interleave_highv4si (t2, op2, op2));
+  emit_insn (gen_sse4_1_mulv2siv2di3 (operands[0], t1, t2));
   DONE;
 })
 
   [(match_operand:V2DI 0 "register_operand" "")
    (match_operand:V4SI 1 "register_operand" "")
    (match_operand:V4SI 2 "register_operand" "")]
-  "TARGET_XOP"
+  "TARGET_SSE4_1"
 {
-  rtx t1, t2;
+  rtx op1, op2, t1, t2;
 
+  op1 = operands[1];
+  op2 = operands[2];
   t1 = gen_reg_rtx (V4SImode);
   t2 = gen_reg_rtx (V4SImode);
 
-  emit_insn (gen_sse2_pshufd_1 (t1, operands[1],
-                               GEN_INT (0),
-                               GEN_INT (2),
-                               GEN_INT (1),
-                               GEN_INT (3)));
-  emit_insn (gen_sse2_pshufd_1 (t2, operands[2],
-                               GEN_INT (0),
-                               GEN_INT (2),
-                               GEN_INT (1),
-                               GEN_INT (3)));
-  emit_insn (gen_xop_mulv2div2di3_low (operands[0], t1, t2));
+  if (TARGET_XOP)
+    {
+      emit_insn (gen_sse2_pshufd_1 (t1, op1, GEN_INT (0), GEN_INT (2),
+                                   GEN_INT (1), GEN_INT (3)));
+      emit_insn (gen_sse2_pshufd_1 (t2, op2, GEN_INT (0), GEN_INT (2),
+                                   GEN_INT (1), GEN_INT (3)));
+      emit_insn (gen_xop_mulv2div2di3_low (operands[0], t1, t2));
+      DONE;
+    }
+
+  emit_insn (gen_vec_interleave_lowv4si (t1, op1, op1));
+  emit_insn (gen_vec_interleave_lowv4si (t2, op2, op2));
+  emit_insn (gen_sse4_1_mulv2siv2di3 (operands[0], t1, t2));
   DONE;
 })
 
   DONE;
 })
 
-(define_expand "sdot_prodv8hi"
-  [(match_operand:V4SI 0 "register_operand" "")
-   (match_operand:V8HI 1 "register_operand" "")
-   (match_operand:V8HI 2 "register_operand" "")
-   (match_operand:V4SI 3 "register_operand" "")]
+(define_expand "sdot_prod<mode>"
+  [(match_operand:<sseunpackmode> 0 "register_operand" "")
+   (match_operand:VI2_AVX2 1 "register_operand" "")
+   (match_operand:VI2_AVX2 2 "register_operand" "")
+   (match_operand:<sseunpackmode> 3 "register_operand" "")]
   "TARGET_SSE2"
 {
-  rtx t = gen_reg_rtx (V4SImode);
-  emit_insn (gen_sse2_pmaddwd (t, operands[1], operands[2]));
-  emit_insn (gen_addv4si3 (operands[0], operands[3], t));
+  rtx t = gen_reg_rtx (<sseunpackmode>mode);
+  emit_insn (gen_<sse2_avx2>_pmaddwd (t, operands[1], operands[2]));
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+                         gen_rtx_PLUS (<sseunpackmode>mode,
+                                       operands[3], t)));
   DONE;
 })
 
-(define_expand "udot_prodv4si"
+(define_code_attr sse2_sse4_1
+   [(zero_extend "sse2") (sign_extend "sse4_1")])
+
+(define_expand "<s>dot_prodv4si"
   [(match_operand:V2DI 0 "register_operand" "")
-   (match_operand:V4SI 1 "register_operand" "")
+   (any_extend:V2DI (match_operand:V4SI 1 "register_operand" ""))
    (match_operand:V4SI 2 "register_operand" "")
    (match_operand:V2DI 3 "register_operand" "")]
-  "TARGET_SSE2"
+  "<CODE> == ZERO_EXTEND ? TARGET_SSE2 : TARGET_SSE4_1"
 {
   rtx t1, t2, t3, t4;
 
   t1 = gen_reg_rtx (V2DImode);
-  emit_insn (gen_sse2_umulv2siv2di3 (t1, operands[1], operands[2]));
+  emit_insn (gen_<sse2_sse4_1>_<u>mulv2siv2di3 (t1, operands[1], operands[2]));
   emit_insn (gen_addv2di3 (t1, t1, operands[3]));
 
   t2 = gen_reg_rtx (V4SImode);
                                 GEN_INT (32)));
 
   t4 = gen_reg_rtx (V2DImode);
-  emit_insn (gen_sse2_umulv2siv2di3 (t4, t2, t3));
+  emit_insn (gen_<sse2_sse4_1>_<u>mulv2siv2di3 (t4, t2, t3));
 
   emit_insn (gen_addv2di3 (operands[0], t1, t4));
   DONE;
 })
 
+(define_expand "<s>dot_prodv8si"
+  [(match_operand:V4DI 0 "register_operand" "")
+   (any_extend:V4DI (match_operand:V8SI 1 "register_operand" ""))
+   (match_operand:V8SI 2 "register_operand" "")
+   (match_operand:V4DI 3 "register_operand" "")]
+  "TARGET_AVX2"
+{
+  rtx t1, t2, t3, t4;
+
+  t1 = gen_reg_rtx (V4DImode);
+  emit_insn (gen_avx2_<u>mulv4siv4di3 (t1, operands[1], operands[2]));
+  emit_insn (gen_addv4di3 (t1, t1, operands[3]));
+
+  t2 = gen_reg_rtx (V8SImode);
+  t3 = gen_reg_rtx (V8SImode);
+  emit_insn (gen_avx2_lshrv2ti3 (gen_lowpart (V2TImode, t2),
+                                gen_lowpart (V2TImode, operands[1]),
+                                GEN_INT (32)));
+  emit_insn (gen_avx2_lshrv2ti3 (gen_lowpart (V2TImode, t3),
+                                gen_lowpart (V2TImode, operands[2]),
+                                GEN_INT (32)));
+
+  t4 = gen_reg_rtx (V4DImode);
+  emit_insn (gen_avx2_<u>mulv4siv4di3 (t4, t2, t3));
+
+  emit_insn (gen_addv4di3 (operands[0], t1, t4));
+  DONE;
+})
+
 (define_insn "ashr<mode>3"
   [(set (match_operand:VI24_AVX2 0 "register_operand" "=x,x")
        (ashiftrt:VI24_AVX2
    (set_attr "prefix" "orig,vex")
    (set_attr "mode" "<sseinsnmode>")])
 
-(define_insn "avx2_lshl<mode>3"
-  [(set (match_operand:VI248_256 0 "register_operand" "=x")
-       (ashift:VI248_256
-         (match_operand:VI248_256 1 "register_operand" "x")
-         (match_operand:SI 2 "nonmemory_operand" "xN")))]
-  "TARGET_AVX2"
-  "vpsll<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
-  [(set_attr "type" "sseishft")
-   (set_attr "prefix" "vex")
-   (set (attr "length_immediate")
-     (if_then_else (match_operand 2 "const_int_operand" "")
-       (const_string "1")
-       (const_string "0")))
-   (set_attr "mode" "OI")])
-
 (define_insn "ashl<mode>3"
   [(set (match_operand:VI248_AVX2 0 "register_operand" "=x,x")
        (ashift:VI248_AVX2
    (set_attr "prefix" "orig,vex")
    (set_attr "mode" "TI")])
 
+(define_expand "vec_interleave_high<mode>"
+  [(match_operand:VI_256 0 "register_operand" "=x")
+   (match_operand:VI_256 1 "register_operand" "x")
+   (match_operand:VI_256 2 "nonimmediate_operand" "xm")]
+ "TARGET_AVX2"
+{
+  rtx t1 = gen_reg_rtx (<MODE>mode);
+  rtx t2 = gen_reg_rtx (<MODE>mode);
+  emit_insn (gen_avx2_interleave_low<mode> (t1, operands[1], operands[2]));
+  emit_insn (gen_avx2_interleave_high<mode> (t2,  operands[1], operands[2]));
+  emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, operands[0]),
+                               gen_lowpart (V4DImode, t1),
+                               gen_lowpart (V4DImode, t2), GEN_INT (1 + (3 << 4))));
+  DONE;
+})
+
+(define_expand "vec_interleave_low<mode>"
+  [(match_operand:VI_256 0 "register_operand" "=x")
+   (match_operand:VI_256 1 "register_operand" "x")
+   (match_operand:VI_256 2 "nonimmediate_operand" "xm")]
+ "TARGET_AVX2"
+{
+  rtx t1 = gen_reg_rtx (<MODE>mode);
+  rtx t2 = gen_reg_rtx (<MODE>mode);
+  emit_insn (gen_avx2_interleave_low<mode> (t1, operands[1], operands[2]));
+  emit_insn (gen_avx2_interleave_high<mode> (t2, operands[1], operands[2]));
+  emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, operands[0]),
+                               gen_lowpart (V4DImode, t1),
+                               gen_lowpart (V4DImode, t2), GEN_INT (0 + (2 << 4))));
+  DONE;
+})
+
 ;; Modes handled by pinsr patterns.
 (define_mode_iterator PINSR_MODE
   [(V16QI "TARGET_SSE4_1") V8HI
                       (const_int 6)
                       (const_int 7)]))))]
   "TARGET_SSE4_1"
-  "%vpmov<extsuffix>bw\t{%1, %0|%0, %1}"
+  "%vpmov<extsuffix>bw\t{%1, %0|%0, %q1}"
   [(set_attr "type" "ssemov")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "maybe_vex")
                       (const_int 6)
                       (const_int 7)]))))]
   "TARGET_AVX2"
-  "vpmov<extsuffix>bd\t{%1, %0|%0, %1}"
+  "vpmov<extsuffix>bd\t{%1, %0|%0, %q1}"
   [(set_attr "type" "ssemov")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "vex")
                       (const_int 2)
                       (const_int 3)]))))]
   "TARGET_SSE4_1"
-  "%vpmov<extsuffix>bd\t{%1, %0|%0, %1}"
+  "%vpmov<extsuffix>bd\t{%1, %0|%0, %k1}"
   [(set_attr "type" "ssemov")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "maybe_vex")
                       (const_int 2)
                       (const_int 3)]))))]
   "TARGET_SSE4_1"
-  "%vpmov<extsuffix>wd\t{%1, %0|%0, %1}"
+  "%vpmov<extsuffix>wd\t{%1, %0|%0, %q1}"
   [(set_attr "type" "ssemov")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "maybe_vex")
                       (const_int 2)
                       (const_int 3)]))))]
   "TARGET_AVX2"
-  "vpmov<extsuffix>bq\t{%1, %0|%0, %1}"
+  "vpmov<extsuffix>bq\t{%1, %0|%0, %k1}"
   [(set_attr "type" "ssemov")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "vex")
            (parallel [(const_int 0)
                       (const_int 1)]))))]
   "TARGET_SSE4_1"
-  "%vpmov<extsuffix>bq\t{%1, %0|%0, %1}"
+  "%vpmov<extsuffix>bq\t{%1, %0|%0, %w1}"
   [(set_attr "type" "ssemov")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "maybe_vex")
                       (const_int 2)
                       (const_int 3)]))))]
   "TARGET_AVX2"
-  "vpmov<extsuffix>wq\t{%1, %0|%0, %1}"
+  "vpmov<extsuffix>wq\t{%1, %0|%0, %q1}"
   [(set_attr "type" "ssemov")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "vex")
            (parallel [(const_int 0)
                       (const_int 1)]))))]
   "TARGET_SSE4_1"
-  "%vpmov<extsuffix>wq\t{%1, %0|%0, %1}"
+  "%vpmov<extsuffix>wq\t{%1, %0|%0, %k1}"
   [(set_attr "type" "ssemov")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "maybe_vex")
            (parallel [(const_int 0)
                       (const_int 1)]))))]
   "TARGET_SSE4_1"
-  "%vpmov<extsuffix>dq\t{%1, %0|%0, %1}"
+  "%vpmov<extsuffix>dq\t{%1, %0|%0, %q1}"
   [(set_attr "type" "ssemov")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "maybe_vex")
    (set_attr "prefix" "vex")
    (set_attr "mode" "OI")])
 
-(define_expand "<avx_avx2>_maskload<ssemodesuffix><avxsizesuffix>"
-  [(set (match_operand:V48_AVX2 0 "register_operand" "")
-       (unspec:V48_AVX2
-         [(match_operand:<sseintvecmode> 2 "register_operand" "")
-          (match_operand:V48_AVX2 1 "memory_operand" "")
-          (match_dup 0)]
-         UNSPEC_MASKMOV))]
-  "TARGET_AVX")
-
-(define_expand "<avx_avx2>_maskstore<ssemodesuffix><avxsizesuffix>"
-  [(set (match_operand:V48_AVX2 0 "memory_operand" "")
+(define_insn "<avx_avx2>_maskload<ssemodesuffix><avxsizesuffix>"
+  [(set (match_operand:V48_AVX2 0 "register_operand" "=x")
        (unspec:V48_AVX2
-         [(match_operand:<sseintvecmode> 1 "register_operand" "")
-          (match_operand:V48_AVX2 2 "register_operand" "")
-          (match_dup 0)]
+         [(match_operand:<sseintvecmode> 2 "register_operand" "x")
+          (match_operand:V48_AVX2 1 "memory_operand" "m")]
          UNSPEC_MASKMOV))]
-  "TARGET_AVX")
-
-(define_insn "*avx2_maskmov<ssemodesuffix><avxsizesuffix>"
-  [(set (match_operand:VI48_AVX2 0 "nonimmediate_operand" "=x,m")
-       (unspec:VI48_AVX2
-         [(match_operand:<sseintvecmode> 1 "register_operand" "x,x")
-          (match_operand:VI48_AVX2 2 "nonimmediate_operand" "m,x")
-          (match_dup 0)]
-         UNSPEC_MASKMOV))]
-  "TARGET_AVX2
-   && (REG_P (operands[0]) == MEM_P (operands[2]))"
-  "vpmaskmov<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+  "TARGET_AVX"
+  "v<sseintprefix>maskmov<ssemodesuffix>\t{%1, %2, %0|%0, %2, %1}"
   [(set_attr "type" "sselog1")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "vex")
    (set_attr "mode" "<sseinsnmode>")])
 
-(define_insn "*avx_maskmov<ssemodesuffix><avxsizesuffix>"
-  [(set (match_operand:VF 0 "nonimmediate_operand" "=x,m")
-       (unspec:VF
-         [(match_operand:<sseintvecmode> 1 "register_operand" "x,x")
-          (match_operand:VF 2 "nonimmediate_operand" "m,x")
+(define_insn "<avx_avx2>_maskstore<ssemodesuffix><avxsizesuffix>"
+  [(set (match_operand:V48_AVX2 0 "memory_operand" "=m")
+       (unspec:V48_AVX2
+         [(match_operand:<sseintvecmode> 1 "register_operand" "x")
+          (match_operand:V48_AVX2 2 "register_operand" "x")
           (match_dup 0)]
          UNSPEC_MASKMOV))]
-  "TARGET_AVX
-   && (REG_P (operands[0]) == MEM_P (operands[2]))"
-  "vmaskmov<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+  "TARGET_AVX"
+  "v<sseintprefix>maskmov<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
   [(set_attr "type" "sselog1")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "vex")
-   (set_attr "mode" "<MODE>")])
+   (set_attr "mode" "<sseinsnmode>")])
 
 (define_insn_and_split "avx_<castmode><avxsizesuffix>_<castmode>"
   [(set (match_operand:AVX256MODE2P 0 "nonimmediate_operand" "=x,m")
   [(parallel [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "")
                   (unspec:VEC_GATHER_MODE
                     [(match_operand:VEC_GATHER_MODE 1 "register_operand" "")
-                     (match_operand 2 "register_operand" "")
+                     (mem:<ssescalarmode>
+                       (match_par_dup 7
+                         [(match_operand 2 "vsib_address_operand" "")
+                          (match_operand:<VEC_GATHER_MODE> 3 "register_operand" "")
+                          (match_operand:SI 5 "const1248_operand " "")]))
                      (mem:BLK (scratch))
-                     (match_operand:<VEC_GATHER_MODE> 3 "register_operand" "")
-                     (match_operand:VEC_GATHER_MODE 4 "register_operand" "")
-                     (match_operand:SI 5 "const1248_operand " "")]
+                     (match_operand:VEC_GATHER_MODE 4 "register_operand" "")]
                     UNSPEC_GATHER))
              (clobber (match_scratch:VEC_GATHER_MODE 6 ""))])]
-  "TARGET_AVX2")
+  "TARGET_AVX2"
+{
+  operands[7]
+    = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, operands[2], operands[3],
+                                       operands[5]), UNSPEC_VSIBADDR);
+})
 
 (define_insn "*avx2_gathersi<mode>"
   [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "=&x")
        (unspec:VEC_GATHER_MODE
          [(match_operand:VEC_GATHER_MODE 2 "register_operand" "0")
-          (match_operand:P 3 "register_operand" "r")
+          (match_operator:<ssescalarmode> 7 "vsib_mem_operator"
+            [(unspec:P
+               [(match_operand:P 3 "vsib_address_operand" "p")
+                (match_operand:<VEC_GATHER_MODE> 4 "register_operand" "x")
+                (match_operand:SI 6 "const1248_operand" "n")]
+               UNSPEC_VSIBADDR)])
           (mem:BLK (scratch))
-          (match_operand:<VEC_GATHER_MODE> 4 "register_operand" "x")
-          (match_operand:VEC_GATHER_MODE 5 "register_operand" "1")
-          (match_operand:SI 6 "const1248_operand" "n")]
+          (match_operand:VEC_GATHER_MODE 5 "register_operand" "1")]
          UNSPEC_GATHER))
    (clobber (match_scratch:VEC_GATHER_MODE 1 "=&x"))]
   "TARGET_AVX2"
-  "v<gthrfirstp>gatherd<gthrlastp>\t{%1, (%3, %4, %p6), %0|%0, (%3, %4, %p6), %1}"
+  "v<sseintprefix>gatherd<ssemodesuffix>\t{%1, %7, %0|%0, %7, %1}"
   [(set_attr "type" "ssemov")
    (set_attr "prefix" "vex")
    (set_attr "mode" "<sseinsnmode>")])
   [(parallel [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "")
                   (unspec:VEC_GATHER_MODE
                     [(match_operand:VEC_GATHER_MODE 1 "register_operand" "")
-                     (match_operand 2 "register_operand" "")
+                     (mem:<ssescalarmode>
+                       (match_par_dup 7
+                         [(match_operand 2 "vsib_address_operand" "")
+                          (match_operand:<AVXMODE48P_DI> 3 "register_operand" "")
+                          (match_operand:SI 5 "const1248_operand " "")]))
                      (mem:BLK (scratch))
-                     (match_operand:<AVXMODE48P_DI> 3 "register_operand" "")
-                     (match_operand:VEC_GATHER_MODE 4 "register_operand" "")
-                     (match_operand:SI 5 "const1248_operand " "")]
+                     (match_operand:VEC_GATHER_MODE 4 "register_operand" "")]
                     UNSPEC_GATHER))
              (clobber (match_scratch:VEC_GATHER_MODE 6 ""))])]
-  "TARGET_AVX2")
+  "TARGET_AVX2"
+{
+  operands[7]
+    = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, operands[2], operands[3],
+                                       operands[5]), UNSPEC_VSIBADDR);
+})
 
 (define_insn "*avx2_gatherdi<mode>"
   [(set (match_operand:AVXMODE48P_DI 0 "register_operand" "=&x")
        (unspec:AVXMODE48P_DI
          [(match_operand:AVXMODE48P_DI 2 "register_operand" "0")
-          (match_operand:P 3 "register_operand" "r")
+          (match_operator:<ssescalarmode> 7 "vsib_mem_operator"
+            [(unspec:P
+               [(match_operand:P 3 "vsib_address_operand" "p")
+                (match_operand:<AVXMODE48P_DI> 4 "register_operand" "x")
+                (match_operand:SI 6 "const1248_operand" "n")]
+               UNSPEC_VSIBADDR)])
           (mem:BLK (scratch))
-          (match_operand:<AVXMODE48P_DI> 4 "register_operand" "x")
-          (match_operand:AVXMODE48P_DI 5 "register_operand" "1")
-          (match_operand:SI 6 "const1248_operand" "n")]
+          (match_operand:AVXMODE48P_DI 5 "register_operand" "1")]
          UNSPEC_GATHER))
    (clobber (match_scratch:AVXMODE48P_DI 1 "=&x"))]
   "TARGET_AVX2"
-  "v<gthrfirstp>gatherq<gthrlastp>\t{%1, (%3, %4, %p6), %0|%0, (%3, %4, %p6), %1}"
+  "v<sseintprefix>gatherq<ssemodesuffix>\t{%1, %7, %0|%0, %7, %1}"
   [(set_attr "type" "ssemov")
    (set_attr "prefix" "vex")
    (set_attr "mode" "<sseinsnmode>")])
   [(parallel [(set (match_operand:VI4F_128 0 "register_operand" "")
                   (unspec:VI4F_128
                     [(match_operand:VI4F_128 1 "register_operand" "")
-                     (match_operand 2 "register_operand" "")
+                     (mem:<ssescalarmode>
+                       (match_par_dup 7
+                         [(match_operand 2 "vsib_address_operand" "")
+                          (match_operand:V4DI 3 "register_operand" "")
+                          (match_operand:SI 5 "const1248_operand " "")]))
                      (mem:BLK (scratch))
-                     (match_operand:V4DI 3 "register_operand" "")
-                     (match_operand:VI4F_128 4 "register_operand" "")
-                     (match_operand:SI 5 "const1248_operand " "")]
+                     (match_operand:VI4F_128 4 "register_operand" "")]
                     UNSPEC_GATHER))
              (clobber (match_scratch:VI4F_128 6 ""))])]
-  "TARGET_AVX2")
+  "TARGET_AVX2"
+{
+  operands[7]
+    = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, operands[2], operands[3],
+                                       operands[5]), UNSPEC_VSIBADDR);
+})
 
 (define_insn "*avx2_gatherdi<mode>256"
   [(set (match_operand:VI4F_128 0 "register_operand" "=x")
        (unspec:VI4F_128
          [(match_operand:VI4F_128 2 "register_operand" "0")
-          (match_operand:P 3 "register_operand" "r")
+          (match_operator:<ssescalarmode> 7 "vsib_mem_operator"
+            [(unspec:P
+               [(match_operand:P 3 "vsib_address_operand" "p")
+                (match_operand:V4DI 4 "register_operand" "x")
+                (match_operand:SI 6 "const1248_operand" "n")]
+               UNSPEC_VSIBADDR)])
           (mem:BLK (scratch))
-          (match_operand:V4DI 4 "register_operand" "x")
-          (match_operand:VI4F_128 5 "register_operand" "1")
-          (match_operand:SI 6 "const1248_operand" "n")]
+          (match_operand:VI4F_128 5 "register_operand" "1")]
          UNSPEC_GATHER)) 
    (clobber (match_scratch:VI4F_128 1 "=&x"))]
   "TARGET_AVX2"
-  "v<gthrfirstp>gatherq<gthrlastp>\t{%1, (%3, %4, %p6), %0|%0, (%3, %4, %p6), %1}"
+  "v<sseintprefix>gatherq<ssemodesuffix>\t{%1, %7, %0|%0, %7, %1}"
   [(set_attr "type" "ssemov")
    (set_attr "prefix" "vex")
    (set_attr "mode" "<sseinsnmode>")])