[RFA][Bug target/108892 ][13 regression] Force re-recognition after changing RTL...
authorJeff Law <jlaw@ventanamicro>
Wed, 5 Apr 2023 15:16:29 +0000 (09:16 -0600)
committerJeff Law <jlaw@ventanamicro>
Wed, 5 Apr 2023 15:19:43 +0000 (09:19 -0600)
So as mentioned in the PR the underlying issue here is combine changes the form of an existing insn, but fails to force re-recognition.  As a result other parts of the compiler blow up.

>                   /* Temporarily replace the set's source with the
>                      contents of the REG_EQUAL note.  The insn will
>                      be deleted or recognized by try_combine.  */
>                   rtx orig_src = SET_SRC (set);                   rtx orig_dest = SET_DEST (set);                   if (GET_CODE (SET_DEST (set)) == ZERO_EXTRACT)
>                     SET_DEST (set) = XEXP (SET_DEST (set), 0);
>                   SET_SRC (set) = note;
>                   i2mod = temp;
>                   i2mod_old_rhs = copy_rtx (orig_src);
>                   i2mod_new_rhs = copy_rtx (note);
>                   next = try_combine (insn, i2mod, NULL, NULL,
>                                       &new_direct_jump_p,                                       last_combined_insn);
>                   i2mod = NULL;
>                   if (next)
>                     {
>                       statistics_counter_event (cfun, "insn-with-note combine", 1);
>                       goto retry;
>                     }                   SET_SRC (set) = orig_src;
>                   SET_DEST (set) = orig_dest;

This code replaces the SET_SRC of an insn in the RTL stream with the contents of a REG_EQUAL note.  So given an insn like this:

> (insn 122 117 127 2 (set (reg:DI 157 [ _46 ])
>         (ior:DI (reg:DI 200)
>             (reg:DI 251))) "j.c":14:5 -1
>      (expr_list:REG_EQUAL (const_int 25769803782 [0x600000006])
>         (nil)))

It replaces the (ior ...) with a (const_int ...).  The resulting insn is passed to try_combine which will try to recognize it, then use it in a combination attempt.  Recognition succeeds with the special define_insn_and_split pattern in the risc-v backend resulting in:

> (insn 122 117 127 2 (set (reg:DI 157 [ _46 ])
>         (const_int 25769803782 [0x600000006])) "j.c":14:5 177 {*mvconst_internal}
>      (expr_list:REG_EQUAL (const_int 25769803782 [0x600000006])
>         (nil)))

This is as-expected.  Now assume we were unable to combine anything, so try_combine returns NULL_RTX.  The quoted code above restores SET_SRC (and SET_DEST) resulting in:

> (insn 122 117 127 2 (set (reg:DI 157 [ _46 ])
>         (ior:DI (reg:DI 200)
>             (reg:DI 251))) "j.c":14:5 177 {*mvconst_internal}
>      (expr_list:REG_EQUAL (const_int 25769803782 [0x600000006])
>         (nil)))

But this doesn't get re-recognized and we ICE later in LRA.

The fix is trivial, reset the INSN_CODE to force re-recognition in the case where try_combine fails.

PR target/108892
gcc/
* combine.cc (combine_instructions): Force re-recognition when
after restoring the body of an insn to its original form.

gcc/testsuite/
* gcc.c-torture/compile/pr108892.c: New test.

gcc/combine.cc
gcc/testsuite/gcc.c-torture/compile/pr108892.c [new file with mode: 0644]

index 053879500b73eef103f819e04961007f18718d69..22bf8e1ec89814ec75a6e042946fbf55ca2e9614 100644 (file)
@@ -1416,6 +1416,7 @@ combine_instructions (rtx_insn *f, unsigned int nregs)
                      statistics_counter_event (cfun, "insn-with-note combine", 1);
                      goto retry;
                    }
+                 INSN_CODE (temp) = -1;
                  SET_SRC (set) = orig_src;
                  SET_DEST (set) = orig_dest;
                }
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr108892.c b/gcc/testsuite/gcc.c-torture/compile/pr108892.c
new file mode 100644 (file)
index 0000000..d7fecd5
--- /dev/null
@@ -0,0 +1,23 @@
+typedef char __attribute__((__vector_size__ (64))) U;
+typedef int __attribute__((__vector_size__ (64))) V;
+
+int g;
+U u;
+
+static inline __attribute__((__always_inline__)) void
+bar (short a, short b, V w)
+{
+  V v = __builtin_shufflevector ((V) { }, a % (0 != w), 17, 22, 20, 15,
+                                20, 23, 17, 20, 16, 21, 16, 19, 18, 14, 15,
+                                14) ^ b;
+  g *= __builtin_memcmp_eq (0, 0, 2);
+  v |= 6;
+  __builtin_ilogb (0);
+  u = (U) w + (U) v;
+}
+
+void
+foo (void)
+{
+  bar (5, 4, (V){30, 4, 1, 5, 6});
+}