diff mbox series

[pushed] aarch64: Avoid allocating FPRs to address registers [PR113623]

Message ID mpth6iv88rc.fsf@arm.com
State New
Headers show
Series [pushed] aarch64: Avoid allocating FPRs to address registers [PR113623] | expand

Commit Message

Richard Sandiford Jan. 30, 2024, 9:34 a.m. UTC
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.

Tested on aarch64-linux-gnu & pushed.

Richard


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.
---
 gcc/config/aarch64/aarch64-early-ra.cc        |   9 ++
 .../gcc.c-torture/compile/pr113623.c          | 137 ++++++++++++++++++
 2 files changed, 146 insertions(+)
 create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr113623.c
diff mbox series

Patch

diff --git a/gcc/config/aarch64/aarch64-early-ra.cc b/gcc/config/aarch64/aarch64-early-ra.cc
index 028296639b8..1a03d86e94b 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 00000000000..ed33890054e
--- /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);
+      }
+}