aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2024-01-30 09:30:35 +0000
committerRichard Sandiford <richard.sandiford@arm.com>2024-01-30 09:30:35 +0000
commitfa2739ac1b74769d97fba34db9b9a8aa8786539e (patch)
tree331421137f262e3c46904e3d5f465e59395ec663 /gcc
parentaeec7d87a28ac80c64ebfa88cef3dccee3ba8efc (diff)
downloadgcc-fa2739ac1b74769d97fba34db9b9a8aa8786539e.zip
gcc-fa2739ac1b74769d97fba34db9b9a8aa8786539e.tar.gz
gcc-fa2739ac1b74769d97fba34db9b9a8aa8786539e.tar.bz2
aarch64: Avoid allocating FPRs to address registers [PR113623]
For something like: void foo (void) { int *ptr; asm volatile ("%0" : "=w" (ptr)); asm volatile ("%0" :: "m" (*ptr)); } early-ra would allocate ptr to an FPR for the first asm, thus leaving an FPR address in the second asm. The address was then reloaded by LRA to make it valid. But early-ra shouldn't be allocating at all in that kind of situation. Doing so caused the ICE in the PR (with LDP fusion). Fixed by making sure that we record address references as GPR references. gcc/ PR target/113623 * config/aarch64/aarch64-early-ra.cc (early_ra::preprocess_insns): Mark all registers that occur in addresses as needing a GPR. gcc/testsuite/ PR target/113623 * gcc.c-torture/compile/pr113623.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/aarch64/aarch64-early-ra.cc9
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr113623.c137
2 files changed, 146 insertions, 0 deletions
diff --git a/gcc/config/aarch64/aarch64-early-ra.cc b/gcc/config/aarch64/aarch64-early-ra.cc
index 0282966..1a03d86 100644
--- a/gcc/config/aarch64/aarch64-early-ra.cc
+++ b/gcc/config/aarch64/aarch64-early-ra.cc
@@ -1173,6 +1173,15 @@ early_ra::preprocess_insns ()
if (!NONDEBUG_INSN_P (insn))
continue;
+ // Mark all registers that occur in addresses as needing a GPR.
+ vec_rtx_properties properties;
+ properties.add_insn (insn, true);
+ for (rtx_obj_reference ref : properties.refs ())
+ if (ref.is_reg ()
+ && ref.in_address ()
+ && !HARD_REGISTER_NUM_P (ref.regno))
+ m_pseudo_regs[ref.regno].flags |= ALLOWS_NONFPR | NEEDS_NONFPR;
+
if (GET_CODE (PATTERN (insn)) == USE
|| GET_CODE (PATTERN (insn)) == CLOBBER)
continue;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr113623.c b/gcc/testsuite/gcc.c-torture/compile/pr113623.c
new file mode 100644
index 0000000..ed33890
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr113623.c
@@ -0,0 +1,137 @@
+typedef struct A A;
+typedef struct B B;
+struct A { char *a; long b; };
+enum { C, D };
+typedef struct { A *c; A *d; } E;
+typedef enum { F } G;
+typedef enum { H } I;
+struct B { A *e, *f, *g, *h; char i; } j;
+int k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae, af;
+int ag, ah, ai, aj, ak, al, am, an, ao, ap;
+E aq;
+G ar;
+I as;
+char at;
+
+static int
+foo (char *c, long d)
+{
+ switch (d) {
+ case 7:
+ switch (c[6])
+ case 'd':
+ if (ao)
+ case 'h':
+ if (an)
+ case 'r':
+ if (am)
+ case 's':
+ if (al)
+ if (ak)
+ return C;
+ /* FALLTHRU */
+ case 8:
+ switch (c[7])
+ case 'e':
+ if (aj)
+ case 'h':
+ if (ai)
+ case 'n':
+ if (ah)
+ case 'y':
+ if (ag)
+ case 9:
+ switch (c[8])
+ case 'l':
+ case 0:
+ switch (c[9])
+ case 'e':
+ if (af)
+ if (ae)
+ case 'n':
+ if (ad)
+ case 't':
+ if (ac)
+ case 'y':
+ if (ab)
+ case 1:
+ switch (c[0])
+ case 'r':
+ case 2:
+ switch (c[1])
+ case 'e':
+ case 3:
+ switch (c[2])
+ case 'd':
+ if (aa)
+ case 'e':
+ if (z)
+ case 'h':
+ if (y)
+ case 'l':
+ if (x)
+ case 'n':
+ if (w)
+ case 's':
+ if (v)
+ case 4:
+ switch (c[3])
+ case 'h':
+ if (u)
+ case 't':
+ if (t)
+ case 5:
+ switch (c[4])
+ case 'e':
+ if (s)
+ case 'g':
+ if (r)
+ case 6:
+ switch (c[5])
+ case 'e':
+ if (q)
+ if (p)
+ case 'g':
+ if (o)
+ case 'n':
+ if (n)
+ if (m)
+ case 7:
+ switch (c[6])
+ case 'e':
+ if (l)
+ case 'g':
+ if (k)
+ return D;
+ }
+ return 0;
+}
+
+void bar (void);
+
+static int
+baz (B *x)
+{
+ aq.c = x->e;
+ aq.d = x->f;
+ ap = foo (x->e->a, x->e->b);
+ if (x->i)
+ bar ();
+ x->g = aq.c;
+ x->h = aq.d;
+ return 0;
+}
+
+void
+qux (void)
+{
+ for (; at;)
+ switch (as)
+ {
+ case H:
+ baz (&j);
+ j.f->b = 0;
+ if (ar)
+ baz (&j);
+ }
+}