https://gcc.gnu.org/g:b407be9e4bdc117a59d232a4db9672544c14a40a

commit r17-2286-gb407be9e4bdc117a59d232a4db9672544c14a40a
Author: Andreas Schwab <[email protected]>
Date:   Thu Jul 9 20:24:35 2026 +0200

    m68k: Properly model bset/bclr on memory
    
    When operating on memory the bset and bclr insns use only the low 3 bits
    of the bit number.
    
            PR target/126121
    gcc/
            * config/m68k/m68k.md (bsetmemqi, *bsetmemqi_ext, bclrmemqi)
            (*bclrmemqi_ext): Add AND with 7 around bit number.
    gcc/testsuite/
            * gcc.dg/torture/pr126121.c: New test.

Diff:
---
 gcc/config/m68k/m68k.md                 | 20 ++++++++++++--------
 gcc/testsuite/gcc.dg/torture/pr126121.c | 19 +++++++++++++++++++
 2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index e77ac13cf1b7..227399feeee4 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -5387,7 +5387,8 @@
 (define_insn "bsetmemqi"
   [(set (match_operand:QI 0 "memory_operand" "+m")
        (ior:QI (subreg:QI (ashift:SI (const_int 1)
-               (match_operand:SI 1 "general_operand" "d")) 3)
+               (and:SI (match_operand:SI 1 "general_operand" "d")
+                       (const_int 7))) 3)
        (match_dup 0)))]
   ""
   "bset %1,%0"
@@ -5397,8 +5398,9 @@
 (define_insn "*bsetmemqi_ext"
   [(set (match_operand:QI 0 "memory_operand" "+m")
        (ior:QI (subreg:QI (ashift:SI (const_int 1)
-           (match_operator:SI 2 "extend_operator"
-               [(match_operand 1 "general_operand" "d")])) 3)
+           (and:SI (match_operator:SI 2 "extend_operator"
+                       [(match_operand 1 "general_operand" "d")])
+                   (const_int 7))) 3)
        (match_dup 0)))]
   ""
   "bset %1,%0"
@@ -5438,8 +5440,9 @@
 (define_insn "bclrmemqi"
   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+m")
        (const_int 1)
-       (minus:SI (const_int 7)
-           (match_operand:SI 1 "general_operand" "d")))
+       (and:SI (minus:SI (const_int 7)
+                   (match_operand:SI 1 "general_operand" "d"))
+               (const_int 7)))
     (const_int 0))]
   ""
   "bclr %1,%0"
@@ -5449,9 +5452,10 @@
 (define_insn "*bclrmemqi_ext"
   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+m")
        (const_int 1)
-       (minus:SI (const_int 7)
-           (match_operator:SI 2 "extend_operator"
-               [(match_operand 1 "general_operand" "d")])))
+       (and:SI (minus:SI (const_int 7)
+                   (match_operator:SI 2 "extend_operator"
+                       [(match_operand 1 "general_operand" "d")]))
+               (const_int 7)))
     (const_int 0))]
   ""
   "bclr %1,%0"
diff --git a/gcc/testsuite/gcc.dg/torture/pr126121.c 
b/gcc/testsuite/gcc.dg/torture/pr126121.c
new file mode 100644
index 000000000000..cea2c4eda658
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr126121.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+
+__attribute__ ((noipa,noclone,noinline))
+void foo (char *a, int b)
+{
+  char c = 1 << b;
+  *a |= c;
+}
+
+int
+main (void)
+{
+  char a = 0;
+  foo (&a, 1);
+  if (a != 2) __builtin_abort ();
+  foo (&a, __CHAR_BIT__ + 2);
+  if (a != 2) __builtin_abort ();
+}
+

Reply via email to