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.

Bootstrapped and regression tested on x86_64 and riscv.   OK for the trunk?

Jeff
gcc/
        * combine.cc (combine_instructions): Force re-recognition when
        potentially changing the underlying RTL structure of an insn.

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

diff --git a/gcc/combine.cc b/gcc/combine.cc
index 053879500b7..22bf8e1ec89 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -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
index 00000000000..d7fecd54ecf
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr108892.c
@@ -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});
+}

Reply via email to