aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2025-01-22 12:22:42 +0000
committerRichard Sandiford <richard.sandiford@arm.com>2025-01-22 12:22:42 +0000
commit6fbf0b55b4308da36f6e766d20d4b64ff5095b48 (patch)
tree59ba62508d9c2bfb440c765314c941e37942cb83
parent6f4592ae95eed53dc3a370f98c04a8f25f007811 (diff)
downloadgcc-6fbf0b55b4308da36f6e766d20d4b64ff5095b48.zip
gcc-6fbf0b55b4308da36f6e766d20d4b64ff5095b48.tar.gz
gcc-6fbf0b55b4308da36f6e766d20d4b64ff5095b48.tar.bz2
aarch64: Fix aarch64_write_sysregdi predicate
While working on another MSR-related patch, I noticed that aarch64_write_sysregdi's constraints allowed zero, but its predicate didn't. This could in principle lead to an ICE during or after RA, since "Z" allows the RA to rematerialise a known zero directly into the instruction. The usual techniques for exposing a bug like that didn't work in this case, since the optimisers seem to make no attempt to remove redundant zero moves (at least not for these unspec_volatiles). But the problem still seems worth fixing pre-emptively. gcc/ * config/aarch64/aarch64.md (aarch64_read_sysregti): Change the source predicate to aarch64_reg_or_zero. gcc/testsuite/ * gcc.target/aarch64/acle/rwsr-4.c: New test. * gcc.target/aarch64/acle/rwsr-armv8p9.c: Avoid read of uninitialized variable.
-rw-r--r--gcc/config/aarch64/aarch64.md2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/acle/rwsr-4.c15
-rw-r--r--gcc/testsuite/gcc.target/aarch64/acle/rwsr-armv8p9.c4
3 files changed, 17 insertions, 4 deletions
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index f8d82ce..39655ea 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -659,7 +659,7 @@
(define_insn "aarch64_write_sysregdi"
[(unspec_volatile:DI [(match_operand 0 "aarch64_sysreg_string" "")
- (match_operand:DI 1 "register_operand" "rZ")]
+ (match_operand:DI 1 "aarch64_reg_or_zero" "rZ")]
UNSPEC_SYSREG_WDI)]
""
"msr\t%0, %x1"
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/rwsr-4.c b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-4.c
new file mode 100644
index 0000000..52fb603
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-4.c
@@ -0,0 +1,15 @@
+/* { dg-options "-O" } */
+
+#include <stdint.h>
+#include <arm_acle.h>
+
+void f();
+void g()
+{
+ int64_t x = 0;
+ __arm_wsr64("tpidr_el0", x);
+ f();
+ __arm_wsr64("tpidr_el0", x);
+}
+
+/* { dg-final { scan-assembler-times {\tmsr\t[^,]+, xzr\n} 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/acle/rwsr-armv8p9.c b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-armv8p9.c
index e2f297b..c49fbb5 100644
--- a/gcc/testsuite/gcc.target/aarch64/acle/rwsr-armv8p9.c
+++ b/gcc/testsuite/gcc.target/aarch64/acle/rwsr-armv8p9.c
@@ -3,10 +3,8 @@
/* { dg-options "-O2 -march=armv8.9-a" } */
#include <arm_acle.h>
void
-readwrite_armv8p9a_sysregs ()
+readwrite_armv8p9a_sysregs (long long int a)
{
- long long int a;
-
/* Write-only system registers. */
__arm_wsr64 ("pmzr_el0", a); /* { dg-final { scan-assembler "msr\ts3_3_c9_c13_4, x0" } } */