cselib, reload: Fix cselib ICE on m68k/microblaze [PR94526]
authorJakub Jelinek <jakub@redhat.com>
Wed, 8 Apr 2020 19:23:58 +0000 (21:23 +0200)
committerJakub Jelinek <jakub@redhat.com>
Wed, 8 Apr 2020 19:23:58 +0000 (21:23 +0200)
The following testcase ICEs on m68k (and another one Jeff mailed me
privately on microblaze).
The problem is that reload creates two DEBUG_INSNs with the same
value of (plus:P (reg:P sp) (const_int 0)), we compute correctly the
same hash value for them, but then don't find them in the cselib hash table,
as rtx_equal_for_cselib_1 thinks it is different from (reg:P sp),
and trigger an assertion failure that requires that from two different debug
insns one doesn't add locations to VALUEs.

The patch has two fixes for this, each fixes the ICE on both targets
separately, but I think we want both.

The cselib.c change ensures that rtx_equal_for_cselib_1 considers
(value:P sp_derived_value) and (plus:P (reg:P sp) (const_int 0)) equivalent.

The reload1.c change makes sure we don't create those bogus plus 0
expressions.  I understand the reasons for creating them, but they don't
really apply to DEBUG_INSNs; we don't have validity matching there, all we
care is that the expressions aren't arbitrarily deep, but it is just fine
to fold x + 0 into just x in there.

2020-04-08  Jakub Jelinek  <jakub@redhat.com>

PR middle-end/94526
* cselib.c (autoinc_split): Handle e->val_rtx being SP_DERIVED_VALUE_P
with zero offset.
* reload1.c (eliminate_regs_1): Avoid creating
(plus (reg) (const_int 0)) in DEBUG_INSNs.

* gcc.dg/pr94526.c: New test.

gcc/ChangeLog
gcc/cselib.c
gcc/reload1.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr94526.c [new file with mode: 0644]

index dcdfae1ae8cfb8013b2dd2bc6aeaefbbf07582c6..20fe7e2ac637398d046c46ac6c0beecca549ae60 100644 (file)
@@ -1,5 +1,11 @@
 2020-04-08  Jakub Jelinek  <jakub@redhat.com>
 
+       PR middle-end/94526
+       * cselib.c (autoinc_split): Handle e->val_rtx being SP_DERIVED_VALUE_P
+       with zero offset.
+       * reload1.c (eliminate_regs_1): Avoid creating
+       (plus (reg) (const_int 0)) in DEBUG_INSNs.
+
        PR tree-optimization/94524
        * tree-vect-generic.c (expand_vector_divmod): If any elt of op1 is
        negative for signed TRUNC_MOD_EXPR, multiply with absolute value of
index 69c9ca5b211cbc9f5c6403dcadb5f943bfdc66f9..0de683617d1e2dae64b0122d1af6572028680f05 100644 (file)
@@ -884,21 +884,29 @@ autoinc_split (rtx x, rtx *off, machine_mode memmode)
       else
        e = cselib_lookup (x, GET_MODE (x), 0, memmode);
       if (e)
-       for (struct elt_loc_list *l = e->locs; l; l = l->next)
-         if (GET_CODE (l->loc) == PLUS
-             && GET_CODE (XEXP (l->loc, 0)) == VALUE
-             && SP_DERIVED_VALUE_P (XEXP (l->loc, 0))
-             && CONST_INT_P (XEXP (l->loc, 1)))
+       {
+         if (SP_DERIVED_VALUE_P (e->val_rtx)
+             && (*off == NULL_RTX || *off == const0_rtx))
            {
-             if (*off == NULL_RTX)
-               *off = XEXP (l->loc, 1);
-             else
-               *off = plus_constant (Pmode, *off,
-                                     INTVAL (XEXP (l->loc, 1)));
-             if (*off == const0_rtx)
-               *off = NULL_RTX;
-             return XEXP (l->loc, 0);
+             *off = NULL_RTX;
+             return e->val_rtx;
            }
+         for (struct elt_loc_list *l = e->locs; l; l = l->next)
+           if (GET_CODE (l->loc) == PLUS
+               && GET_CODE (XEXP (l->loc, 0)) == VALUE
+               && SP_DERIVED_VALUE_P (XEXP (l->loc, 0))
+               && CONST_INT_P (XEXP (l->loc, 1)))
+             {
+               if (*off == NULL_RTX)
+                 *off = XEXP (l->loc, 1);
+               else
+                 *off = plus_constant (Pmode, *off,
+                                       INTVAL (XEXP (l->loc, 1)));
+               if (*off == const0_rtx)
+                 *off = NULL_RTX;
+               return XEXP (l->loc, 0);
+             }
+       }
     }
   return x;
 }
index 2f02c3e8636eb46d88a3ec2e56b4f7359c966001..88f4727d5453dd0b406fc22838274a3a7bb1eb5c 100644 (file)
@@ -2607,8 +2607,9 @@ eliminate_regs_1 (rtx x, machine_mode mem_mode, rtx insn,
                   structure of the insn in a way that reload can't handle.
                   We special-case the commonest situation in
                   eliminate_regs_in_insn, so just replace a PLUS with a
-                  PLUS here, unless inside a MEM.  */
-               if (mem_mode != 0
+                  PLUS here, unless inside a MEM.  In DEBUG_INSNs, it is
+                  always ok to replace a PLUS with just a REG.  */
+               if ((mem_mode != 0 || (insn && DEBUG_INSN_P (insn)))
                    && CONST_INT_P (XEXP (x, 1))
                    && known_eq (INTVAL (XEXP (x, 1)), -ep->previous_offset))
                  return ep->to_rtx;
index 134280d1369e8f68c3dad8a91328e4f46368c8d0..6f26fc6cdc275b162c826d54a084aef028000ca4 100644 (file)
@@ -1,5 +1,8 @@
 2020-04-08  Jakub Jelinek  <jakub@redhat.com>
 
+       PR middle-end/94526
+       * gcc.dg/pr94526.c: New test.
+
        PR tree-optimization/94524
        * gcc.c-torture/execute/pr94524-1.c: New test.
        * gcc.c-torture/execute/pr94524-2.c: New test.
diff --git a/gcc/testsuite/gcc.dg/pr94526.c b/gcc/testsuite/gcc.dg/pr94526.c
new file mode 100644 (file)
index 0000000..9864c4c
--- /dev/null
@@ -0,0 +1,21 @@
+/* PR middle-end/94526 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -g" } */
+
+struct S { int val[8 * sizeof (int)]; };
+
+void
+foo (struct S *x)
+{
+  struct S *a = x;
+}
+
+void baz (struct S);
+
+void
+bar (void)
+{
+  struct S b;
+  foo (&b);
+  baz (b);
+}