re PR target/91188 (strict_low_part operations do not work)
authorUros Bizjak <ubizjak@gmail.com>
Thu, 18 Jul 2019 17:17:31 +0000 (19:17 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Thu, 18 Jul 2019 17:17:31 +0000 (19:17 +0200)
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

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr91188-1a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr91188-1b.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr91188-1c.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr91188-2a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr91188-2b.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr91188-2c.c [new file with mode: 0644]

index 7055ca4398bce7889e176881fd4f850fb6a5477f..4a64253a3c039616d01ff23f85e0193d7fce2441 100644 (file)
@@ -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
index 62485c34a96a1c16b2849d355b4a6288321b304a..4fc03009c53017791c1aca4942bc7e41118257fd 100644 (file)
              (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
   [(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)
              (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")
              (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)
   "(!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")])
 
              (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
        (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
        (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")
index 7bf322fc18220d6ce27398598a6d514f5b7f9201..7eb95f7127d65c6c143e8271008c59fb3794a755 100644 (file)
@@ -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 (file)
index 0000000..8673c2a
--- /dev/null
@@ -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 (file)
index 0000000..9294911
--- /dev/null
@@ -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 (file)
index 0000000..0b32420
--- /dev/null
@@ -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 (file)
index 0000000..6529114
--- /dev/null
@@ -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 (file)
index 0000000..cdaeae0
--- /dev/null
@@ -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 (file)
index 0000000..c84e9c5
--- /dev/null
@@ -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" } } */