This BZ is a request to improve the code we generate for single bit set/clear/flip on the m68k where the target bit varies *and* is properly masked to avoid undefined behavior.

I wasn't able to trigger this in GCC or newlib's runtime, but in the past Kazu was looking at real embedded code, so I'm going to go with the assumption that's where this request came from.

Tested by building the GCC and newlib runtimes (where it does not trigger) and the m68k testsuite (where I've added a trivial test).

Installing on the trunk.

Jeff
commit adfa4e7a5d603569c0ab401ec89af574dff04bcf
Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Sat Nov 19 17:52:04 2016 +0000

        PR target/25111
        * config/m68k/m68k.md (bsetdreg): New pattern.
        (bchgdreg, bclrdreg): Likewise.
    
        PR target/25111
        * gcc.target/m68k/pr25111.c: New test.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@242623 
138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fd09a79..1d560f5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2016-11-19  Jeff Law  <l...@redhat.com>
+
+       PR target/25111
+       * config/m68k/m68k.md (bsetdreg): New pattern.
+       (bchgdreg, bclrdreg): Likewise.
+
 2016-11-19  Kaz Kojima  <kkoj...@gcc.gnu.org>
 
        PR target/78426
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 7b7f373..2085619 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -5336,6 +5336,45 @@
 }
   [(set_attr "type" "bitrw")])
 
+(define_insn "*bsetdreg"
+  [(set (match_operand:SI 0 "register_operand" "+d")
+       (ior:SI (ashift:SI (const_int 1)
+                          (and:SI (match_operand:SI 1 "register_operand" "d")
+                                  (const_int 31)))
+               (match_operand:SI 2 "register_operand" "0")))]
+  ""
+{
+  CC_STATUS_INIT;
+  return "bset %1,%0";
+}
+  [(set_attr "type" "bitrw")])
+
+(define_insn "*bchgdreg"
+  [(set (match_operand:SI 0 "register_operand" "+d")
+       (xor:SI (ashift:SI (const_int 1)
+                          (and:SI (match_operand:SI 1 "register_operand" "d")
+                                  (const_int 31)))
+               (match_operand:SI 2 "register_operand" "0")))]
+  ""
+{
+  CC_STATUS_INIT;
+  return "bchg %1,%0";
+}
+  [(set_attr "type" "bitrw")])
+
+(define_insn "*bclrdreg"
+  [(set (match_operand:SI 0 "register_operand" "+d")
+       (and:SI (rotate:SI (const_int -2)
+                          (and:SI (match_operand:SI 1 "register_operand" "d")
+                                  (const_int 31)))
+               (match_operand:SI 2 "register_operand" "0")))]
+  ""
+{
+  CC_STATUS_INIT;
+  return "bclr %1,%0";
+}
+  [(set_attr "type" "bitrw")])
+
 ;; clear bit, bit number is int
 (define_insn "bclrmemqi"
   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+m")
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 50b8888..41133d8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-11-18  Jeff Law  <l...@redhat.com>
+
+       PR target/25111
+       * gcc.target/m68k/pr25111.c: New test.
+
 2016-11-18  Jakub Jelinek  <ja...@redhat.com>
 
        PR c++/68180
diff --git a/gcc/testsuite/gcc.target/m68k/pr25111.c 
b/gcc/testsuite/gcc.target/m68k/pr25111.c
new file mode 100644
index 0000000..950eeda
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/pr25111.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* { dg-final { scan-assembler-times "bset" 1 } } */
+/* { dg-final { scan-assembler-times "bchg" 1 } } */
+/* { dg-final { scan-assembler-times "bclr" 1 } } */
+
+int bar (void);
+
+int
+foo1 (int b)
+{
+  int a = bar ();
+  return ( a | (1 << (b & 31)));
+}
+
+int
+foo2 (int b)
+{
+  int a = bar ();
+  return ( a ^ (1 << (b & 31)));
+}
+
+
+int
+foo3 (int b)
+{
+  int a = bar ();
+  return ( a & ~(1 << (b & 31)));
+}
+
+

Reply via email to