Hi, Lower-subreg decomposes concatn subregs. Since the regmode-natural-size changes we could trigger an ICE by insisting the inner mode of such a subreg is splittable into words. But the CONCATN handling in lower-subreg is specifically for the CONCATNs that lower-subreg.cc itself creates, rather than a general operation. For example, other parts of the file assume that a CONCATN has exactly two operands. There are also other asserts that could trigger for preexisting CONCATNs.
This patch sets a flag on these temporary CONCATNs to distinguish them from preexisting CONCATNs. 'volatil' is free and is used in a similar fashion by var-tracking.cc (for CONCAT rather than CONCATN). Bootstrapped and regtested on x86, power10, and aarch64. Regtested on risc64. Regards Robin Co-Authored-By: Richard Sandiford <[email protected]> PR rtl-optimization/127443 gcc/ChangeLog: * lower-subreg.cc (DECOMPOSED_REGISTER_P): New macro. (decompose_register): Mark decomposed. (resolve_reg_p): Only resolve decomposed regs. (resolve_subreg_p): Move. (simplify_subreg_concatn): Remove assert. (simplify_gen_subreg_concatn): Use resolve_subreg_p. (resolve_operand_for_swap_move_operator): Adjust assert. (resolve_debug): Unmark as decomposed. * rtl.h (struct GTY): Document usage of volatil in lower-subreg. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/pr127443.c: New test. --- gcc/lower-subreg.cc | 63 ++++++++++--------- gcc/rtl.h | 1 + .../gcc.target/riscv/rvv/autovec/pr127443.c | 14 +++++ 3 files changed, 50 insertions(+), 28 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/pr127443.c diff --git a/gcc/lower-subreg.cc b/gcc/lower-subreg.cc index 548f1b0d4b8..e4d613c5d22 100644 --- a/gcc/lower-subreg.cc +++ b/gcc/lower-subreg.cc @@ -76,6 +76,10 @@ along with GCC; see the file COPYING3. If not see #define LOG_COSTS 0 #define FORCE_LOWERING 0 +/* True if a CONCATN was created by decompose_register. */ +#define DECOMPOSED_REGISTER_P(x) \ + (RTL_FLAG_CHECK1 ("DECOMPOSED_REGISTER_P", (x), CONCATN)->volatil) + /* Bit N in this bitmap is set if regno N is used in a context in which we can decompose it. */ static bitmap decomposable_context; @@ -650,6 +654,7 @@ decompose_register (unsigned int regno) RTVEC_ELT (v, i) = gen_reg_rtx_offset (reg, word_mode, i * UNITS_PER_WORD); PUT_CODE (reg, CONCATN); + DECOMPOSED_REGISTER_P (reg) = true; XVEC (reg, 0) = v; if (dump_file) @@ -661,6 +666,26 @@ decompose_register (unsigned int regno) } } +/* Return whether we should resolve X into the registers into which it + was decomposed. */ + +static bool +resolve_reg_p (rtx x) +{ + return GET_CODE (x) == CONCATN && DECOMPOSED_REGISTER_P (x); +} + +/* Return whether X is a SUBREG of a register which we need to + resolve. */ + +static bool +resolve_subreg_p (rtx x) +{ + if (GET_CODE (x) != SUBREG) + return false; + return resolve_reg_p (SUBREG_REG (x)); +} + /* Get a SUBREG of a CONCATN. */ static rtx @@ -672,6 +697,8 @@ simplify_subreg_concatn (machine_mode outermode, rtx op, poly_uint64 orig_byte) unsigned int final_offset; unsigned int byte; + gcc_assert (resolve_reg_p (op)); + innermode = GET_MODE (op); if (!interesting_mode_p (innermode, &inner_size, &inner_words)) @@ -682,7 +709,6 @@ simplify_subreg_concatn (machine_mode outermode, rtx op, poly_uint64 orig_byte) /* Must be constant if outer_size is. */ byte = orig_byte.to_constant (); - gcc_assert (GET_CODE (op) == CONCATN); gcc_assert (byte % outer_size == 0); gcc_assert (byte < inner_size); @@ -721,7 +747,7 @@ simplify_gen_subreg_concatn (machine_mode outermode, rtx op, If OP is a SUBREG of a CONCATN, then it must be a simple mode change with the same size and offset 0, or it must extract a part. We shouldn't see anything else here. */ - if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == CONCATN) + if (resolve_subreg_p (op)) { rtx op2; @@ -749,7 +775,7 @@ simplify_gen_subreg_concatn (machine_mode outermode, rtx op, gcc_assert (innermode == GET_MODE (op)); } - if (GET_CODE (op) == CONCATN) + if (resolve_reg_p (op)) return simplify_subreg_concatn (outermode, op, byte); ret = simplify_gen_subreg (outermode, op, innermode, byte); @@ -765,26 +791,6 @@ simplify_gen_subreg_concatn (machine_mode outermode, rtx op, return ret; } -/* Return whether we should resolve X into the registers into which it - was decomposed. */ - -static bool -resolve_reg_p (rtx x) -{ - return GET_CODE (x) == CONCATN; -} - -/* Return whether X is a SUBREG of a register which we need to - resolve. */ - -static bool -resolve_subreg_p (rtx x) -{ - if (GET_CODE (x) != SUBREG) - return false; - return resolve_reg_p (SUBREG_REG (x)); -} - /* Look for SUBREGs in *LOC which need to be decomposed. */ static bool @@ -900,7 +906,7 @@ can_decompose_p (rtx x) static rtx resolve_operand_for_swap_move_operator (rtx opnd) { - gcc_assert (GET_CODE (opnd) == CONCATN); + gcc_assert (resolve_reg_p (opnd)); rtx concatn = copy_rtx (opnd); rtx op0 = XVECEXP (concatn, 0, 0); rtx op1 = XVECEXP (concatn, 0, 1); @@ -1263,11 +1269,12 @@ resolve_debug (rtx_insn *insn) if (x) *loc = x; - else - x = copy_rtx (*loc); } - if (resolve_reg_p (x)) - *loc = copy_rtx (x); + else if (resolve_reg_p (x)) + { + *loc = copy_rtx (x); + DECOMPOSED_REGISTER_P (*loc) = false; + } } df_insn_rescan (insn); diff --git a/gcc/rtl.h b/gcc/rtl.h index d61e576c940..c9dd7d76c30 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -361,6 +361,7 @@ struct GTY((desc("0"), tag("0"), In a PREFETCH, this flag indicates that it should be considered a scheduling barrier. 1 in a CONCAT is VAL_NEEDS_RESOLUTION in var-tracking.cc. + 1 in a CONCATN is used internally by lower-subreg.cc. Dumped as "/v" in RTL dumps. */ unsigned int volatil : 1; /* 1 in a REG if the register is used only in exit code a loop. diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr127443.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr127443.c new file mode 100644 index 00000000000..e78c9a2d6a1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr127443.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O -march=rv64gcv -mabi=lp64d -g" } */ + +typedef __attribute__((__vector_size__(16))) __int128 V; +typedef __attribute__((__vector_size__(16))) char W; + +char c; + +void +foo(V v) +{ + v &= c; + c = ((W)v)[1]; +} -- 2.55.0
