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

commit r15-9602-ge268cb27332a1c39a5fc8426ae368c9878f3f241
Author: Georg-Johann Lay <a...@gjlay.de>
Date:   Wed Apr 30 08:43:51 2025 +0200

    AVR: target/119989 - Add missing clobbers to xload_<mode>_libgcc.
    
    libgcc's __xload_1...4 is clobbering Z (and also R21 is some cases),
    but avr.md had clobbers of respective GPRs only up to reload.
    Outcome was that code reading from the same __memx address twice
    could be wrong.  This patch adds respective clobbers.
    
          Forward-port from 2025-04-30 r14-11703
          PR target/119989
    gcc/
            * config/avr/avr.md (xload_<mode>_libgcc): Clobber R21, Z.
    
    gcc/testsuite/
            * gcc.target/avr/torture/pr119989.h: New file.
            * gcc.target/avr/torture/pr119989-memx-1.c: New test.
            * gcc.target/avr/torture/pr119989-memx-2.c: New test.
            * gcc.target/avr/torture/pr119989-memx-3.c: New test.
            * gcc.target/avr/torture/pr119989-memx-4.c: New test.
            * gcc.target/avr/torture/pr119989-flashx-1.c: New test.
            * gcc.target/avr/torture/pr119989-flashx-2.c: New test.
            * gcc.target/avr/torture/pr119989-flashx-3.c: New test.
            * gcc.target/avr/torture/pr119989-flashx-4.c: New test.
    
    (cherry picked from commit 1ca1c1fc3b58ae5e1d3db4f5a2014132fe69f82a)

Diff:
---
 gcc/config/avr/avr.md                              |  6 +++-
 .../gcc.target/avr/torture/pr119989-flashx-1.c     |  7 ++++
 .../gcc.target/avr/torture/pr119989-flashx-2.c     |  7 ++++
 .../gcc.target/avr/torture/pr119989-flashx-3.c     |  7 ++++
 .../gcc.target/avr/torture/pr119989-flashx-4.c     |  7 ++++
 .../gcc.target/avr/torture/pr119989-memx-1.c       |  7 ++++
 .../gcc.target/avr/torture/pr119989-memx-2.c       |  7 ++++
 .../gcc.target/avr/torture/pr119989-memx-3.c       |  7 ++++
 .../gcc.target/avr/torture/pr119989-memx-4.c       |  7 ++++
 gcc/testsuite/gcc.target/avr/torture/pr119989.h    | 37 ++++++++++++++++++++++
 10 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 1c4e44dcfe41..14b3e77ae506 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -716,8 +716,10 @@
     || avr_load_libgcc_insn_p (insn, ADDR_SPACE_FLASHX, true)"
   "#"
   "&& reload_completed"
-  [(parallel [(set (reg:MOVMODE REG_22)
+  [(parallel [(set (reg:MOVMODE 22)
                    (match_dup 0))
+              (clobber (reg:QI 21))
+              (clobber (reg:HI REG_Z))
               (clobber (reg:CC REG_CC))])]
   {
     operands[0] = SET_SRC (single_set (curr_insn));
@@ -727,6 +729,8 @@
   [(set (reg:MOVMODE REG_22)
         (mem:MOVMODE (lo_sum:PSI (reg:QI REG_21)
                                  (reg:HI REG_Z))))
+   (clobber (reg:QI 21))
+   (clobber (reg:HI REG_Z))
    (clobber (reg:CC REG_CC))]
   "reload_completed
    && (avr_load_libgcc_insn_p (insn, ADDR_SPACE_MEMX, true)
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-1.c 
b/gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-1.c
new file mode 100644
index 000000000000..086d1eab0e24
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-1.c
@@ -0,0 +1,7 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-std=gnu99" } */
+
+typedef __UINT8_TYPE__ TYP;
+#define AS __flashx
+
+#include "pr119989.h"
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-2.c 
b/gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-2.c
new file mode 100644
index 000000000000..d053ab9c109a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-2.c
@@ -0,0 +1,7 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-std=gnu99" } */
+
+typedef __UINT16_TYPE__ TYP;
+#define AS __flashx
+
+#include "pr119989.h"
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-3.c 
b/gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-3.c
new file mode 100644
index 000000000000..1a5e8f0488ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-3.c
@@ -0,0 +1,7 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-std=gnu99" } */
+
+__extension__ typedef __uint24 TYP;
+#define AS __flashx
+
+#include "pr119989.h"
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-4.c 
b/gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-4.c
new file mode 100644
index 000000000000..63fb52c146ff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-4.c
@@ -0,0 +1,7 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-std=gnu99" } */
+
+typedef __UINT32_TYPE__ TYP;
+#define AS __flashx
+
+#include "pr119989.h"
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr119989-memx-1.c 
b/gcc/testsuite/gcc.target/avr/torture/pr119989-memx-1.c
new file mode 100644
index 000000000000..45535178bdb3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr119989-memx-1.c
@@ -0,0 +1,7 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-std=gnu99" } */
+
+typedef __UINT8_TYPE__ TYP;
+#define AS __memx
+
+#include "pr119989.h"
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr119989-memx-2.c 
b/gcc/testsuite/gcc.target/avr/torture/pr119989-memx-2.c
new file mode 100644
index 000000000000..b28c49775189
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr119989-memx-2.c
@@ -0,0 +1,7 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-std=gnu99" } */
+
+typedef __UINT16_TYPE__ TYP;
+#define AS __memx
+
+#include "pr119989.h"
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr119989-memx-3.c 
b/gcc/testsuite/gcc.target/avr/torture/pr119989-memx-3.c
new file mode 100644
index 000000000000..bb20053c1570
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr119989-memx-3.c
@@ -0,0 +1,7 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-std=gnu99" } */
+
+__extension__ typedef __uint24 TYP;
+#define AS __memx
+
+#include "pr119989.h"
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr119989-memx-4.c 
b/gcc/testsuite/gcc.target/avr/torture/pr119989-memx-4.c
new file mode 100644
index 000000000000..05a3ee7438ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr119989-memx-4.c
@@ -0,0 +1,7 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-std=gnu99" } */
+
+typedef __UINT32_TYPE__ TYP;
+#define AS __memx
+
+#include "pr119989.h"
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr119989.h 
b/gcc/testsuite/gcc.target/avr/torture/pr119989.h
new file mode 100644
index 000000000000..12b5449b7c82
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr119989.h
@@ -0,0 +1,37 @@
+const AS TYP some_data[] = { 1, 2, 3, 4, 5 };
+const AS TYP *IP;
+
+TYP DT, a, b;
+
+__attribute__((noipa))
+void do_test1 (void)
+{
+    DT = *IP;
+    DT = *IP--;
+}
+
+__attribute__((noipa))
+void do_test2 (void)
+{
+    DT = *IP;
+    __asm volatile ("" ::: "memory"); // Prevents unwanted optimization
+    DT = *IP--;
+}
+
+TYP difference(void)
+{
+    IP = &some_data[3];
+    do_test1();
+    a = DT;
+    IP = &some_data[3];
+    do_test2();
+    b = DT;
+    return a - b; // Expected: 0
+}
+
+int main (void)
+{
+    if (difference () != 0)
+        __builtin_exit (__LINE__);
+    return 0;
+}

Reply via email to