aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorUros Bizjak <ubizjak@gmail.com>2019-07-18 19:17:31 +0200
committerUros Bizjak <uros@gcc.gnu.org>2019-07-18 19:17:31 +0200
commit07d7662ff7ed987d98a61f333169b65620ec8202 (patch)
tree6249d46c573b8695de4b987c6c4c55f01b4e6de9 /gcc
parent36729568fbf96ea0d481344cf3ef559c74f59f95 (diff)
downloadgcc-07d7662ff7ed987d98a61f333169b65620ec8202.zip
gcc-07d7662ff7ed987d98a61f333169b65620ec8202.tar.gz
gcc-07d7662ff7ed987d98a61f333169b65620ec8202.tar.bz2
re PR target/91188 (strict_low_part operations do not work)
PR target/91188 * config/i386/i386.md (*addqi_1_slp): Use register_operand predicate for operand 0. Do not use (match_dup) to match operand 1 with operand 0. Add check in insn constraint that either input operand matches operand 0. Use SWI12 mode iterator to also handle HImode operands. (*and<mode>_1_slp): Ditto. (*<code>qi_1_slp): Ditto. (*sub<mode>_1_slp): Use register_operand predicate for operand 0. Do not use (match_dup) to match operand 1 with operand 0. Add check in insn constraint that operand 1 matches operand 0. Use SWI12 mode iterator to also handle HImode operands. (*ashl<mode>3_1_slp): Ditto. (*<shift_insn><mode>3_1_slp): Ditto. (*<rotate_insn><mode>3_1_slp): Ditto. testsuite/ChangeLog: PR target/91188 * gcc.target/i386/pr91188-1a.c: New test. * gcc.target/i386/pr91188-1b.c: Ditto. * gcc.target/i386/pr91188-1c.c: Ditto. * gcc.target/i386/pr91188-2a.c: Ditto. * gcc.target/i386/pr91188-2b.c: Ditto. * gcc.target/i386/pr91188-2c.c: Ditto. From-SVN: r273578
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/config/i386/i386.md194
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr91188-1a.c63
-rw-r--r--gcc/testsuite/gcc.target/i386/pr91188-1b.c65
-rw-r--r--gcc/testsuite/gcc.target/i386/pr91188-1c.c113
-rw-r--r--gcc/testsuite/gcc.target/i386/pr91188-2a.c62
-rw-r--r--gcc/testsuite/gcc.target/i386/pr91188-2b.c64
-rw-r--r--gcc/testsuite/gcc.target/i386/pr91188-2c.c112
9 files changed, 603 insertions, 98 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7055ca4..4a64253 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,21 @@
+2019-07-18 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/91188
+ * config/i386/i386.md (*addqi_1_slp): Use register_operand predicate
+ for operand 0. Do not use (match_dup) to match operand 1 with
+ operand 0. Add check in insn constraint that either input operand
+ matches operand 0. Use SWI12 mode iterator to also handle
+ HImode operands.
+ (*and<mode>_1_slp): Ditto.
+ (*<code>qi_1_slp): Ditto.
+ (*sub<mode>_1_slp): Use register_operand predicate for operand 0.
+ Do not use (match_dup) to match operand 1 with operand 0. Add
+ check in insn constraint that operand 1 matches operand 0.
+ Use SWI12 mode iterator to also handle HImode operands.
+ (*ashl<mode>3_1_slp): Ditto.
+ (*<shift_insn><mode>3_1_slp): Ditto.
+ (*<rotate_insn><mode>3_1_slp): Ditto.
+
2019-07-18 Sylvia Taylor <sylvia.taylor@arm.com>
* config/arm/arm-builtins.c
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 62485c3..4fc0300 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -5583,41 +5583,39 @@
(symbol_ref "!TARGET_PARTIAL_REG_STALL")]
(symbol_ref "true")))])
-(define_insn "*addqi_1_slp"
- [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
- (plus:QI (match_dup 0)
- (match_operand:QI 1 "general_operand" "qn,m")))
+(define_insn "*add<mode>_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
+ (plus:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0")
+ (match_operand:SWI12 2 "general_operand" "<r>mn")))
(clobber (reg:CC FLAGS_REG))]
- "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
+ /* FIXME: without this LRA can't reload this pattern, see PR82524. */
+ && (rtx_equal_p (operands[0], operands[1])
+ || rtx_equal_p (operands[0], operands[2]))"
{
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
- if (operands[1] == const1_rtx)
- return "inc{b}\t%0";
+ if (operands[2] == const1_rtx)
+ return "inc{<imodesuffix>}\t%0";
else
{
- gcc_assert (operands[1] == constm1_rtx);
- return "dec{b}\t%0";
+ gcc_assert (operands[2] == constm1_rtx);
+ return "dec{<imodesuffix>}\t%0";
}
default:
- if (x86_maybe_negate_const_int (&operands[1], QImode))
- return "sub{b}\t{%1, %0|%0, %1}";
+ if (x86_maybe_negate_const_int (&operands[2], QImode))
+ return "sub{<imodesuffix>}\t{%2, %0|%0, %2}";
- return "add{b}\t{%1, %0|%0, %1}";
+ return "add{<imodesuffix>}\t{%2, %0|%0, %2}";
}
}
[(set (attr "type")
- (if_then_else (match_operand:QI 1 "incdec_operand")
+ (if_then_else (match_operand:QI 2 "incdec_operand")
(const_string "incdec")
- (const_string "alu1")))
- (set (attr "memory")
- (if_then_else (match_operand 1 "memory_operand")
- (const_string "load")
- (const_string "none")))
- (set_attr "mode" "QI")])
+ (const_string "alu")))
+ (set_attr "mode" "<MODE>")])
;; Split non destructive adds if we cannot use lea.
(define_split
@@ -6345,16 +6343,17 @@
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
-(define_insn "*subqi_1_slp"
- [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
- (minus:QI (match_dup 0)
- (match_operand:QI 1 "general_operand" "qn,m")))
+(define_insn "*sub<mode>_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
+ (minus:SWI12 (match_operand:SWI12 1 "register_operand" "0")
+ (match_operand:SWI12 2 "general_operand" "<r>mn")))
(clobber (reg:CC FLAGS_REG))]
- "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
- "sub{b}\t{%1, %0|%0, %1}"
- [(set_attr "type" "alu1")
- (set_attr "mode" "QI")])
+ "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
+ /* FIXME: without this LRA can't reload this pattern, see PR82524. */
+ && rtx_equal_p (operands[0], operands[1])"
+ "sub{<imodesuffix>}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "mode" "<MODE>")])
(define_insn "*sub<mode>_2"
[(set (reg FLAGS_REG)
@@ -8548,16 +8547,18 @@
(symbol_ref "!TARGET_PARTIAL_REG_STALL")]
(symbol_ref "true")))])
-(define_insn "*andqi_1_slp"
- [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
- (and:QI (match_dup 0)
- (match_operand:QI 1 "general_operand" "qn,m")))
+(define_insn "*and<mode>_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
+ (and:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0")
+ (match_operand:SWI12 2 "general_operand" "<r>mn")))
(clobber (reg:CC FLAGS_REG))]
"(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
- "and{b}\t{%1, %0|%0, %1}"
- [(set_attr "type" "alu1")
- (set_attr "mode" "QI")])
+ /* FIXME: without this LRA can't reload this pattern, see PR82524. */
+ && (rtx_equal_p (operands[0], operands[1])
+ || rtx_equal_p (operands[0], operands[2]))"
+ "and{<imodesuffix>}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "mode" "<MODE>")])
(define_split
[(set (match_operand:SWI248 0 "register_operand")
@@ -9098,16 +9099,18 @@
(symbol_ref "!TARGET_PARTIAL_REG_STALL")]
(symbol_ref "true")))])
-(define_insn "*<code>qi_1_slp"
- [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
- (any_or:QI (match_dup 0)
- (match_operand:QI 1 "general_operand" "qn,m")))
+(define_insn "*<code><mode>_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
+ (any_or:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0")
+ (match_operand:SWI12 2 "general_operand" "<r>mn")))
(clobber (reg:CC FLAGS_REG))]
"(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
- "<logic>{b}\t{%1, %0|%0, %1}"
- [(set_attr "type" "alu1")
- (set_attr "mode" "QI")])
+ /* FIXME: without this LRA can't reload this pattern, see PR82524. */
+ && (rtx_equal_p (operands[0], operands[1])
+ || rtx_equal_p (operands[0], operands[2]))"
+ "<logic>{<imodesuffix>}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "mode" "<MODE>")])
(define_insn "*<code><mode>_2"
[(set (reg FLAGS_REG)
@@ -9162,7 +9165,7 @@
"(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
&& ix86_match_ccmode (insn, CCNOmode)
&& !(MEM_P (operands[0]) && MEM_P (operands[1]))"
- "<logic>{b}\t{%1, %0|%0, %1}"
+ "<logic>{<imodesuffix>}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu1")
(set_attr "mode" "QI")])
@@ -10318,48 +10321,45 @@
(symbol_ref "!TARGET_PARTIAL_REG_STALL")]
(symbol_ref "true")))])
-(define_insn "*ashlqi3_1_slp"
- [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
- (ashift:QI (match_dup 0)
- (match_operand:QI 1 "nonmemory_operand" "cI")))
+(define_insn "*ashl<mode>3_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
+ (ashift:SWI12 (match_operand:SWI12 1 "register_operand" "0")
+ (match_operand:QI 2 "nonmemory_operand" "cI")))
(clobber (reg:CC FLAGS_REG))]
- "(optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_FLAG_REG_STALL
- || (operands[1] == const1_rtx
- && (TARGET_SHIFT1
- || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))"
+ "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
+ /* FIXME: without this LRA can't reload this pattern, see PR82524. */
+ && rtx_equal_p (operands[0], operands[1])"
{
switch (get_attr_type (insn))
{
- case TYPE_ALU1:
- gcc_assert (operands[1] == const1_rtx);
- return "add{b}\t%0, %0";
+ case TYPE_ALU:
+ gcc_assert (operands[2] == const1_rtx);
+ return "add{<imodesuffix>}\t%0, %0";
default:
- if (operands[1] == const1_rtx
+ if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "sal{b}\t%0";
+ return "sal{<imodesuffix>}\t%0";
else
- return "sal{b}\t{%1, %0|%0, %1}";
+ return "sal{<imodesuffix>}\t{%2, %0|%0, %2}";
}
}
[(set (attr "type")
- (cond [(and (and (match_test "TARGET_DOUBLE_WITH_ADD")
- (match_operand 0 "register_operand"))
- (match_operand 1 "const1_operand"))
- (const_string "alu1")
+ (cond [(and (match_test "TARGET_DOUBLE_WITH_ADD")
+ (match_operand 2 "const1_operand"))
+ (const_string "alu")
]
- (const_string "ishift1")))
+ (const_string "ishift")))
(set (attr "length_immediate")
(if_then_else
- (ior (eq_attr "type" "alu1")
- (and (eq_attr "type" "ishift1")
- (and (match_operand 1 "const1_operand")
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand")
(ior (match_test "TARGET_SHIFT1")
(match_test "optimize_function_for_size_p (cfun)")))))
(const_string "0")
(const_string "*")))
- (set_attr "mode" "QI")])
+ (set_attr "mode" "<MODE>")])
;; Convert ashift to the lea pattern to avoid flags dependency.
(define_split
@@ -10937,31 +10937,30 @@
(const_string "*")))
(set_attr "mode" "<MODE>")])
-(define_insn "*<shift_insn>qi3_1_slp"
- [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
- (any_shiftrt:QI (match_dup 0)
- (match_operand:QI 1 "nonmemory_operand" "cI")))
+(define_insn "*<shift_insn><mode>3_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
+ (any_shiftrt:SWI12 (match_operand:SWI12 1 "register_operand" "0")
+ (match_operand:QI 2 "nonmemory_operand" "cI")))
(clobber (reg:CC FLAGS_REG))]
- "(optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_REG_STALL
- || (operands[1] == const1_rtx
- && TARGET_SHIFT1))"
+ "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
+ /* FIXME: without this LRA can't reload this pattern, see PR82524. */
+ && rtx_equal_p (operands[0], operands[1])"
{
- if (operands[1] == const1_rtx
+ if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "<shift>{b}\t%0";
+ return "<shift>{<imodesuffix>}\t%0";
else
- return "<shift>{b}\t{%1, %0|%0, %1}";
+ return "<shift>{<imodesuffix>}\t{%2, %0|%0, %2}";
}
- [(set_attr "type" "ishift1")
+ [(set_attr "type" "ishift")
(set (attr "length_immediate")
(if_then_else
- (and (match_operand 1 "const1_operand")
+ (and (match_operand 2 "const1_operand")
(ior (match_test "TARGET_SHIFT1")
(match_test "optimize_function_for_size_p (cfun)")))
(const_string "0")
(const_string "*")))
- (set_attr "mode" "QI")])
+ (set_attr "mode" "<MODE>")])
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
@@ -11366,31 +11365,30 @@
(const_string "*")))
(set_attr "mode" "<MODE>")])
-(define_insn "*<rotate_insn>qi3_1_slp"
- [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
- (any_rotate:QI (match_dup 0)
- (match_operand:QI 1 "nonmemory_operand" "cI")))
+(define_insn "*<rotate_insn><mode>3_1_slp"
+ [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
+ (any_rotate:SWI12 (match_operand:SWI12 1 "register_operand" "0")
+ (match_operand:QI 2 "nonmemory_operand" "cI")))
(clobber (reg:CC FLAGS_REG))]
- "(optimize_function_for_size_p (cfun)
- || !TARGET_PARTIAL_REG_STALL
- || (operands[1] == const1_rtx
- && TARGET_SHIFT1))"
+ "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
+ /* FIXME: without this LRA can't reload this pattern, see PR82524. */
+ && rtx_equal_p (operands[0], operands[1])"
{
- if (operands[1] == const1_rtx
+ if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "<rotate>{b}\t%0";
+ return "<rotate>{<imodesuffix>}\t%0";
else
- return "<rotate>{b}\t{%1, %0|%0, %1}";
+ return "<rotate>{<imodesuffix>}\t{%2, %0|%0, %2}";
}
- [(set_attr "type" "rotate1")
+ [(set_attr "type" "rotate")
(set (attr "length_immediate")
(if_then_else
- (and (match_operand 1 "const1_operand")
+ (and (match_operand 2 "const1_operand")
(ior (match_test "TARGET_SHIFT1")
(match_test "optimize_function_for_size_p (cfun)")))
(const_string "0")
(const_string "*")))
- (set_attr "mode" "QI")])
+ (set_attr "mode" "<MODE>")])
(define_split
[(set (match_operand:HI 0 "QIreg_operand")
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7bf322f..7eb95f7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2019-07-18 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/91188
+ * gcc.target/i386/pr91188-1a.c: New test.
+ * gcc.target/i386/pr91188-1b.c: Ditto.
+ * gcc.target/i386/pr91188-1c.c: Ditto.
+ * gcc.target/i386/pr91188-2a.c: Ditto.
+ * gcc.target/i386/pr91188-2b.c: Ditto.
+ * gcc.target/i386/pr91188-2c.c: Ditto.
+
2019-07-18 Sylvia Taylor <sylvia.taylor@arm.com>
PR target/90317
diff --git a/gcc/testsuite/gcc.target/i386/pr91188-1a.c b/gcc/testsuite/gcc.target/i386/pr91188-1a.c
new file mode 100644
index 0000000..8673c2a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr91188-1a.c
@@ -0,0 +1,63 @@
+/* PR target/91188 */
+/* { 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 val;
+ unsigned char pad1;
+ unsigned short pad2;
+};
+
+struct S
+test_and (struct S a, unsigned char b)
+{
+ a.val &= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]andb" } } */
+
+struct S
+test_or (struct S a, unsigned char b)
+{
+ a.val |= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]orb" } } */
+
+struct S
+test_xor (struct S a, unsigned char b)
+{
+ a.val ^= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]xorb" } } */
+
+struct S
+test_add (struct S a, unsigned char b)
+{
+ a.val += b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]addb" } } */
+
+struct S
+test_sub (struct S a, unsigned char b)
+{
+ a.val -= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]subb" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr91188-1b.c b/gcc/testsuite/gcc.target/i386/pr91188-1b.c
new file mode 100644
index 0000000..9294911
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr91188-1b.c
@@ -0,0 +1,65 @@
+/* PR target/91188 */
+/* { 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 val;
+ unsigned char pad1;
+ unsigned short pad2;
+};
+
+unsigned char b;
+
+struct S
+test_and (struct S a)
+{
+ a.val &= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]andb" } } */
+
+struct S
+test_or (struct S a)
+{
+ a.val |= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]orb" } } */
+
+struct S
+test_xor (struct S a)
+{
+ a.val ^= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]xorb" } } */
+
+struct S
+test_add (struct S a)
+{
+ a.val += b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]addb" } } */
+
+struct S
+test_sub (struct S a)
+{
+ a.val -= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]subb" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr91188-1c.c b/gcc/testsuite/gcc.target/i386/pr91188-1c.c
new file mode 100644
index 0000000..0b32420
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr91188-1c.c
@@ -0,0 +1,113 @@
+/* PR target/91188 */
+/* { 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 val;
+ unsigned char pad1;
+ unsigned short pad2;
+};
+
+struct S
+test_and (struct S a)
+{
+ a.val &= 0x42;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]andb" } } */
+
+struct S
+test_or (struct S a)
+{
+ a.val |= 0x42;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]orb" } } */
+
+struct S
+test_xor (struct S a)
+{
+ a.val ^= 0x42;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]xorb" } } */
+
+struct S
+test_sal (struct S a)
+{
+ a.val <<= 3;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]salb" } } */
+
+struct S
+test_shr (struct S a)
+{
+ a.val >>= 3;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]shrb" } } */
+
+struct S
+test_sar (struct S a)
+{
+ a.val = (signed char) a.val >> 3;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]sarb" } } */
+
+struct S
+test_rol (struct S a)
+{
+ a.val = (a.val << 3 | a.val >> 5) ;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]rolb" } } */
+
+struct S
+test_ror (struct S a)
+{
+ a.val = (a.val >> 3 | a.val << 5) ;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]rorb" } } */
+
+struct S
+test_add (struct S a)
+{
+ a.val += 42;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]addb" } } */
+
+struct S
+test_sub (struct S a)
+{
+ a.val -= 42;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]subb" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr91188-2a.c b/gcc/testsuite/gcc.target/i386/pr91188-2a.c
new file mode 100644
index 0000000..6529114
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr91188-2a.c
@@ -0,0 +1,62 @@
+/* PR target/91188 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-additional-options "-mregparm=3" { target ia32 } } */
+/* { dg-final { scan-assembler-not "movzwl" } } */
+/* { dg-final { scan-assembler-not "movw" } } */
+
+struct S
+{
+ unsigned short val;
+ unsigned short pad;
+};
+
+struct S
+test_and (struct S a, unsigned short b)
+{
+ a.val &= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]andw" } } */
+
+struct S
+test_or (struct S a, unsigned short b)
+{
+ a.val |= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]orw" } } */
+
+struct S
+test_xor (struct S a, unsigned short b)
+{
+ a.val ^= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]xorw" } } */
+
+struct S
+test_add (struct S a, unsigned short b)
+{
+ a.val += b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]addw" } } */
+
+struct S
+test_sub (struct S a, unsigned short b)
+{
+ a.val -= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]subw" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr91188-2b.c b/gcc/testsuite/gcc.target/i386/pr91188-2b.c
new file mode 100644
index 0000000..cdaeae0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr91188-2b.c
@@ -0,0 +1,64 @@
+/* PR target/91188 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-additional-options "-mregparm=3" { target ia32 } } */
+/* { dg-final { scan-assembler-not "movzwl" } } */
+/* { dg-final { scan-assembler-not "movw" } } */
+
+struct S
+{
+ unsigned short val;
+ unsigned short pad;
+};
+
+unsigned short b;
+
+struct S
+test_and (struct S a)
+{
+ a.val &= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]andw" } } */
+
+struct S
+test_or (struct S a)
+{
+ a.val |= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]orw" } } */
+
+struct S
+test_xor (struct S a)
+{
+ a.val ^= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]xorw" } } */
+
+struct S
+test_add (struct S a)
+{
+ a.val += b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]addw" } } */
+
+struct S
+test_sub (struct S a)
+{
+ a.val -= b;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]subw" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr91188-2c.c b/gcc/testsuite/gcc.target/i386/pr91188-2c.c
new file mode 100644
index 0000000..c84e9c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr91188-2c.c
@@ -0,0 +1,112 @@
+/* PR target/91188 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-additional-options "-mregparm=3" { target ia32 } } */
+/* { dg-final { scan-assembler-not "movzwl" } } */
+/* { dg-final { scan-assembler-not "movw" } } */
+
+struct S
+{
+ unsigned short val;
+ unsigned short pad;
+};
+
+struct S
+test_and (struct S a)
+{
+ a.val &= 0x42;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]andw" } } */
+
+struct S
+test_or (struct S a)
+{
+ a.val |= 0x42;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]orw" } } */
+
+struct S
+test_xor (struct S a)
+{
+ a.val ^= 0x42;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]xorw" } } */
+
+struct S
+test_sal (struct S a)
+{
+ a.val <<= 3;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]salw" } } */
+
+struct S
+test_shr (struct S a)
+{
+ a.val >>= 3;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]shrw" } } */
+
+struct S
+test_sar (struct S a)
+{
+ a.val = (signed short) a.val >> 3;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]sarw" } } */
+
+struct S
+test_rol (struct S a)
+{
+ a.val = (a.val << 3 | a.val >> 13) ;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]rolw" } } */
+
+struct S
+test_ror (struct S a)
+{
+ a.val = (a.val >> 3 | a.val << 13) ;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]rorw" } } */
+
+struct S
+test_add (struct S a)
+{
+ a.val += 42;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]addw" } } */
+
+struct S
+test_sub (struct S a)
+{
+ a.val -= 42;
+
+ return a;
+}
+
+/* { dg-final { scan-assembler "\[ \t\]subw" } } */