]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
AVR: target/119989 - Add missing clobbers to xload_<mode>_libgcc.
authorGeorg-Johann Lay <avr@gjlay.de>
Wed, 30 Apr 2025 06:43:51 +0000 (08:43 +0200)
committerGeorg-Johann Lay <avr@gjlay.de>
Wed, 30 Apr 2025 09:31:58 +0000 (11:31 +0200)
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)

gcc/config/avr/avr.md
gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/torture/pr119989-flashx-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/torture/pr119989-memx-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/torture/pr119989-memx-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/torture/pr119989-memx-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/torture/pr119989-memx-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/torture/pr119989.h [new file with mode: 0644]

index 1c4e44dcfe416b651aaf9aa2e1a8dfeef28dd899..01b8e4bce4cf9e2ab1a35785b61695220ed90ff6 100644 (file)
   "&& reload_completed"
   [(parallel [(set (reg:MOVMODE REG_22)
                    (match_dup 0))
+              (clobber (reg:QI REG_21))
+              (clobber (reg:HI REG_Z))
               (clobber (reg:CC REG_CC))])]
   {
     operands[0] = SET_SRC (single_set (curr_insn));
   [(set (reg:MOVMODE REG_22)
         (mem:MOVMODE (lo_sum:PSI (reg:QI REG_21)
                                  (reg:HI REG_Z))))
+   (clobber (reg:QI REG_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 (file)
index 0000000..086d1ea
--- /dev/null
@@ -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 (file)
index 0000000..d053ab9
--- /dev/null
@@ -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 (file)
index 0000000..1a5e8f0
--- /dev/null
@@ -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 (file)
index 0000000..63fb52c
--- /dev/null
@@ -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 (file)
index 0000000..4553517
--- /dev/null
@@ -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 (file)
index 0000000..b28c497
--- /dev/null
@@ -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 (file)
index 0000000..bb20053
--- /dev/null
@@ -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 (file)
index 0000000..05a3ee7
--- /dev/null
@@ -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 (file)
index 0000000..12b5449
--- /dev/null
@@ -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;
+}