Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md	(revision 242765)
+++ config/i386/i386.md	(working copy)
@@ -970,6 +970,11 @@
 (define_mode_iterator SWI1248_AVX512BWDQ
   [(QI "TARGET_AVX512DQ") HI (SI "TARGET_AVX512BW") (DI "TARGET_AVX512BW")])
 
+;; All integer modes with AVX512BW, where HImode operation
+;; can be used instead of QImode.
+(define_mode_iterator SWI1248_AVX512BW
+  [QI HI (SI "TARGET_AVX512BW") (DI "TARGET_AVX512BW")])
+
 ;; All integer modes without QImode.
 (define_mode_iterator SWI248x [HI SI DI])
 
@@ -2574,11 +2582,15 @@
 
 (define_insn "*movqi_internal"
   [(set (match_operand:QI 0 "nonimmediate_operand"
-			"=q,q ,q ,r,r ,?r,m ,k,k,r ,m,k")
+			"=q,q ,q ,r,r ,?r,m ,k,k,r,m,k")
 	(match_operand:QI 1 "general_operand"
-			"q ,qn,qm,q,rn,qm,qn,r ,k,k,k,m"))]
+			"q ,qn,qm,q,rn,qm,qn,r,k,k,k,m"))]
   "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
 {
+  static char buf[128];
+  const char *ops;
+  const char *suffix;
+
   switch (get_attr_type (insn))
     {
     case TYPE_IMOVX:
@@ -2588,24 +2600,33 @@
     case TYPE_MSKMOV:
       switch (which_alternative)
         {
-	case 7: return TARGET_AVX512DQ ? "kmovb\t{%k1, %0|%0, %k1}"
-				       : "kmovw\t{%k1, %0|%0, %k1}";
-	case 8: return TARGET_AVX512DQ ? "kmovb\t{%1, %0|%0, %1}"
-				       : "kmovw\t{%1, %0|%0, %1}";
-	case 9: return TARGET_AVX512DQ ? "kmovb\t{%1, %k0|%k0, %1}"
-				       : "kmovw\t{%1, %k0|%k0, %1}";
+	case 7:
+	  ops = "kmov%s\t{%%k1, %%0|%%0, %%k1}";
+	  break;
+	case 9:
+	  ops = "kmov%s\t{%%1, %%k0|%%k0, %%1}";
+	  break;
 	case 10:
 	case 11:
 	  gcc_assert (TARGET_AVX512DQ);
-	  return "kmovb\t{%1, %0|%0, %1}";
-	default: gcc_unreachable ();
+	  /* FALLTHRU */
+	case 8:
+	  ops = "kmov%s\t{%%1, %%0|%%0, %%1}";
+	  break;
+	default:
+	  gcc_unreachable ();
 	}
 
+      suffix = (get_attr_mode (insn) == MODE_HI) ? "w" : "b";
+
+      snprintf (buf, sizeof (buf), ops, suffix);
+      return buf;
+
     default:
       if (get_attr_mode (insn) == MODE_SI)
-        return "mov{l}\t{%k1, %k0|%k0, %k1}";
+	return "mov{l}\t{%k1, %k0|%k0, %k1}";
       else
-        return "mov{b}\t{%1, %0|%0, %1}";
+	return "mov{b}\t{%1, %0|%0, %1}";
     }
 }
   [(set (attr "isa")
@@ -2640,6 +2661,9 @@
 	       (const_string "SI")
 	     (eq_attr "alternative" "6")
 	       (const_string "QI")
+	     (and (eq_attr "alternative" "7,8,9")
+		  (not (match_test "TARGET_AVX512DQ")))
+	       (const_string "HI")
 	     (eq_attr "type" "imovx")
 	       (const_string "SI")
 	     (and (eq_attr "type" "imov")
@@ -8055,23 +8079,26 @@
 	(any_logic:SWI1248x (match_dup 1)
 			    (match_dup 2)))])
 
-(define_mode_iterator SWI1248_AVX512BW
-  [QI HI (SI "TARGET_AVX512BW") (DI "TARGET_AVX512BW")])
-
 (define_insn "*k<logic><mode>"
   [(set (match_operand:SWI1248_AVX512BW 0 "mask_reg_operand" "=k")
-	(any_logic:SWI1248_AVX512BW (match_operand:SWI1248_AVX512BW 1 "mask_reg_operand" "k")
-				    (match_operand:SWI1248_AVX512BW 2 "mask_reg_operand" "k")))]
+	(any_logic:SWI1248_AVX512BW
+	  (match_operand:SWI1248_AVX512BW 1 "mask_reg_operand" "k")
+	  (match_operand:SWI1248_AVX512BW 2 "mask_reg_operand" "k")))]
   "TARGET_AVX512F"
   {
-    if (!TARGET_AVX512DQ && <MODE>mode == QImode)
+    if (get_attr_mode (insn) == MODE_HI)
       return "k<logic>w\t{%2, %1, %0|%0, %1, %2}";
     else
       return "k<logic><mskmodesuffix>\t{%2, %1, %0|%0, %1, %2}";
   }
-  [(set_attr "mode" "<MODE>")
-   (set_attr "type" "msklog")
-   (set_attr "prefix" "vex")])
+  [(set_attr "type" "msklog")
+   (set_attr "prefix" "vex")
+   (set (attr "mode")
+     (cond [(and (match_test "<MODE>mode == QImode")
+		 (not (match_test "TARGET_AVX512DQ")))
+	       (const_string "HI")
+	   ]
+	   (const_string "<MODE>")))])
 
 ;; %%% This used to optimize known byte-wide and operations to memory,
 ;; and sometimes to QImode registers.  If this is considered useful,
@@ -8278,14 +8305,22 @@
     case 2:
       return "and{l}\t{%k2, %k0|%k0, %k2}";
     case 3:
-      return TARGET_AVX512DQ ? "kandb\t{%2, %1, %0|%0, %1, %2}"
-			     : "kandw\t{%2, %1, %0|%0, %1, %2}";
+      if (get_attr_mode (insn) == MODE_HI)
+	return "kandw\t{%2, %1, %0|%0, %1, %2}";
+      else
+	return "kandb\t{%2, %1, %0|%0, %1, %2}";
     default:
       gcc_unreachable ();
     }
 }
   [(set_attr "type" "alu,alu,alu,msklog")
-   (set_attr "mode" "QI,QI,SI,HI")
+   (set (attr "mode")
+      (cond [(eq_attr "alternative" "2")
+	       (const_string "SI")
+	     (and (eq_attr "alternative" "3")
+		  (not (match_test "TARGET_AVX512DQ")))
+	       (const_string "HI")]
+	    (const_string "QI")))
    ;; Potential partial reg stall on alternative 2.
    (set (attr "preferred_for_speed")
      (cond [(eq_attr "alternative" "2")
@@ -8319,10 +8354,10 @@
     case 1:
       return "#";
     case 2:
-      if (TARGET_AVX512DQ && <MODE>mode == QImode)
-	return "kandnb\t{%2, %1, %0|%0, %1, %2}";
+      if (get_attr_mode (insn) == MODE_HI)
+	return "kandnw\t{%2, %1, %0|%0, %1, %2}";
       else
-	return "kandnw\t{%2, %1, %0|%0, %1, %2}";
+	return "kandn<mskmodesuffix>\t{%2, %1, %0|%0, %1, %2}";
     default:
       gcc_unreachable ();
     }
@@ -8331,7 +8366,13 @@
    (set_attr "type" "bitmanip,*,msklog")
    (set_attr "prefix" "*,*,vex")
    (set_attr "btver2_decode" "direct,*,*")
-   (set_attr "mode" "<MODE>")])
+   (set (attr "mode")
+     (cond [(and (eq_attr "alternative" "2")
+		 (and (match_test "<MODE>mode == QImode")
+		      (not (match_test "TARGET_AVX512DQ"))))
+	       (const_string "HI")
+	   ]
+	   (const_string "<MODE>")))])
 
 (define_split
   [(set (match_operand:SWI12 0 "general_reg_operand")
@@ -8843,37 +8884,32 @@
    (set_attr "mode" "<MODE>")])
 
 (define_insn "kxnor<mode>"
-  [(set (match_operand:SWI12 0 "register_operand" "=r,!k")
-	(not:SWI12
-	  (xor:SWI12
-	    (match_operand:SWI12 1 "register_operand" "0,k")
-	    (match_operand:SWI12 2 "register_operand" "r,k"))))
+  [(set (match_operand:SWI1248_AVX512BW 0 "register_operand" "=r,!k")
+	(not:SWI1248_AVX512BW
+	  (xor:SWI1248_AVX512BW
+	    (match_operand:SWI1248_AVX512BW 1 "register_operand" "0,k")
+	    (match_operand:SWI1248_AVX512BW 2 "register_operand" "r,k"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_AVX512F"
 {
-  if (which_alternative == 1 && <MODE>mode == QImode && TARGET_AVX512DQ)
-    return "kxnorb\t{%2, %1, %0|%0, %1, %2}";
-  return "kxnorw\t{%2, %1, %0|%0, %1, %2}";
+  if (which_alternative == 0)
+    return "#";
+
+  if (get_attr_mode (insn) == MODE_HI)
+    return "kxnorw\t{%2, %1, %0|%0, %1, %2}";
+  else
+    return "kxnor<mskmodesuffix>\t{%2, %1, %0|%0, %1, %2}";
 }
   [(set_attr "type" "*,msklog")
    (set_attr "prefix" "*,vex")
-   (set_attr "mode" "<MODE>")])
+   (set (attr "mode")
+     (cond [(and (eq_attr "alternative" "1")
+		 (and (match_test "<MODE>mode == QImode")
+		      (not (match_test "TARGET_AVX512DQ"))))
+	      (const_string "HI")
+	   ]
+	   (const_string "<MODE>")))])
 
-(define_insn "kxnor<mode>"
-  [(set (match_operand:SWI48x 0 "register_operand" "=r,!k")
-	(not:SWI48x
-	  (xor:SWI48x
-	    (match_operand:SWI48x 1 "register_operand" "0,k")
-	    (match_operand:SWI48x 2 "register_operand" "r,k"))))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_AVX512BW"
-  "@
-   #
-   kxnor<mskmodesuffix>\t{%2, %1, %0|%0, %1, %2}"
-  [(set_attr "type" "*,msklog")
-   (set_attr "prefix" "*,vex")
-   (set_attr "mode" "<MODE>")])
-
 (define_split
   [(set (match_operand:SWI1248x 0 "general_reg_operand")
 	(not:SWI1248x
@@ -9583,9 +9619,10 @@
     case 1:
       return "not{l}\t%k0";
     case 2:
-      if (TARGET_AVX512DQ)
+      if (get_attr_mode (insn) == MODE_HI)
+	return "knotw\t{%1, %0|%0, %1}";
+      else
 	return "knotb\t{%1, %0|%0, %1}";
-      return "knotw\t{%1, %0|%0, %1}";
     default:
       gcc_unreachable ();
     }
@@ -9593,7 +9630,13 @@
   [(set_attr "isa" "*,*,avx512f")
    (set_attr "type" "negnot,negnot,msklog")
    (set_attr "prefix" "*,*,vex")
-   (set_attr "mode" "QI,SI,QI")
+   (set (attr "mode")
+      (cond [(eq_attr "alternative" "1")
+	       (const_string "SI")
+	     (and (eq_attr "alternative" "2")
+		  (not (match_test "TARGET_AVX512DQ")))
+	       (const_string "HI")]
+	    (const_string "QI")))
    ;; Potential partial reg stall on alternative 1.
    (set (attr "preferred_for_speed")
      (cond [(eq_attr "alternative" "1")
