OSDN Git Service

* config/i386/i386.c (ix86_print_operand): Handle 'q' and 'x'
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / sse.md
index e649b30..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])
 
   DONE;
 })
 
+(define_expand "reduc_umin_v8hi"
+  [(umin:V8HI
+     (match_operand:V8HI 0 "register_operand" "")
+     (match_operand:V8HI 1 "register_operand" ""))]
+  "TARGET_SSE4_1"
+{
+  ix86_expand_reduc (gen_uminv8hi3, operands[0], operands[1]);
+  DONE;
+})
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
 ;; Parallel floating point comparisons
    (set_attr "prefix" "vex")
    (set_attr "mode" "V4DF")])
 
-(define_insn "*avx_cvtdq2pd256_2"
+(define_insn "avx_cvtdq2pd256_2"
   [(set (match_operand:V4DF 0 "register_operand" "=x")
        (float:V4DF
          (vec_select:V4SI
            (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")
                       (const_int 2) (const_int 3)]))))]
   "TARGET_AVX")
 
-(define_expand "vec_unpacks_float_hi_v8hi"
-  [(match_operand:V4SF 0 "register_operand" "")
-   (match_operand:V8HI 1 "register_operand" "")]
+(define_mode_attr sseunpackfltmode
+  [(V8HI "V4SF") (V4SI "V2DF") (V16HI "V8SF") (V8SI "V4DF")])
+
+(define_expand "vec_unpacks_float_hi_<mode>"
+  [(match_operand:<sseunpackfltmode> 0 "register_operand" "")
+   (match_operand:VI2_AVX2 1 "register_operand" "")]
   "TARGET_SSE2"
 {
-  rtx tmp = gen_reg_rtx (V4SImode);
+  rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
 
-  emit_insn (gen_vec_unpacks_hi_v8hi (tmp, operands[1]));
-  emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+  emit_insn (gen_vec_unpacks_hi_<mode> (tmp, operands[1]));
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+                         gen_rtx_FLOAT (<sseunpackfltmode>mode, tmp)));
   DONE;
 })
 
-(define_expand "vec_unpacks_float_lo_v8hi"
-  [(match_operand:V4SF 0 "register_operand" "")
-   (match_operand:V8HI 1 "register_operand" "")]
+(define_expand "vec_unpacks_float_lo_<mode>"
+  [(match_operand:<sseunpackfltmode> 0 "register_operand" "")
+   (match_operand:VI2_AVX2 1 "register_operand" "")]
   "TARGET_SSE2"
 {
-  rtx tmp = gen_reg_rtx (V4SImode);
+  rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
 
-  emit_insn (gen_vec_unpacks_lo_v8hi (tmp, operands[1]));
-  emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+  emit_insn (gen_vec_unpacks_lo_<mode> (tmp, operands[1]));
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+                         gen_rtx_FLOAT (<sseunpackfltmode>mode, tmp)));
   DONE;
 })
 
-(define_expand "vec_unpacku_float_hi_v8hi"
-  [(match_operand:V4SF 0 "register_operand" "")
-   (match_operand:V8HI 1 "register_operand" "")]
+(define_expand "vec_unpacku_float_hi_<mode>"
+  [(match_operand:<sseunpackfltmode> 0 "register_operand" "")
+   (match_operand:VI2_AVX2 1 "register_operand" "")]
   "TARGET_SSE2"
 {
-  rtx tmp = gen_reg_rtx (V4SImode);
+  rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
 
-  emit_insn (gen_vec_unpacku_hi_v8hi (tmp, operands[1]));
-  emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+  emit_insn (gen_vec_unpacku_hi_<mode> (tmp, operands[1]));
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+                         gen_rtx_FLOAT (<sseunpackfltmode>mode, tmp)));
   DONE;
 })
 
-(define_expand "vec_unpacku_float_lo_v8hi"
-  [(match_operand:V4SF 0 "register_operand" "")
-   (match_operand:V8HI 1 "register_operand" "")]
+(define_expand "vec_unpacku_float_lo_<mode>"
+  [(match_operand:<sseunpackfltmode> 0 "register_operand" "")
+   (match_operand:VI2_AVX2 1 "register_operand" "")]
   "TARGET_SSE2"
 {
-  rtx tmp = gen_reg_rtx (V4SImode);
+  rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
 
-  emit_insn (gen_vec_unpacku_lo_v8hi (tmp, operands[1]));
-  emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+  emit_insn (gen_vec_unpacku_lo_<mode> (tmp, operands[1]));
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+                         gen_rtx_FLOAT (<sseunpackfltmode>mode, tmp)));
   DONE;
 })
 
     operands[i] = gen_reg_rtx (V2DFmode);
 })
 
+(define_expand "vec_unpacku_float_hi_v8si"
+  [(match_operand:V4DF 0 "register_operand" "")
+   (match_operand:V8SI 1 "register_operand" "")]
+  "TARGET_AVX"
+{
+  REAL_VALUE_TYPE TWO32r;
+  rtx x, tmp[6];
+  int i;
+
+  real_ldexp (&TWO32r, &dconst1, 32);
+  x = const_double_from_real_value (TWO32r, DFmode);
+
+  tmp[0] = force_reg (V4DFmode, CONST0_RTX (V4DFmode));
+  tmp[1] = force_reg (V4DFmode, ix86_build_const_vector (V4DFmode, 1, x));
+  tmp[5] = gen_reg_rtx (V4SImode);
+
+  for (i = 2; i < 5; i++)
+    tmp[i] = gen_reg_rtx (V4DFmode);
+  emit_insn (gen_vec_extract_hi_v8si (tmp[5], operands[1]));
+  emit_insn (gen_avx_cvtdq2pd256 (tmp[2], tmp[5]));
+  emit_insn (gen_rtx_SET (VOIDmode, tmp[3],
+                         gen_rtx_LT (V4DFmode, tmp[2], tmp[0])));
+  emit_insn (gen_andv4df3 (tmp[4], tmp[3], tmp[1]));
+  emit_insn (gen_addv4df3 (operands[0], tmp[2], tmp[4]));
+  DONE;
+})
+
+(define_expand "vec_unpacku_float_lo_v8si"
+  [(match_operand:V4DF 0 "register_operand" "")
+   (match_operand:V8SI 1 "nonimmediate_operand" "")]
+  "TARGET_AVX"
+{
+  REAL_VALUE_TYPE TWO32r;
+  rtx x, tmp[5];
+  int i;
+
+  real_ldexp (&TWO32r, &dconst1, 32);
+  x = const_double_from_real_value (TWO32r, DFmode);
+
+  tmp[0] = force_reg (V4DFmode, CONST0_RTX (V4DFmode));
+  tmp[1] = force_reg (V4DFmode, ix86_build_const_vector (V4DFmode, 1, x));
+
+  for (i = 2; i < 5; i++)
+    tmp[i] = gen_reg_rtx (V4DFmode);
+  emit_insn (gen_avx_cvtdq2pd256_2 (tmp[2], operands[1]));
+  emit_insn (gen_rtx_SET (VOIDmode, tmp[3],
+                         gen_rtx_LT (V4DFmode, tmp[2], tmp[0])));
+  emit_insn (gen_andv4df3 (tmp[4], tmp[3], tmp[1]));
+  emit_insn (gen_addv4df3 (operands[0], tmp[2], tmp[4]));
+  DONE;
+})
+
 (define_expand "vec_pack_trunc_v4df"
   [(set (match_dup 3)
        (float_truncate:V4SF
 })
 
 (define_expand "vec_set<mode>"
-  [(match_operand:V_128 0 "register_operand" "")
+  [(match_operand:V 0 "register_operand" "")
    (match_operand:<ssescalarmode> 1 "register_operand" "")
    (match_operand 2 "const_int_operand" "")]
   "TARGET_SSE"
   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_insn_and_split "mulv2di3"
-  [(set (match_operand:V2DI 0 "register_operand" "")
-       (mult:V2DI (match_operand:V2DI 1 "register_operand" "")
-                  (match_operand:V2DI 2 "register_operand" "")))]
+(define_insn_and_split "mul<mode>3"
+  [(set (match_operand:VI8_AVX2 0 "register_operand" "")
+       (mult:VI8_AVX2 (match_operand:VI8_AVX2 1 "register_operand" "")
+                      (match_operand:VI8_AVX2 2 "register_operand" "")))]
   "TARGET_SSE2
    && can_create_pseudo_p ()"
   "#"
   op1 = operands[1];
   op2 = operands[2];
 
-  if (TARGET_XOP)
+  if (TARGET_XOP && <MODE>mode == V2DImode)
     {
       /* op1: A,B,C,D, op2: E,F,G,H */
       op1 = gen_lowpart (V4SImode, op1);
     }
   else
     {
-      t1 = gen_reg_rtx (V2DImode);
-      t2 = gen_reg_rtx (V2DImode);
-      t3 = gen_reg_rtx (V2DImode);
-      t4 = gen_reg_rtx (V2DImode);
-      t5 = gen_reg_rtx (V2DImode);
-      t6 = gen_reg_rtx (V2DImode);
+      t1 = gen_reg_rtx (<MODE>mode);
+      t2 = gen_reg_rtx (<MODE>mode);
+      t3 = gen_reg_rtx (<MODE>mode);
+      t4 = gen_reg_rtx (<MODE>mode);
+      t5 = gen_reg_rtx (<MODE>mode);
+      t6 = gen_reg_rtx (<MODE>mode);
       thirtytwo = GEN_INT (32);
 
       /* Multiply low parts.  */
-      emit_insn (gen_sse2_umulv2siv2di3 (t1, gen_lowpart (V4SImode, op1),
-                                        gen_lowpart (V4SImode, op2)));
+      emit_insn (gen_<sse2_avx2>_umulv<ssescalarnum>si<mode>3
+                 (t1, gen_lowpart (<ssepackmode>mode, op1),
+                  gen_lowpart (<ssepackmode>mode, op2)));
 
-      /* Shift input vectors left 32 bits so we can multiply high parts.  */
-      emit_insn (gen_lshrv2di3 (t2, op1, thirtytwo));
-      emit_insn (gen_lshrv2di3 (t3, op2, thirtytwo));
+      /* Shift input vectors right 32 bits so we can multiply high parts.  */
+      emit_insn (gen_lshr<mode>3 (t2, op1, thirtytwo));
+      emit_insn (gen_lshr<mode>3 (t3, op2, thirtytwo));
 
       /* Multiply high parts by low parts.  */
-      emit_insn (gen_sse2_umulv2siv2di3 (t4, gen_lowpart (V4SImode, op1),
-                                        gen_lowpart (V4SImode, t3)));
-      emit_insn (gen_sse2_umulv2siv2di3 (t5, gen_lowpart (V4SImode, op2),
-                                        gen_lowpart (V4SImode, t2)));
+      emit_insn (gen_<sse2_avx2>_umulv<ssescalarnum>si<mode>3
+                 (t4, gen_lowpart (<ssepackmode>mode, op1),
+                  gen_lowpart (<ssepackmode>mode, t3)));
+      emit_insn (gen_<sse2_avx2>_umulv<ssescalarnum>si<mode>3
+                 (t5, gen_lowpart (<ssepackmode>mode, op2),
+                  gen_lowpart (<ssepackmode>mode, t2)));
 
       /* Shift them back.  */
-      emit_insn (gen_ashlv2di3 (t4, t4, thirtytwo));
-      emit_insn (gen_ashlv2di3 (t5, t5, thirtytwo));
+      emit_insn (gen_ashl<mode>3 (t4, t4, thirtytwo));
+      emit_insn (gen_ashl<mode>3 (t5, t5, thirtytwo));
 
       /* Add the three parts together.  */
-      emit_insn (gen_addv2di3 (t6, t1, t4));
-      emit_insn (gen_addv2di3 (op0, t6, t5));
+      emit_insn (gen_add<mode>3 (t6, t1, t4));
+      emit_insn (gen_add<mode>3 (op0, t6, t5));
     }
 
   set_unique_reg_note (get_last_insn (), REG_EQUAL,
-                      gen_rtx_MULT (V2DImode, operands[1], operands[2]));
+                      gen_rtx_MULT (<MODE>mode, operands[1], operands[2]));
   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_128 0 "register_operand" "=x,x")
-       (ashift:VI248_128
-         (match_operand:VI248_128 1 "register_operand" "0,x")
+  [(set (match_operand:VI248_AVX2 0 "register_operand" "=x,x")
+       (ashift:VI248_AVX2
+         (match_operand:VI248_AVX2 1 "register_operand" "0,x")
          (match_operand:SI 2 "nonmemory_operand" "xN,xN")))]
   "TARGET_SSE2"
   "@
        (const_string "0")))
    (set_attr "prefix_data16" "1,*")
    (set_attr "prefix" "orig,vex")
-   (set_attr "mode" "TI")])
+   (set_attr "mode" "<sseinsnmode>")])
 
 (define_expand "vec_shl_<mode>"
   [(set (match_operand:VI_128 0 "register_operand" "")
   DONE;
 })
 
+(define_mode_iterator VEC_PERM_CONST
+  [(V4SF "TARGET_SSE") (V4SI "TARGET_SSE")
+   (V2DF "TARGET_SSE") (V2DI "TARGET_SSE")
+   (V16QI "TARGET_SSE2") (V8HI "TARGET_SSE2")
+   (V8SF "TARGET_AVX") (V4DF "TARGET_AVX")
+   (V8SI "TARGET_AVX") (V4DI "TARGET_AVX")
+   (V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2")])
+
+(define_expand "vec_perm_const<mode>"
+  [(match_operand:VEC_PERM_CONST 0 "register_operand" "")
+   (match_operand:VEC_PERM_CONST 1 "register_operand" "")
+   (match_operand:VEC_PERM_CONST 2 "register_operand" "")
+   (match_operand:<sseintvecmode> 3 "" "")]
+  ""
+{
+  if (ix86_expand_vec_perm_const (operands))
+    DONE;
+  else
+    FAIL;
+})
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
 ;; Parallel bitwise logical operations
    (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
 
 (define_expand "vec_unpacks_lo_<mode>"
   [(match_operand:<sseunpackmode> 0 "register_operand" "")
-   (match_operand:VI124_128 1 "register_operand" "")]
+   (match_operand:VI124_AVX2 1 "register_operand" "")]
   "TARGET_SSE2"
   "ix86_expand_sse_unpack (operands, false, false); DONE;")
 
 (define_expand "vec_unpacks_hi_<mode>"
   [(match_operand:<sseunpackmode> 0 "register_operand" "")
-   (match_operand:VI124_128 1 "register_operand" "")]
+   (match_operand:VI124_AVX2 1 "register_operand" "")]
   "TARGET_SSE2"
   "ix86_expand_sse_unpack (operands, false, true); DONE;")
 
 (define_expand "vec_unpacku_lo_<mode>"
   [(match_operand:<sseunpackmode> 0 "register_operand" "")
-   (match_operand:VI124_128 1 "register_operand" "")]
+   (match_operand:VI124_AVX2 1 "register_operand" "")]
   "TARGET_SSE2"
   "ix86_expand_sse_unpack (operands, true, false); DONE;")
 
 (define_expand "vec_unpacku_hi_<mode>"
   [(match_operand:<sseunpackmode> 0 "register_operand" "")
-   (match_operand:VI124_128 1 "register_operand" "")]
+   (match_operand:VI124_AVX2 1 "register_operand" "")]
   "TARGET_SSE2"
   "ix86_expand_sse_unpack (operands, true, true); DONE;")
 
                       (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>")])