diff mbox

[rs6000,GCC6] Fix PR78543, ICE in push_reload on powerpc64le-linux-gnu

Message ID 2c67c7b2-867b-b58e-e877-efdd5ee6f2b1@vnet.ibm.com
State New
Headers show

Commit Message

Peter Bergner March 6, 2017, 6:16 p.m. UTC
PR78543 has two related test cases that have similar insns that need
reloading (pseudo 185 in this case) due to spills:

(insn 142 144 146 20 (parallel [
            (set (reg:HI 4 4 [orig:260 p ] [260])
                (bswap:HI (subreg/s/v:HI (reg:DI 185 [ load_dst_59 ]) 0)))
            (clobber (scratch:SI))
        ]) pr78543.i:23 144 {bswaphi2_internal}
     (expr_list:REG_DEAD (reg:DI 185 [ load_dst_59 ])
        (nil)))

In simplify_subreg, we execute the following code:

  /* If we have a SUBREG of a register that we are replacing and we are
     replacing it with a MEM, make a new MEM and try replacing the
     SUBREG with it.  Don't do this if the MEM has a mode-dependent address
     or if we would be widening it.  */

  if (MEM_P (op)
      && ! mode_dependent_address_p (XEXP (op, 0), MEM_ADDR_SPACE (op))
      /* Allow splitting of volatile memory references in case we don't
         have instruction to move the whole thing.  */
      && (! MEM_VOLATILE_P (op)
          || ! have_insn_for (SET, innermode))
      && GET_MODE_SIZE (outermode) <= GET_MODE_SIZE (GET_MODE (op)))
    return adjust_address_nv (op, outermode, byte);

The address we pass to mode_dependent_address_p() is:

	(plus:DI (reg/f:DI 1 1)
		 (const_int 65648 [0x10070]))

...which rs6000_mode_dependent_address() says *is* mode dependent, so we
do not end up calling adjust_address_nv() to adjust the stack address.
This ends up leaving us with the followng insn to handle:

  (subreg/s/v:HI (mem/c:DI (plus:DI (plus:DI (reg/f:DI 1 1)
                  (const_int 65536 [0x10000]))
              (const_int 112 [0x70])) [5 %sfp+65648 S8 A64]) 0)

Which triggers the gcc_assert at reload.c:1348:

  /* Optional output reloads are always OK even if we have no register class,
     since the function of these reloads is only to have spill_reg_store etc.
     set, so that the storing insn can be deleted later.  */
  gcc_assert (rclass != NO_REGS
              || (optional != 0 && type == RELOAD_FOR_OUTPUT));

where: rclass = NO_REGS, optional = 0, type = RELOAD_FOR_INPUT

If we look at rs6000_mode_dependent_address(), it accepts some addresses
as not being mode dependent:

    case PLUS:
      /* Any offset from virtual_stack_vars_rtx and arg_pointer_rtx
         is considered a legitimate address before reload, so there
         are no offset restrictions in that case.  Note that this
         condition is safe in strict mode because any address involving
         virtual_stack_vars_rtx or arg_pointer_rtx would already have
         been rejected as illegitimate.  */
      if (XEXP (addr, 0) != virtual_stack_vars_rtx
          && XEXP (addr, 0) != arg_pointer_rtx
          && GET_CODE (XEXP (addr, 1)) == CONST_INT)
        {
          unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1));
          return val + 0x8000 >= 0x10000 - (TARGET_POWERPC64 ? 8 : 12);
        }
      break;

It seems wrong that we accept addresses based off virtual_stack_vars_rtx
and arg_pointer_rtx, but not stack_pointer_rtx (ie, r1) like we have in
these test cases.  Adding a change to accept stack_pointer_rtx, allows
us to call adjust_address_nv() which ends up transforming the:

  (mem:DI (plus (reg:1) (const_int 65648)))
into:
  (mem:HI (plus (reg:1) (const_int 65648)))

allowing us to eliminate the subreg insn below:

  (subreg/s/v:HI (mem/c:DI (plus:DI (plus:DI (reg/f:DI 1 1)
                  (const_int 65536 [0x10000]))
              (const_int 112 [0x70])) [5 %sfp+65648 S8 A64]) 0)

which solves our ICE.

The following patch passes bootstrap and regtesting on powerpc64le-linux.
Ok for the GCC 6 branch?

We don't hit this on trunk, because we're using LRA there, so I'm not
sure whether we want to add this there this late in the release cycle.

Peter

gcc/
	PR target/78543
	* config/rs6000/rs6000.c (rs6000_mode_dependent_address): Handle
	stack_pointer_rtx.

gcc/testsuite/
	PR target/78543
	* gcc.target/powerpc/pr78543.c: New test.
	* gcc.target/powerpc/pr78543-2.c: Likewise.

Comments

Segher Boessenkool March 6, 2017, 6:55 p.m. UTC | #1
On Mon, Mar 06, 2017 at 12:16:58PM -0600, Peter Bergner wrote:

[ big snip, thanks for the thorough explanation! ]

> The following patch passes bootstrap and regtesting on powerpc64le-linux.
> Ok for the GCC 6 branch?

Please also test on BE and 32-bit.

> We don't hit this on trunk, because we're using LRA there, so I'm not
> sure whether we want to add this there this late in the release cycle.

I prefer to have it on trunk as well.  We *do* still support non-LRA
on trunk, just not by default.

This is okay if all testing works out.  Thanks!


Segher
diff mbox

Patch

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 245904)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -8988,6 +8988,7 @@ 
 	 been rejected as illegitimate.  */
       if (XEXP (addr, 0) != virtual_stack_vars_rtx
 	  && XEXP (addr, 0) != arg_pointer_rtx
+	  && XEXP (addr, 0) != stack_pointer_rtx
 	  && GET_CODE (XEXP (addr, 1)) == CONST_INT)
 	{
 	  unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1));
Index: gcc/testsuite/gcc.target/powerpc/pr78543-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr78543-2.c	(nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/pr78543-2.c	(working copy)
@@ -0,0 +1,60 @@ 
+/* PR target/78543 */
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-O1 -mcpu=power8" } */
+
+typedef long a;
+enum c { e, f, g, h, i, ab } j();
+int l, n, o, p;
+a q, r;
+void *memcpy();
+void b();
+static int k(int *s) {
+  int m;
+  if (j(&m))
+    *s = m;
+  return !0;
+}
+void d(char s) {
+  int af[4];
+  int ag;
+  enum c ah;
+  char ai[24 << 11];
+  unsigned aj;
+  if (!k(&aj))
+    goto ak;
+  for (;;) {
+    if (!k(&ag))
+      goto ak;
+    switch (ah) {
+    case e:
+      b("");
+      b("bad length %d for GUID in fileinfo v%u for \"%s\"");
+    case i:
+      b("bad length %d for TTH in fileinfo v%u for \"%s\"", aj);
+    case ab:
+      if (ag % 24)
+	b("for \"%s\"", s);
+    case f:
+      if (20 == ag)
+      case h:
+	if (20 == ag)
+	  o = 0;
+      break;
+    case g:
+      memcpy(af, ai, sizeof af);
+      b();
+      if (p) {
+	a al, am;
+	r = al << 2 | am;
+	n = af[2];
+	al = n;
+	l = __builtin_bswap32(af[3]);
+	am = q = n | l;
+      }
+    default:
+      b("%s0 unhandled field ID %u 0", __func__);
+    }
+  }
+ak:;
+}
Index: gcc/testsuite/gcc.target/powerpc/pr78543.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr78543.c	(nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/pr78543.c	(working copy)
@@ -0,0 +1,40 @@ 
+/* PR target/78543 */
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-O3 -mcpu=power8" } */
+
+int a, b, c, d, e, f = 0, g, i;
+int h[4];
+extern void fn2();
+extern int fn3();
+extern void fn4();
+extern void fn5();
+void
+fn1 (void)
+{
+  unsigned short j;
+  int k = c;
+  char l[65535];
+  if (g && h[e])
+    fn2();
+  for (; h[e]; e--)
+    if (a)
+      return;
+  for (short n = h[0]; n; n--) {
+    a = fn3(d, l, sizeof l) < 0;
+    if (a)
+      return;
+    char m;
+    short o = 0, p = ({
+		   j = i;
+		   j >> 8 | (j & 255) << 8;
+		 });
+    long q = b;
+    if (g && h[0]) {
+      fn2(k, "%7d", "%7", &o, "%7 ", f);
+      while (b < q)
+	fn4();
+      fn5(m, p, "");
+    }
+  }
+}