@@ -6641,6 +6641,22 @@ (define_insn "*add<mode>_5"
(const_string "*")))
(set_attr "mode" "<MODE>")])
+(define_insn "*addqi_ext<mode>_0"
+ [(set (match_operand:QI 0 "nonimm_x64constmem_operand" "=QBc,m")
+ (plus:QI
+ (subreg:QI
+ (zero_extract:SWI248
+ (match_operand 2 "int248_register_operand" "Q,Q")
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_operand:QI 1 "nonimm_x64constmem_operand" "0,0")))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "add{b}\t{%h2, %0|%0, %h2}"
+ [(set_attr "isa" "*,nox64")
+ (set_attr "type" "alu")
+ (set_attr "mode" "QI")])
+
(define_expand "addqi_ext_1"
[(parallel
[(set (zero_extract:HI (match_operand:HI 0 "register_operand")
@@ -7265,6 +7281,22 @@ (define_insn "*subsi_2_zext"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
+(define_insn "*subqi_ext<mode>_0"
+ [(set (match_operand:QI 0 "nonimm_x64constmem_operand" "=QBc,m")
+ (minus:QI
+ (match_operand:QI 1 "nonimm_x64constmem_operand" "0,0")
+ (subreg:QI
+ (zero_extract:SWI248
+ (match_operand 2 "int248_register_operand" "Q,Q")
+ (const_int 8)
+ (const_int 8)) 0)))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "sub{b}\t{%h2, %0|%0, %h2}"
+ [(set_attr "isa" "*,nox64")
+ (set_attr "type" "alu")
+ (set_attr "mode" "QI")])
+
(define_insn "*subqi_ext<mode>_2"
[(set (zero_extract:SWI248
(match_operand 0 "int248_register_operand" "+Q")
@@ -10528,6 +10560,22 @@ (define_insn "*and<mode>_2"
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
+(define_insn "*andqi_ext<mode>_0"
+ [(set (match_operand:QI 0 "nonimm_x64constmem_operand" "=QBc,m")
+ (and:QI
+ (subreg:QI
+ (zero_extract:SWI248
+ (match_operand 2 "int248_register_operand" "Q,Q")
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_operand:QI 1 "nonimm_x64constmem_operand" "0,0")))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "and{b}\t{%h2, %0|%0, %h2}"
+ [(set_attr "isa" "*,nox64")
+ (set_attr "type" "alu")
+ (set_attr "mode" "QI")])
+
(define_expand "andqi_ext_1"
[(parallel
[(set (zero_extract:HI (match_operand:HI 0 "register_operand")
@@ -11269,6 +11317,22 @@ (define_insn "*<code><mode>_3"
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
+(define_insn "*<code>qi_ext<mode>_0"
+ [(set (match_operand:QI 0 "nonimm_x64constmem_operand" "=QBc,m")
+ (any_or:QI
+ (subreg:QI
+ (zero_extract:SWI248
+ (match_operand 2 "int248_register_operand" "Q,Q")
+ (const_int 8)
+ (const_int 8)) 0)
+ (match_operand:QI 1 "nonimm_x64constmem_operand" "0,0")))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "<logic>{b}\t{%h2, %0|%0, %h2}"
+ [(set_attr "isa" "*,nox64")
+ (set_attr "type" "alu")
+ (set_attr "mode" "QI")])
+
(define_insn "*<code>qi_ext<mode>_1"
[(set (zero_extract:SWI248
(match_operand 0 "int248_register_operand" "+Q,Q")
@@ -109,6 +109,13 @@ (define_special_predicate "int_nonimmediate_operand"
(match_test "GET_MODE (op) == HImode")
(match_test "GET_MODE (op) == QImode"))))
+;; Match nonimmediate operand, but exclude non-constant addresses for x86_64.
+(define_predicate "nonimm_x64constmem_operand"
+ (ior (match_operand 0 "register_operand")
+ (and (match_operand 0 "memory_operand")
+ (ior (not (match_test "TARGET_64BIT"))
+ (match_test "constant_address_p (XEXP (op, 0))")))))
+
;; Match register operands, but include memory operands for TARGET_SSE_MATH.
(define_predicate "register_ssemem_operand"
(if_then_else
new file mode 100644
@@ -0,0 +1,63 @@
+/* PR target/108831 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-additional-options "-mregparm=3" { target ia32 } } */
+/* { dg-final { scan-assembler-not "movzbl" } } */
+/* { dg-final { scan-assembler-not "movb" } } */
+
+struct S
+{
+ unsigned char pad1;
+ unsigned char val;
+ unsigned short pad2;
+};
+
+unsigned char
+test_and (unsigned char a, struct S b)
+{
+ a &= b.val;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]andb" } } */
+
+unsigned char
+test_or (unsigned char a, struct S b)
+{
+ a |= b.val;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]orb" } } */
+
+unsigned char
+test_xor (unsigned char a, struct S b)
+{
+ a ^= b.val;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]xorb" } } */
+
+unsigned char
+test_add (unsigned char a, struct S b)
+{
+ a += b.val;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]addb" } } */
+
+unsigned char
+test_sub (unsigned char a, struct S b)
+{
+ a -= b.val;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]subb" } } */
new file mode 100644
@@ -0,0 +1,55 @@
+/* PR target/108831 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-additional-options "-mregparm=3" { target ia32 } } */
+/* { dg-final { scan-assembler-not "movzbl" } } */
+/* { dg-final { scan-assembler-not "movb" } } */
+
+struct S
+{
+ unsigned char pad1;
+ unsigned char val;
+ unsigned short pad2;
+};
+
+unsigned char a;
+
+void
+test_and (struct S b)
+{
+ a &= b.val;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]andb" } } */
+
+void
+test_or (struct S b)
+{
+ a |= b.val;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]orb" } } */
+
+void
+test_xor (struct S b)
+{
+ a ^= b.val;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]xorb" } } */
+
+void
+test_add (struct S b)
+{
+ a += b.val;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]addb" } } */
+
+void
+test_sub (struct S b)
+{
+ a -= b.val;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]subb" } } */