combine: Fix split_i2i3 ICE [PR94291]
authorJakub Jelinek <jakub@redhat.com>
Tue, 7 Apr 2020 19:30:12 +0000 (21:30 +0200)
committerJakub Jelinek <jakub@redhat.com>
Tue, 7 Apr 2020 19:30:12 +0000 (21:30 +0200)
The following testcase ICEs on armv7hl-linux-gnueabi.
try_combine is called on:
(gdb) p debug_rtx (i3)
(insn 20 12 22 2 (set (mem/c:SI (plus:SI (reg/f:SI 102 sfp)
                (const_int -4 [0xfffffffffffffffc])) [1 x+0 S4 A32])
        (reg:SI 125)) "pr94291.c":7:8 241 {*arm_movsi_insn}
     (expr_list:REG_DEAD (reg:SI 125)
        (nil)))
(gdb) p debug_rtx (i2)
(insn 12 7 20 2 (parallel [
            (set (reg:CC 100 cc)
                (compare:CC (reg:SI 121 [ <retval> ])
                    (const_int 0 [0])))
            (set (reg:SI 125)
                (reg:SI 121 [ <retval> ]))
        ]) "pr94291.c":7:8 248 {*movsi_compare0}
     (expr_list:REG_UNUSED (reg:CC 100 cc)
        (nil)))
and tries to recognize cc = r121 cmp 0; [sfp-4] = r121 parallel,
but that isn't recognized, so it splits it into two: split_i2i3
[sfp-4] = r121 followed by cc = r121 cmp 0 which is recognized, but
ICEs because the code below insist that the SET_DEST of newi2pat
(or first set in PARALLEL thereof) must be a REG or SUBREG of REG,
but it is a MEM in this case.  I don't see any condition that would
guarantee that, perhaps for the swap_i2i3 case it was somehow guaranteed.

As the code just wants to update LOG_LINKS and LOG_LINKS are only for
registers, not for MEM or anything else, the patch just doesn't update those
if it isn't a REG or SUBREG of REG.

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

PR rtl-optimization/94291
PR rtl-optimization/84169
* combine.c (try_combine): For split_i2i3, don't assume SET_DEST
must be a REG or SUBREG of REG; if it is not one of these, don't
update LOG_LINKs.

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

gcc/ChangeLog
gcc/combine.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr94291.c [new file with mode: 0644]

index a1ab9fb4ef3c6e38ad2bb378f11ebf075dce9826..12803e90b0a0815de845773849905cb7cdd651a2 100644 (file)
@@ -1,3 +1,11 @@
+2020-04-07  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/94291
+       PR rtl-optimization/84169
+       * combine.c (try_combine): For split_i2i3, don't assume SET_DEST
+       must be a REG or SUBREG of REG; if it is not one of these, don't
+       update LOG_LINKs.
+
 2020-04-07  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/94479
index 58366a6d3316eb10c96a810e1275f90a6c878f03..cff76cd3303483aed5476c63b191401ec2599a7e 100644 (file)
@@ -4351,25 +4351,29 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
       if (GET_CODE (x) == PARALLEL)
        x = XVECEXP (newi2pat, 0, 0);
 
-      /* It can only be a SET of a REG or of a SUBREG of a REG.  */
-      unsigned int regno = reg_or_subregno (SET_DEST (x));
-
-      bool done = false;
-      for (rtx_insn *insn = NEXT_INSN (i3);
-          !done
-          && insn
-          && NONDEBUG_INSN_P (insn)
-          && BLOCK_FOR_INSN (insn) == this_basic_block;
-          insn = NEXT_INSN (insn))
-       {
-         struct insn_link *link;
-         FOR_EACH_LOG_LINK (link, insn)
-           if (link->insn == i3 && link->regno == regno)
-             {
-               link->insn = i2;
-               done = true;
-               break;
-             }
+      if (REG_P (SET_DEST (x))
+         || (GET_CODE (SET_DEST (x)) == SUBREG
+             && REG_P (SUBREG_REG (SET_DEST (x)))))
+       {
+         unsigned int regno = reg_or_subregno (SET_DEST (x));
+
+         bool done = false;
+         for (rtx_insn *insn = NEXT_INSN (i3);
+              !done
+              && insn
+              && NONDEBUG_INSN_P (insn)
+              && BLOCK_FOR_INSN (insn) == this_basic_block;
+              insn = NEXT_INSN (insn))
+           {
+             struct insn_link *link;
+             FOR_EACH_LOG_LINK (link, insn)
+               if (link->insn == i3 && link->regno == regno)
+                 {
+                   link->insn = i2;
+                   done = true;
+                   break;
+                 }
+           }
        }
     }
 
index 71b5a14bcbe57b2d01084560a49b42f1ab0345f9..3cbf891d58d168c14d72f14cd4a94ca646f92755 100644 (file)
@@ -1,3 +1,9 @@
+2020-04-07  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/94291
+       PR rtl-optimization/84169
+       * gcc.dg/pr94291.c: New test.
+
 2020-04-07  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/94479
diff --git a/gcc/testsuite/gcc.dg/pr94291.c b/gcc/testsuite/gcc.dg/pr94291.c
new file mode 100644 (file)
index 0000000..7daa2b0
--- /dev/null
@@ -0,0 +1,14 @@
+/* PR rtl-optimization/94291 */
+/* { dg-do compile } */
+/* { dg-options "-Og" } */
+
+unsigned a;
+
+unsigned
+foo (void)
+{
+  unsigned x
+    = (__builtin_sub_overflow ((long long) a, 0, &x)
+       ? 1 : (__INTPTR_TYPE__) __builtin_memmove (&x, foo, 1));
+  return a;
+}