diff options
author | Jeff Law <jlaw@ventanamicro> | 2023-04-05 09:16:29 -0600 |
---|---|---|
committer | Jeff Law <jlaw@ventanamicro> | 2023-04-05 09:19:43 -0600 |
commit | 4a45f5d6a9b53f7f5446dee47e25b07d413bb7eb (patch) | |
tree | 50868241121a2296d7e722ae1042316d01ad1185 /gcc | |
parent | ddb0f66e6c1e846bdc217075c9a770bfd0b01970 (diff) | |
download | gcc-4a45f5d6a9b53f7f5446dee47e25b07d413bb7eb.zip gcc-4a45f5d6a9b53f7f5446dee47e25b07d413bb7eb.tar.gz gcc-4a45f5d6a9b53f7f5446dee47e25b07d413bb7eb.tar.bz2 |
[RFA][Bug target/108892 ][13 regression] Force re-recognition after changing RTL structure of an insn
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/combine.cc | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr108892.c | 23 |
2 files changed, 24 insertions, 0 deletions
diff --git a/gcc/combine.cc b/gcc/combine.cc index 0538795..22bf8e1 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 0000000..d7fecd5 --- /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}); +} |