diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c
index d7077980f9b..d81dd73f034 100644
--- a/gcc/config/i386/i386-expand.c
+++ b/gcc/config/i386/i386-expand.c
@@ -1179,9 +1179,8 @@ ix86_split_idivmod (machine_mode mode, rtx operands[],
   JUMP_LABEL (insn) = qimode_label;
 
   /* Generate original signed/unsigned divimod.  */
-  div = gen_divmod4_1 (operands[0], operands[1],
-		       operands[2], operands[3]);
-  emit_insn (div);
+  emit_insn (gen_divmod4_1 (operands[0], operands[1],
+			    operands[2], operands[3]));
 
   /* Branch to the end.  */
   emit_jump_insn (gen_jump (end_label));
@@ -1215,18 +1214,10 @@ ix86_split_idivmod (machine_mode mode, rtx operands[],
     }
 
   /* Extract remainder from AH.  */
-  tmp1 = gen_rtx_ZERO_EXTRACT (GET_MODE (operands[1]),
-			       tmp0, GEN_INT (8), GEN_INT (8));
-  if (REG_P (operands[1]))
-    insn = emit_move_insn (operands[1], tmp1);
-  else
-    {
-      /* Need a new scratch register since the old one has result
-	 of 8bit divide.  */
-      scratch = gen_reg_rtx (GET_MODE (operands[1]));
-      emit_move_insn (scratch, tmp1);
-      insn = emit_move_insn (operands[1], scratch);
-    }
+  scratch = gen_lowpart (GET_MODE (operands[1]), scratch);
+  tmp1 = gen_rtx_ZERO_EXTRACT (GET_MODE (operands[1]), scratch,
+			       GEN_INT (8), GEN_INT (8));
+  insn = emit_move_insn (operands[1], tmp1);
   set_unique_reg_note (insn, REG_EQUAL, mod);
 
   /* Zero extend quotient from AL.  */
@@ -7060,10 +7051,7 @@ promote_duplicated_reg (machine_mode mode, rtx val)
       rtx reg = convert_modes (mode, QImode, val, true);
 
       if (!TARGET_PARTIAL_REG_STALL)
-	if (mode == SImode)
-	  emit_insn (gen_insvsi_1 (reg, reg));
-	else
-	  emit_insn (gen_insvdi_1 (reg, reg));
+	emit_insn (gen_insv_1 (mode, reg, reg));
       else
 	{
 	  tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (8),
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 4d455584f09..d0ecd9eb6cf 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1355,13 +1355,13 @@
   [(set_attr "type" "icmp")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "*cmpqi_ext_1"
+(define_insn "*cmpqi_ext<mode>_1"
   [(set (reg FLAGS_REG)
 	(compare
 	  (match_operand:QI 0 "nonimmediate_operand" "QBc,m")
 	  (subreg:QI
-	    (zero_extract:SI
-	      (match_operand 1 "ext_register_operand" "Q,Q")
+	    (zero_extract:SWI248
+	      (match_operand:SWI248 1 "register_operand" "Q,Q")
 	      (const_int 8)
 	      (const_int 8)) 0)))]
   "ix86_match_ccmode (insn, CCmode)"
@@ -1370,12 +1370,12 @@
    (set_attr "type" "icmp")
    (set_attr "mode" "QI")])
 
-(define_insn "*cmpqi_ext_2"
+(define_insn "*cmpqi_ext<mode>_2"
   [(set (reg FLAGS_REG)
 	(compare
 	  (subreg:QI
-	    (zero_extract:SI
-	      (match_operand 0 "ext_register_operand" "Q")
+	    (zero_extract:SWI248
+	      (match_operand:SWI248 0 "register_operand" "Q")
 	      (const_int 8)
 	      (const_int 8)) 0)
 	  (match_operand:QI 1 "const0_operand")))]
@@ -1389,18 +1389,18 @@
   [(set (reg:CC FLAGS_REG)
 	(compare:CC
 	  (subreg:QI
-	    (zero_extract:SI
-	      (match_operand 0 "ext_register_operand")
+	    (zero_extract:HI
+	      (match_operand:HI 0 "register_operand")
 	      (const_int 8)
 	      (const_int 8)) 0)
 	  (match_operand:QI 1 "const_int_operand")))])
 
-(define_insn "*cmpqi_ext_3"
+(define_insn "*cmpqi_ext<mode>_3"
   [(set (reg FLAGS_REG)
 	(compare
 	  (subreg:QI
-	    (zero_extract:SI
-	      (match_operand 0 "ext_register_operand" "Q,Q")
+	    (zero_extract:SWI248
+	      (match_operand:SWI248 0 "register_operand" "Q,Q")
 	      (const_int 8)
 	      (const_int 8)) 0)
 	  (match_operand:QI 1 "general_operand" "QnBc,m")))]
@@ -1410,17 +1410,17 @@
    (set_attr "type" "icmp")
    (set_attr "mode" "QI")])
 
-(define_insn "*cmpqi_ext_4"
+(define_insn "*cmpqi_ext<mode>_4"
   [(set (reg FLAGS_REG)
 	(compare
 	  (subreg:QI
-	    (zero_extract:SI
-	      (match_operand 0 "ext_register_operand" "Q")
+	    (zero_extract:SWI248
+	      (match_operand:SWI248 0 "register_operand" "Q")
 	      (const_int 8)
 	      (const_int 8)) 0)
 	  (subreg:QI
-	    (zero_extract:SI
-	      (match_operand 1 "ext_register_operand" "Q")
+	    (zero_extract:SWI248
+	      (match_operand:SWI248 1 "register_operand" "Q")
 	      (const_int 8)
 	      (const_int 8)) 0)))]
   "ix86_match_ccmode (insn, CCmode)"
@@ -2775,7 +2775,7 @@
 
 (define_insn "*extv<mode>"
   [(set (match_operand:SWI24 0 "register_operand" "=R")
-	(sign_extract:SWI24 (match_operand 1 "ext_register_operand" "Q")
+	(sign_extract:SWI24 (match_operand:SWI24 1 "register_operand" "Q")
 			    (const_int 8)
 			    (const_int 8)))]
   ""
@@ -2807,9 +2807,10 @@
 (define_insn "*extzvqi_mem_rex64"
   [(set (match_operand:QI 0 "norex_memory_operand" "=Bn")
 	(subreg:QI
-	  (zero_extract:SI (match_operand 1 "ext_register_operand" "Q")
-			   (const_int 8)
-			   (const_int 8)) 0))]
+	  (zero_extract:SWI248
+	    (match_operand:SWI248 1 "register_operand" "Q")
+	    (const_int 8)
+	    (const_int 8)) 0))]
   "TARGET_64BIT && reload_completed"
   "mov{b}\t{%h1, %0|%0, %h1}"
   [(set_attr "type" "imov")
@@ -2817,7 +2818,7 @@
 
 (define_insn "*extzv<mode>"
   [(set (match_operand:SWI248 0 "register_operand" "=R")
-	(zero_extract:SWI248 (match_operand 1 "ext_register_operand" "Q")
+	(zero_extract:SWI248 (match_operand:SWI248 1 "register_operand" "Q")
 			     (const_int 8)
 			     (const_int 8)))]
   ""
@@ -2828,9 +2829,10 @@
 (define_insn "*extzvqi"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=QBc,?R,m")
 	(subreg:QI
-	  (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q,Q")
-			   (const_int 8)
-			   (const_int 8)) 0))]
+	  (zero_extract:SWI248
+	    (match_operand:SWI248 1 "register_operand" "Q,Q,Q")
+	    (const_int 8)
+	    (const_int 8)) 0))]
   ""
 {
   switch (get_attr_type (insn))
@@ -2856,17 +2858,17 @@
 (define_peephole2
   [(set (match_operand:QI 0 "register_operand")
 	(subreg:QI
-	  (zero_extract:SI (match_operand 1 "ext_register_operand")
-			   (const_int 8)
-			   (const_int 8)) 0))
+	  (zero_extract:SWI248 (match_operand:SWI248 1 "register_operand")
+			       (const_int 8)
+			       (const_int 8)) 0))
    (set (match_operand:QI 2 "norex_memory_operand") (match_dup 0))]
   "TARGET_64BIT
    && peep2_reg_dead_p (2, operands[0])"
   [(set (match_dup 2)
 	(subreg:QI
-	  (zero_extract:SI (match_dup 1)
-			   (const_int 8)
-			   (const_int 8)) 0))])
+	  (zero_extract:SWI248 (match_dup 1)
+			       (const_int 8)
+			       (const_int 8)) 0))])
 
 (define_expand "insv<mode>"
   [(set (zero_extract:SWI248 (match_operand:SWI248 0 "register_operand")
@@ -2892,7 +2894,7 @@
   else
     dst = operands[0];
 
-  emit_insn (gen_insv<mode>_1 (dst, operands[3]));
+  emit_insn (gen_insv_1 (<MODE>mode, dst, operands[3]));
 
   /* Fix up the destination if needed.  */
   if (dst != operands[0])
@@ -2902,20 +2904,22 @@
 })
 
 (define_insn "*insvqi_1_mem_rex64"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
-			 (const_int 8)
-			 (const_int 8))
-	(subreg:SI
+  [(set (zero_extract:SWI248
+	  (match_operand:SWI248 0 "register_operand" "+Q")
+	  (const_int 8)
+	  (const_int 8))
+	(subreg:SWI248
 	  (match_operand:QI 1 "norex_memory_operand" "Bn") 0))]
   "TARGET_64BIT && reload_completed"
   "mov{b}\t{%1, %h0|%h0, %1}"
   [(set_attr "type" "imov")
    (set_attr "mode" "QI")])
 
-(define_insn "insv<mode>_1"
-  [(set (zero_extract:SWI248 (match_operand 0 "ext_register_operand" "+Q,Q")
-			     (const_int 8)
-			     (const_int 8))
+(define_insn "@insv<mode>_1"
+  [(set (zero_extract:SWI248
+	  (match_operand:SWI248 0 "register_operand" "+Q,Q")
+	  (const_int 8)
+	  (const_int 8))
 	(match_operand:SWI248 1 "general_operand" "QnBc,m"))]
   ""
 {
@@ -2928,10 +2932,11 @@
    (set_attr "mode" "QI")])
 
 (define_insn "*insvqi_1"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q,Q")
-			 (const_int 8)
-			 (const_int 8))
-	(subreg:SI
+  [(set (zero_extract:SWI248
+	  (match_operand:SWI248 0 "register_operand" "+Q,Q")
+	  (const_int 8)
+	  (const_int 8))
+	(subreg:SWI248
 	  (match_operand:QI 1 "general_operand" "QnBc,m") 0))]
   ""
   "mov{b}\t{%1, %h0|%h0, %1}"
@@ -2942,37 +2947,41 @@
 (define_peephole2
   [(set (match_operand:QI 0 "register_operand")
 	(match_operand:QI 1 "norex_memory_operand"))
-   (set (zero_extract:SI (match_operand 2 "ext_register_operand")
-			 (const_int 8)
-			 (const_int 8))
-	(subreg:SI (match_dup 0) 0))]
+   (set (zero_extract:SWI248 (match_operand:SWI248 2 "register_operand")
+			     (const_int 8)
+			     (const_int 8))
+	(subreg:SWI248 (match_dup 0) 0))]
   "TARGET_64BIT
    && peep2_reg_dead_p (2, operands[0])"
-  [(set (zero_extract:SI (match_dup 2)
-			 (const_int 8)
-			 (const_int 8))
-	   (subreg:SI (match_dup 1) 0))])
+  [(set (zero_extract:SWI248 (match_dup 2)
+			     (const_int 8)
+			     (const_int 8))
+	   (subreg:SWI248 (match_dup 1) 0))])
 
 (define_code_iterator any_extract [sign_extract zero_extract])
 
 (define_insn "*insvqi_2"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
-			 (const_int 8)
-			 (const_int 8))
-	(any_extract:SI (match_operand 1 "ext_register_operand" "Q")
-			(const_int 8)
-			(const_int 8)))]
+  [(set (zero_extract:SWI248
+	  (match_operand:SWI248 0 "register_operand" "+Q")
+	  (const_int 8)
+	  (const_int 8))
+	(any_extract:SWI248
+	  (match_operand:SWI248 1 "register_operand" "Q")
+	  (const_int 8)
+	  (const_int 8)))]
   ""
   "mov{b}\t{%h1, %h0|%h0, %h1}"
   [(set_attr "type" "imov")
    (set_attr "mode" "QI")])
 
 (define_insn "*insvqi_3"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
-			 (const_int 8)
-			 (const_int 8))
-	(any_shiftrt:SI (match_operand:SI 1 "register_operand" "Q")
-			(const_int 8)))]
+  [(set (zero_extract:SWI248
+	  (match_operand:SWI248 0 "register_operand" "+Q")
+	  (const_int 8)
+	  (const_int 8))
+	(any_shiftrt:SWI248
+	  (match_operand:SWI248 1 "register_operand" "Q")
+	  (const_int 8)))]
   ""
   "mov{b}\t{%h1, %h0|%h0, %h1}"
   [(set_attr "type" "imov")
@@ -5835,16 +5844,32 @@
 	(const_string "*")))
    (set_attr "mode" "<MODE>")])
 
-(define_insn "addqi_ext_1"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q,Q")
-			 (const_int 8)
-			 (const_int 8))
-	(subreg:SI
+(define_expand "addqi_ext_1"
+  [(parallel
+     [(set (zero_extract:HI (match_operand:HI 0 "register_operand")
+			    (const_int 8)
+			    (const_int 8))
+	   (subreg:HI
+	     (plus:QI
+	       (subreg:QI
+		 (zero_extract:HI (match_operand:HI 1 "register_operand")
+				  (const_int 8)
+				  (const_int 8)) 0)
+	       (match_operand:QI 2 "const_int_operand")) 0))
+      (clobber (reg:CC FLAGS_REG))])])
+
+(define_insn "*addqi_ext<mode>_1"
+  [(set (zero_extract:SWI248
+	  (match_operand:SWI248 0 "register_operand" "+Q,Q")
+	  (const_int 8)
+	  (const_int 8))
+	(subreg:SWI248
 	  (plus:QI
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 1 "ext_register_operand" "0,0")
-			       (const_int 8)
-			       (const_int 8)) 0)
+	      (zero_extract:SWI248
+	        (match_operand:SWI248 1 "register_operand" "0,0")
+		(const_int 8)
+		(const_int 8)) 0)
 	    (match_operand:QI 2 "general_operand" "QnBc,m")) 0))
    (clobber (reg:CC FLAGS_REG))]
   "/* FIXME: without this LRA can't reload this pattern, see PR82524.  */
@@ -5872,20 +5897,23 @@
 	(const_string "alu")))
    (set_attr "mode" "QI")])
 
-(define_insn "*addqi_ext_2"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
-			 (const_int 8)
-			 (const_int 8))
-	(subreg:SI
+(define_insn "*addqi_ext<mode>_2"
+  [(set (zero_extract:SWI248
+	  (match_operand:SWI248 0 "register_operand" "+Q")
+	  (const_int 8)
+	  (const_int 8))
+	(subreg:SWI248
 	  (plus:QI
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 1 "ext_register_operand" "%0")
-			       (const_int 8)
-			       (const_int 8)) 0)
+	      (zero_extract:SWI248
+	        (match_operand:SWI248 1 "register_operand" "%0")
+		(const_int 8)
+		(const_int 8)) 0)
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
-			       (const_int 8)
-			       (const_int 8)) 0)) 0))
+	      (zero_extract:SWI248
+	        (match_operand:SWI248 2 "register_operand" "Q")
+		(const_int 8)
+		(const_int 8)) 0)) 0))
   (clobber (reg:CC FLAGS_REG))]
   "/* FIXME: without this LRA can't reload this pattern, see PR82524.  */
    rtx_equal_p (operands[0], operands[1])
@@ -8556,8 +8584,8 @@
   emit_insn (gen_divmodhiqi3 (tmp0, tmp1, operands[2]));
 
   /* Extract remainder from AH.  */
-  tmp1 = gen_rtx_ZERO_EXTRACT (SImode, tmp0, GEN_INT (8), GEN_INT (8));
-  tmp1 = lowpart_subreg (QImode, tmp1, SImode);
+  tmp1 = gen_rtx_ZERO_EXTRACT (HImode, tmp0, GEN_INT (8), GEN_INT (8));
+  tmp1 = lowpart_subreg (QImode, tmp1, HImode);
   rtx_insn *insn = emit_move_insn (operands[3], tmp1);
 
   mod = gen_rtx_MOD (QImode, operands[1], operands[2]);
@@ -8593,8 +8621,8 @@
   emit_insn (gen_udivmodhiqi3 (tmp0, tmp1, operands[2]));
 
   /* Extract remainder from AH.  */
-  tmp1 = gen_rtx_ZERO_EXTRACT (SImode, tmp0, GEN_INT (8), GEN_INT (8));
-  tmp1 = lowpart_subreg (QImode, tmp1, SImode);
+  tmp1 = gen_rtx_ZERO_EXTRACT (HImode, tmp0, GEN_INT (8), GEN_INT (8));
+  tmp1 = lowpart_subreg (QImode, tmp1, HImode);
   rtx_insn *insn = emit_move_insn (operands[3], tmp1);
 
   mod = gen_rtx_UMOD (QImode, operands[1], operands[2]);
@@ -8740,20 +8768,22 @@
 	(compare:CCNO
 	  (and:QI
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 0 "ext_register_operand")
-			       (const_int 8)
-			       (const_int 8)) 0)
-	      (match_operand 1 "const_int_operand"))
+	      (zero_extract:HI
+	        (match_operand:HI 0 "register_operand")
+		(const_int 8)
+		(const_int 8)) 0)
+	      (match_operand:QI 1 "const_int_operand"))
 	  (const_int 0)))])
 
-(define_insn "*testqi_ext_1"
+(define_insn "*testqi_ext<mode>_1"
   [(set (reg FLAGS_REG)
 	(compare
 	  (and:QI
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 0 "ext_register_operand" "Q,Q")
-			       (const_int 8)
-			       (const_int 8)) 0)
+	      (zero_extract:SWI248
+	        (match_operand:SWI248 0 "register_operand" "Q,Q")
+		(const_int 8)
+		(const_int 8)) 0)
 	    (match_operand:QI 1 "general_operand" "QnBc,m"))
 	  (const_int 0)))]
   "ix86_match_ccmode (insn, CCNOmode)"
@@ -8762,18 +8792,20 @@
    (set_attr "type" "test")
    (set_attr "mode" "QI")])
 
-(define_insn "*testqi_ext_2"
+(define_insn "*testqi_ext<mode>_2"
   [(set (reg FLAGS_REG)
 	(compare
 	  (and:QI
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 0 "ext_register_operand" "Q")
-			       (const_int 8)
-			       (const_int 8)) 0)
+	      (zero_extract:SWI248
+	        (match_operand:SWI248 0 "register_operand" "Q")
+		(const_int 8)
+		(const_int 8)) 0)
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 1 "ext_register_operand" "Q")
-			       (const_int 8)
-			       (const_int 8)) 0))
+	      (zero_extract:SWI248
+	        (match_operand:SWI248 1 "register_operand" "Q")
+		(const_int 8)
+		(const_int 8)) 0))
 	  (const_int 0)))]
   "ix86_match_ccmode (insn, CCNOmode)"
   "test{b}\t{%h1, %h0|%h0, %h1}"
@@ -9312,16 +9344,32 @@
   [(set_attr "type" "alu")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "andqi_ext_1"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q,Q")
-			 (const_int 8)
-			 (const_int 8))
-	(subreg:SI
+(define_expand "andqi_ext_1"
+  [(parallel
+     [(set (zero_extract:HI (match_operand:HI 0 "register_operand")
+			    (const_int 8)
+			    (const_int 8))
+	   (subreg:HI
+	     (and:QI
+	       (subreg:QI
+		 (zero_extract:HI (match_operand:HI 1 "register_operand")
+				  (const_int 8)
+				  (const_int 8)) 0)
+	       (match_operand:QI 2 "const_int_operand")) 0))
+      (clobber (reg:CC FLAGS_REG))])])
+
+(define_insn "*andqi_ext<mode>_1"
+  [(set (zero_extract:SWI248
+	  (match_operand:SWI248 0 "register_operand" "+Q,Q")
+	  (const_int 8)
+	  (const_int 8))
+	(subreg:SWI248
 	  (and:QI
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 1 "ext_register_operand" "0,0")
-			       (const_int 8)
-			       (const_int 8)) 0)
+	      (zero_extract:SWI248
+	        (match_operand:SWI248 1 "register_operand" "0,0")
+		(const_int 8)
+		(const_int 8)) 0)
 	    (match_operand:QI 2 "general_operand" "QnBc,m")) 0))
    (clobber (reg:CC FLAGS_REG))]
   "/* FIXME: without this LRA can't reload this pattern, see PR82524.  */
@@ -9333,25 +9381,28 @@
 
 ;; Generated by peephole translating test to and.  This shows up
 ;; often in fp comparisons.
-(define_insn "*andqi_ext_1_cc"
+(define_insn "*andqi_ext<mode>_1_cc"
   [(set (reg FLAGS_REG)
 	(compare
 	  (and:QI
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 1 "ext_register_operand" "0,0")
-			       (const_int 8)
-			       (const_int 8)) 0)
+	      (zero_extract:SWI248
+	        (match_operand:SWI248 1 "register_operand" "0,0")
+		(const_int 8)
+		(const_int 8)) 0)
 	    (match_operand:QI 2 "general_operand" "QnBc,m"))
 	  (const_int 0)))
-   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q,Q")
-			 (const_int 8)
-			 (const_int 8))
-	(subreg:SI
+   (set (zero_extract:SWI248
+	  (match_operand:SWI248 0 "register_operand" "+Q,Q")
+	  (const_int 8)
+	  (const_int 8))
+	(subreg:SWI248
 	  (and:QI
 	    (subreg:QI
-	      (zero_extract:SI (match_dup 1)
-			       (const_int 8)
-			       (const_int 8)) 0)
+	      (zero_extract:SWI248
+	        (match_dup 1)
+		(const_int 8)
+		(const_int 8)) 0)
 	    (match_dup 2)) 0))]
   "ix86_match_ccmode (insn, CCNOmode)
    /* FIXME: without this LRA can't reload this pattern, see PR82524.  */
@@ -9361,20 +9412,23 @@
    (set_attr "type" "alu")
    (set_attr "mode" "QI")])
 
-(define_insn "*andqi_ext_2"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
-			 (const_int 8)
-			 (const_int 8))
-	(subreg:SI
+(define_insn "*andqi_ext<mode>_2"
+  [(set (zero_extract:SWI248
+	  (match_operand:SWI248 0 "register_operand" "+Q")
+	  (const_int 8)
+	  (const_int 8))
+	(subreg:SWI248
 	  (and:QI
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 1 "ext_register_operand" "%0")
-			       (const_int 8)
-			       (const_int 8)) 0)
+	      (zero_extract:SWI248
+	        (match_operand:SWI248 1 "register_operand" "%0")
+		(const_int 8)
+		(const_int 8)) 0)
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
-			       (const_int 8)
-			       (const_int 8)) 0)) 0))
+	      (zero_extract:SWI248
+	        (match_operand:SWI248 2 "register_operand" "Q")
+		(const_int 8)
+		(const_int 8)) 0)) 0))
    (clobber (reg:CC FLAGS_REG))]
   "/* FIXME: without this LRA can't reload this pattern, see PR82524.  */
    rtx_equal_p (operands[0], operands[1])
@@ -9743,16 +9797,18 @@
   [(set_attr "type" "alu")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "*<code>qi_ext_1"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q,Q")
-			 (const_int 8)
-			 (const_int 8))
-	(subreg:SI
+(define_insn "*<code>qi_ext<mode>_1"
+  [(set (zero_extract:SWI248
+	  (match_operand:SWI248 0 "register_operand" "+Q,Q")
+	  (const_int 8)
+	  (const_int 8))
+	(subreg:SWI248
 	  (any_or:QI
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 1 "ext_register_operand" "0,0")
-			       (const_int 8)
-			       (const_int 8)) 0)
+	      (zero_extract:SWI248
+	        (match_operand:SWI248 1 "register_operand" "0,0")
+		(const_int 8)
+		(const_int 8)) 0)
 	    (match_operand:QI 2 "general_operand" "QnBc,m")) 0))
    (clobber (reg:CC FLAGS_REG))]
   "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
@@ -9763,20 +9819,23 @@
    (set_attr "type" "alu")
    (set_attr "mode" "QI")])
 
-(define_insn "*<code>qi_ext_2"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
-			 (const_int 8)
-			 (const_int 8))
-	(subreg:SI
+(define_insn "*<code>qi_ext<mode>_2"
+  [(set (zero_extract:SWI248
+	  (match_operand:SWI248 0 "register_operand" "+Q")
+	  (const_int 8)
+	  (const_int 8))
+	(subreg:SWI248
 	  (any_or:QI
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 1 "ext_register_operand" "%0")
-			       (const_int 8)
-			       (const_int 8)) 0)
+	      (zero_extract:SWI248
+	        (match_operand:SWI248 1 "register_operand" "%0")
+		(const_int 8)
+		(const_int 8)) 0)
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
-			       (const_int 8)
-			       (const_int 8)) 0)) 0))
+	      (zero_extract:SWI248
+	        (match_operand:SWI248 2 "register_operand" "Q")
+		(const_int 8)
+		(const_int 8)) 0)) 0))
    (clobber (reg:CC FLAGS_REG))]
   "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
    /* FIXME: without this LRA can't reload this pattern, see PR82524.  */
@@ -9839,46 +9898,49 @@
 })
 
 (define_expand "xorqi_ext_1_cc"
-  [(parallel [
-     (set (reg:CCNO FLAGS_REG)
-	  (compare:CCNO
-	    (xor:QI
-	      (subreg:QI
-		(zero_extract:SI (match_operand 1 "ext_register_operand")
-				 (const_int 8)
-				 (const_int 8)) 0)
-	      (match_operand 2 "const_int_operand"))
-	    (const_int 0)))
-     (set (zero_extract:SI (match_operand 0 "ext_register_operand")
-			   (const_int 8)
-			   (const_int 8))
-	  (subreg:SI
-	    (xor:QI
-	      (subreg:QI
-		(zero_extract:SI (match_dup 1)
-				 (const_int 8)
-				 (const_int 8)) 0)
-	    (match_dup 2)) 0))])])
-
-(define_insn "*xorqi_ext_1_cc"
+  [(parallel
+     [(set (reg:CCNO FLAGS_REG)
+	   (compare:CCNO
+	     (xor:QI
+	       (subreg:QI
+		 (zero_extract:HI (match_operand:HI 1 "register_operand")
+				  (const_int 8)
+				  (const_int 8)) 0)
+	       (match_operand:QI 2 "const_int_operand"))
+	     (const_int 0)))
+      (set (zero_extract:HI (match_operand:HI 0 "register_operand")
+			    (const_int 8)
+			    (const_int 8))
+	   (subreg:HI
+	     (xor:QI
+	       (subreg:QI
+		 (zero_extract:HI (match_dup 1)
+				  (const_int 8)
+				  (const_int 8)) 0)
+	     (match_dup 2)) 0))])])
+
+(define_insn "*xorqi_ext<mode>_1_cc"
   [(set (reg FLAGS_REG)
 	(compare
 	  (xor:QI
 	    (subreg:QI
-	      (zero_extract:SI (match_operand 1 "ext_register_operand" "0,0")
-			       (const_int 8)
-			       (const_int 8)) 0)
+	      (zero_extract:SWI248
+	        (match_operand:SWI248 1 "register_operand" "0,0")
+		(const_int 8)
+		(const_int 8)) 0)
 	    (match_operand:QI 2 "general_operand" "QnBc,m"))
 	  (const_int 0)))
-   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q,Q")
-			 (const_int 8)
-			 (const_int 8))
-	(subreg:SI
+   (set (zero_extract:SWI248
+	  (match_operand:SWI248 0 "register_operand" "+Q,Q")
+	  (const_int 8)
+	  (const_int 8))
+	(subreg:SWI248
 	  (xor:QI
 	    (subreg:QI
-	      (zero_extract:SI (match_dup 1)
-			       (const_int 8)
-			       (const_int 8)) 0)
+	      (zero_extract:SWI248
+	        (match_dup 1)
+		(const_int 8)
+		(const_int 8)) 0)
 	  (match_dup 2)) 0))]
   "ix86_match_ccmode (insn, CCNOmode)
    /* FIXME: without this LRA can't reload this pattern, see PR82524.  */
@@ -19409,9 +19471,9 @@
 	(match_operator 1 "compare_operator"
 	  [(and:QI
 	     (subreg:QI
-	       (zero_extract:SI (match_operand 2 "QIreg_operand")
-				(const_int 8)
-				(const_int 8)) 0)
+	       (zero_extract:SWI248 (match_operand:SWI248 2 "QIreg_operand")
+				    (const_int 8)
+				    (const_int 8)) 0)
 	     (match_operand 3 "const_int_operand"))
 	   (const_int 0)]))]
   "! TARGET_PARTIAL_REG_STALL
@@ -19423,20 +19485,20 @@
 	   (match_op_dup 1
 	     [(and:QI
 		(subreg:QI
-		  (zero_extract:SI (match_dup 2)
-				   (const_int 8)
-				   (const_int 8)) 0)
+		  (zero_extract:SWI248 (match_dup 2)
+				       (const_int 8)
+				       (const_int 8)) 0)
 		(match_dup 3))
 	      (const_int 0)]))
-      (set (zero_extract:SI (match_dup 2)
-			    (const_int 8)
-			    (const_int 8))
-	   (subreg:SI
+      (set (zero_extract:SWI248 (match_dup 2)
+				(const_int 8)
+				(const_int 8))
+	   (subreg:SWI248
 	     (and:QI
 	       (subreg:QI
-		 (zero_extract:SI (match_dup 2)
-				  (const_int 8)
-				  (const_int 8)) 0)
+		 (zero_extract:SWI248 (match_dup 2)
+				      (const_int 8)
+				      (const_int 8)) 0)
 	       (match_dup 3)) 0))])])
 
 ;; Don't do logical operations with memory inputs.
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 8d8bcb1a765..07e69d555c0 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -87,14 +87,6 @@
   (and (match_code "reg")
        (match_test "REGNO (op) == FLAGS_REG")))
 
-;; Match a DI, SI or HImode register for a zero_extract.
-(define_special_predicate "ext_register_operand"
-  (and (match_operand 0 "register_operand")
-       (ior (and (match_test "TARGET_64BIT")
-		 (match_test "GET_MODE (op) == DImode"))
-	    (match_test "GET_MODE (op) == SImode")
-	    (match_test "GET_MODE (op) == HImode"))))
-
 ;; Match a DI, SI, HI or QImode nonimmediate_operand.
 (define_special_predicate "int_nonimmediate_operand"
   (and (match_operand 0 "nonimmediate_operand")
diff --git a/gcc/testsuite/gcc.target/i386/pr78904-1a.c b/gcc/testsuite/gcc.target/i386/pr78904-1a.c
new file mode 100644
index 00000000000..7746477d745
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78904-1a.c
@@ -0,0 +1,47 @@
+/* PR target/78904 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-final { scan-assembler-not "movzbl" } } */
+/* { dg-final { scan-assembler-not "movb" } } */
+
+struct S1
+{
+  unsigned char pad1;
+  unsigned char val;
+};
+
+struct S1 test_and (struct S1 a, struct S1 b)
+{
+  a.val &= b.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]andb" } } */
+
+struct S1 test_or (struct S1 a, struct S1 b)
+{
+  a.val |= b.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]orb" } } */
+
+struct S1 test_xor (struct S1 a, struct S1 b)
+{
+  a.val ^= b.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]xorb" } } */
+
+struct S1 test_add (struct S1 a, struct S1 b)
+{
+  a.val += b.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]addb" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr78904-1b.c b/gcc/testsuite/gcc.target/i386/pr78904-1b.c
new file mode 100644
index 00000000000..20b677252ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78904-1b.c
@@ -0,0 +1,49 @@
+/* PR target/78904 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-final { scan-assembler-not "movzbl" } } */
+/* { dg-final { scan-assembler-not "movb" } } */
+
+struct S1
+{
+  unsigned char pad1;
+  unsigned char val;
+  unsigned short pad2;
+  unsigned int pad3;
+};
+
+struct S1 test_and (struct S1 a, struct S1 b)
+{
+  a.val &= b.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]andb" } } */
+
+struct S1 test_or (struct S1 a, struct S1 b)
+{
+  a.val |= b.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]orb" } } */
+
+struct S1 test_xor (struct S1 a, struct S1 b)
+{
+  a.val ^= b.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]xorb" } } */
+
+struct S1 test_add (struct S1 a, struct S1 b)
+{
+  a.val += b.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]addb" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr78904-2a.c b/gcc/testsuite/gcc.target/i386/pr78904-2a.c
new file mode 100644
index 00000000000..41eaa259158
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78904-2a.c
@@ -0,0 +1,48 @@
+/* PR target/78904 */
+/* { dg-do compile } */
+/* { dg-require-effective-target nonpic } */
+/* { dg-options "-O2 -masm=att" } */
+
+struct S1
+{
+  unsigned char pad1;
+  unsigned char val;
+};
+
+extern struct S1 t;
+
+struct S1 test_and (struct S1 a)
+{
+  a.val &= t.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]andb\[ \t\]+t\[^\n\r]*, %.h" } } */
+
+struct S1 test_or (struct S1 a)
+{
+  a.val |= t.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]orb\[ \t\]+t\[^\n\r]*, %.h" } } */
+
+struct S1 test_xor (struct S1 a)
+{
+  a.val ^= t.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]xorb\[ \t\]+t\[^\n\r]*, %.h" } } */
+
+struct S1 test_add (struct S1 a)
+{
+  a.val += t.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]addb\[ \t\]+t\[^\n\r]*, %.h" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr78904-2b.c b/gcc/testsuite/gcc.target/i386/pr78904-2b.c
new file mode 100644
index 00000000000..23e975ac93e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78904-2b.c
@@ -0,0 +1,50 @@
+/* PR target/78904 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target nonpic } */
+/* { dg-options "-O2 -masm=att" } */
+
+struct S1
+{
+  unsigned char pad1;
+  unsigned char val;
+  unsigned short pad2;
+  unsigned int pad3;
+};
+
+extern struct S1 t;
+
+struct S1 test_and (struct S1 a)
+{
+  a.val &= t.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]andb\[ \t\]+t\[^\n\r]*, %.h" } } */
+
+struct S1 test_or (struct S1 a)
+{
+  a.val |= t.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]orb\[ \t\]+t\[^\n\r]*, %.h" } } */
+
+struct S1 test_xor (struct S1 a)
+{
+  a.val ^= t.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]xorb\[ \t\]+t\[^\n\r]*, %.h" } } */
+
+struct S1 test_add (struct S1 a)
+{
+  a.val += t.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]addb\[ \t\]+t\[^\n\r]*, %.h" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr78904-3a.c b/gcc/testsuite/gcc.target/i386/pr78904-3a.c
new file mode 100644
index 00000000000..2827b380b6c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78904-3a.c
@@ -0,0 +1,42 @@
+/* PR target/78904 */
+/* { dg-do assemble } */
+/* { dg-options "-O2" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+struct S1
+{
+  unsigned char pad1;
+  unsigned char val;
+  unsigned short pad2;
+};
+
+extern struct S1 t[256];
+
+struct S1 test_and (struct S1 a, size_t i)
+{
+  a.val &= t[i].val;
+
+  return a;
+}
+
+struct S1 test_or (struct S1 a, size_t i)
+{
+  a.val |= t[i].val;
+
+  return a;
+}
+
+struct S1 test_xor (struct S1 a, size_t i)
+{
+  a.val ^= t[i].val;
+
+  return a;
+}
+
+struct S1 test_add (struct S1 a, size_t i)
+{
+  a.val += t[i].val;
+
+  return a;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr78904-3b.c b/gcc/testsuite/gcc.target/i386/pr78904-3b.c
new file mode 100644
index 00000000000..0c73cbc2ec9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78904-3b.c
@@ -0,0 +1,43 @@
+/* PR target/78904 */
+/* { dg-do assemble { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+struct S1
+{
+  unsigned char pad1;
+  unsigned char val;
+  unsigned short pad2;
+  unsigned int pad3;
+};
+
+extern struct S1 t[256];
+
+struct S1 test_and (struct S1 a, size_t i)
+{
+  a.val &= t[i].val;
+
+  return a;
+}
+
+struct S1 test_or (struct S1 a, size_t i)
+{
+  a.val |= t[i].val;
+
+  return a;
+}
+
+struct S1 test_xor (struct S1 a, size_t i)
+{
+  a.val ^= t[i].val;
+
+  return a;
+}
+
+struct S1 test_add (struct S1 a, size_t i)
+{
+  a.val += t[i].val;
+
+  return a;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr78904-4a.c b/gcc/testsuite/gcc.target/i386/pr78904-4a.c
new file mode 100644
index 00000000000..5e6159a7648
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78904-4a.c
@@ -0,0 +1,21 @@
+/* PR target/78904 */
+/* { dg-do compile } */
+/* { dg-require-effective-target nonpic } */
+/* { dg-options "-O2 -masm=att" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+struct S1
+{
+  unsigned char pad1;
+  unsigned char val;
+};
+
+extern unsigned char t[256];
+
+void foo (struct S1 a, size_t i)
+{
+  t[i] = a.val;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]movb\[\t \]+%.h, t" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr78904-4b.c b/gcc/testsuite/gcc.target/i386/pr78904-4b.c
new file mode 100644
index 00000000000..ab7434f3de4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78904-4b.c
@@ -0,0 +1,23 @@
+/* PR target/78904 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target nonpic } */
+/* { dg-options "-O2 -masm=att" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+struct S1
+{
+  unsigned char pad1;
+  unsigned char val;
+  unsigned short pad2;
+  unsigned int pad3;
+};
+
+extern unsigned char t[256];
+
+void foo (struct S1 a, size_t i)
+{
+  t[i] = a.val;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]movb\[\t \]+%.h, t" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr78904-5a.c b/gcc/testsuite/gcc.target/i386/pr78904-5a.c
new file mode 100644
index 00000000000..d078d79b73a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78904-5a.c
@@ -0,0 +1,21 @@
+/* PR target/78904 */
+/* { dg-do assemble { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+struct S1
+{
+  unsigned char pad1;
+  unsigned char val;
+};
+
+extern unsigned char t[256];
+
+void foo (struct S1 a, size_t i)
+{
+  register size_t _i __asm ("r10") = i;
+
+  asm volatile ("" : "+r" (_i));
+  t[_i] = a.val;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr78904-5b.c b/gcc/testsuite/gcc.target/i386/pr78904-5b.c
new file mode 100644
index 00000000000..9490030d772
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78904-5b.c
@@ -0,0 +1,23 @@
+/* PR target/78904 */
+/* { dg-do assemble { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+struct S1
+{
+  unsigned char pad1;
+  unsigned char val;
+  unsigned short pad2;
+  unsigned int pad3;
+};
+
+extern unsigned char t[256];
+
+void foo (struct S1 a, size_t i)
+{
+  register size_t _i __asm ("r10") = i;
+
+  asm volatile ("" : "+r" (_i));
+  t[_i] = a.val;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr78904-6a.c b/gcc/testsuite/gcc.target/i386/pr78904-6a.c
new file mode 100644
index 00000000000..ab296a2e173
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78904-6a.c
@@ -0,0 +1,21 @@
+/* PR target/78904 */
+/* { dg-do compile } */
+/* { dg-require-effective-target nonpic } */
+/* { dg-options "-O2 -masm=att" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+struct S1
+{
+  char pad1;
+  char val;
+};
+
+extern char t[256];
+
+void foo (struct S1 a, size_t i)
+{
+  t[i] = a.val;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]movb\[\t \]*%.h, t" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr78904-6b.c b/gcc/testsuite/gcc.target/i386/pr78904-6b.c
new file mode 100644
index 00000000000..235bfe7d042
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78904-6b.c
@@ -0,0 +1,23 @@
+/* PR target/78904 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target nonpic } */
+/* { dg-options "-O2 -masm=att" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+struct S1
+{
+  char pad1;
+  char val;
+  short pad2;
+  int pad3;
+};
+
+extern char t[256];
+
+void foo (struct S1 a, size_t i)
+{
+  t[i] = a.val;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]movb\[\t \]*%.h, t" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr78967-1a.c b/gcc/testsuite/gcc.target/i386/pr78967-1a.c
new file mode 100644
index 00000000000..007c50646b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78967-1a.c
@@ -0,0 +1,20 @@
+/* PR target/78967 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-additional-options "-mregparm=3" { target ia32 } } */
+/* { dg-final { scan-assembler-not "movzbl" } } */
+
+struct S1
+{
+  unsigned char pad1;
+  unsigned char val;
+};
+
+struct S1 foo (struct S1 a, struct S1 b)
+{
+  a.val = b.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]movb\[ \t\]+%.h, %.h" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr78967-1b.c b/gcc/testsuite/gcc.target/i386/pr78967-1b.c
new file mode 100644
index 00000000000..7e7144379f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78967-1b.c
@@ -0,0 +1,21 @@
+/* PR target/78967 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-final { scan-assembler-not "movzbl" } } */
+
+struct S1
+{
+  unsigned char pad1;
+  unsigned char val;
+  unsigned short pad2;
+  unsigned int pad3;
+};
+
+struct S1 foo (struct S1 a, struct S1 b)
+{
+  a.val = b.val;
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]movb\[ \t\]+%.h, %.h" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr78967-2a.c b/gcc/testsuite/gcc.target/i386/pr78967-2a.c
new file mode 100644
index 00000000000..ce61cabf414
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78967-2a.c
@@ -0,0 +1,24 @@
+/* PR target/78967 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-require-effective-target nonpic } */
+/* { dg-final { scan-assembler-not "movzbl" } } */
+
+typedef __SIZE_TYPE__ size_t;
+
+struct S1
+{
+  unsigned char pad1;
+  unsigned char val;
+};
+
+extern unsigned char t[256];
+
+struct S1 foo (struct S1 a, size_t i)
+{
+  a.val = t[i];
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]movb\[ \t\]+t\[^\n\r]*, %.h" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr78967-2b.c b/gcc/testsuite/gcc.target/i386/pr78967-2b.c
new file mode 100644
index 00000000000..ce38ac4d0bf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78967-2b.c
@@ -0,0 +1,26 @@
+/* PR target/78967 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-require-effective-target nonpic } */
+/* { dg-final { scan-assembler-not "movzbl" } } */
+
+typedef __SIZE_TYPE__ size_t;
+
+struct S1
+{
+  unsigned char pad1;
+  unsigned char val;
+  unsigned short pad2;
+  unsigned int pad3;
+};
+
+extern unsigned char t[256];
+
+struct S1 foo (struct S1 a, size_t i)
+{
+  a.val = t[i];
+
+  return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]movb\[ \t\]+t\[^\n\r]*, %.h" } } */
