PR93658 shows a problem in rs6000_legitimate_address_p() where we erroneously
mark an Altivec address as being invalid, which causes LRA to go into an
infinite loop spilling the same address over and over again.  The problem
is, when VSX is enabled, the rs6000_vector_mem[<vector mode>], returns
VECTOR_VSX rather than VECTOR_ALTIVEC, causing us to not handle Altivec
load/store addresses correctly.  The following patch tests for both
and fixes the test case.

This passed bootstrap and regtesting on powerpc64le-linux and powerpc64-linux
(in both 32-bit and 64-bit modes) with no regressions.  Ok for trunk?
The same bug exists in FSF 9 anf FSF 8 branches.  Ok for those too after
some burn in on trunk and clean regtests on the backports?

Peter


gcc/
        PR target/93658
        * config/rs6000/rs6000.c (rs6000_legitimate_address_p): Handle VSX
        vector modes.

gcc/testsuite/
        PR target/93658
        * gcc.target/powerpc/pr93658.c: New test.

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index f34e1ba70c6..9910b27ed24 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -8808,7 +8808,7 @@ rs6000_legitimate_address_p (machine_mode mode, rtx x, 
bool reg_ok_strict)
   bool quad_offset_p = mode_supports_dq_form (mode);
 
   /* If this is an unaligned stvx/ldvx type address, discard the outer AND.  */
-  if (VECTOR_MEM_ALTIVEC_P (mode)
+  if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)
       && GET_CODE (x) == AND
       && CONST_INT_P (XEXP (x, 1))
       && INTVAL (XEXP (x, 1)) == -16)
diff --git a/gcc/testsuite/gcc.target/powerpc/pr93658.c 
b/gcc/testsuite/gcc.target/powerpc/pr93658.c
new file mode 100644
index 00000000000..0170d34d259
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr93658.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fstack-protector-strong -mcpu=power8" } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+
+/* PR93658: Failure compiling this test is an infinite loop in LRA's
+   process_address(), so set a short timeout limit.  */
+/* { dg-timeout 5 } */
+
+void bar();
+char b;
+void
+foo (void)
+{
+  char a;
+  int d = b;
+  char *e = &a;
+  while (d)
+    *e++ = --d;
+  bar ();
+}

Reply via email to