Hi, Richard. This patch fixes an ICE on record_use during RTL_SSA initialization RISC-V backend VSETVL PASS.
This is the ICE: 0x11a8603 partial_subreg_p(machine_mode, machine_mode) ../../../../gcc/gcc/rtl.h:3187 0x3b695eb rtl_ssa::function_info::record_use(rtl_ssa::function_info::build_info&, rtl_ssa::insn_info*, rtx_obj_reference) ../../../../gcc/gcc/rtl-ssa/insns.cc:524 In record_use: if (HARD_REGISTER_NUM_P (regno) && partial_subreg_p (use->mode (), mode)) Assertion failed on partial_subreg_p which is: inline bool partial_subreg_p (machine_mode outermode, machine_mode innermode) { /* Modes involved in a subreg must be ordered. In particular, we must always know at compile time whether the subreg is paradoxical. */ poly_int64 outer_prec = GET_MODE_PRECISION (outermode); poly_int64 inner_prec = GET_MODE_PRECISION (innermode); gcc_checking_assert (ordered_p (outer_prec, inner_prec)); -----> cause ICE. return maybe_lt (outer_prec, inner_prec); } RISC-V VSETVL PASS is an advanced lazy vsetvl insertion PASS after RA (register allocation). The rootcause is that we have a pattern (reduction instruction) that includes both VLA (length-agnostic) and VLS (fixed-length) modes. (insn 168 173 170 31 (set (reg:RVVM1SI 101 v5 [311]) (unspec:RVVM1SI [ (unspec:V32BI [ (const_vector:V32BI [ (const_int 1 [0x1]) repeated x32 ]) (reg:DI 30 t5 [312]) (const_int 2 [0x2]) repeated x2 (reg:SI 66 vl) (reg:SI 67 vtype) ] UNSPEC_VPREDICATE) (unspec:RVVM1SI [ (reg:V32SI 96 v0 [orig:185 vect__96.40 ] [185]) -----> VLS mode NUNITS = 32 elements. (reg:RVVM1SI 113 v17 [439]) -----> VLA mode NUNITS = [8, 8] elements. ] UNSPEC_REDUC_XOR) (unspec:RVVM1SI [ (reg:SI 0 zero) ] UNSPEC_VUNDEF) ] UNSPEC_REDUC)) 15948 {pred_redxorv32si} In this case, record_use is trying to check partial_subreg_p (use->mode (), mode) for RTX = (reg:V32SI 96 v0 [orig:185 vect__96.40 ] [185]). use->mode () == V32SImode, wheras mode = RVVM1SImode. Then it ICE since they are !ordered_p. In this situation, the use mode for such use should keep the original mode (V32SI), no need to compare VLSmode and VLAmode which one is bigger. I am still trying to find a way to walk around this issue in RISC-V backend. Is this patch fix ok for the trunk ? If not, could you give me a suggestion to walk around this ICE in RISC-V backend. Thanks. gcc/ChangeLog: * rtl-ssa/insns.cc (function_info::record_use): Add ordered_p. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/vsetvl/avl_use_bug-2.c: New test. --- gcc/rtl-ssa/insns.cc | 2 ++ .../riscv/rvv/vsetvl/avl_use_bug-2.c | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vsetvl/avl_use_bug-2.c diff --git a/gcc/rtl-ssa/insns.cc b/gcc/rtl-ssa/insns.cc index 2fa48e0dacd..5b9c5baf8c7 100644 --- a/gcc/rtl-ssa/insns.cc +++ b/gcc/rtl-ssa/insns.cc @@ -521,6 +521,8 @@ function_info::record_use (build_info &bi, insn_info *insn, // different but equal-sized modes. gcc_checking_assert (use->insn () == insn); if (HARD_REGISTER_NUM_P (regno) + && ordered_p (GET_MODE_PRECISION (use->mode ()), + GET_MODE_PRECISION (mode)) && partial_subreg_p (use->mode (), mode)) use->set_mode (mode); use->record_reference (ref, false); diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/avl_use_bug-2.c b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/avl_use_bug-2.c new file mode 100644 index 00000000000..bbc02eab818 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/avl_use_bug-2.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64d --param=riscv-autovec-lmul=m4 -O3 -fomit-frame-pointer -funroll-loops" } */ + +int safe_lshift_func_int32_t_s_s_left, safe_lshift_func_int32_t_s_s_right, + safe_sub_func_uint64_t_u_u_ui2, safe_mul_func_uint64_t_u_u_ui2, g_79_2, + g_97_l_439; +void g_97(int * __restrict l_437) +{ + for (; g_97_l_439; g_97_l_439 += 1) + for (char l_502 = 0; l_502 < 4; l_502++) + { + int __trans_tmp_14 = ((safe_lshift_func_int32_t_s_s_right >= 2 + || safe_lshift_func_int32_t_s_s_left) + ? 1 : safe_lshift_func_int32_t_s_s_right); + long __trans_tmp_15 = __trans_tmp_14 * safe_mul_func_uint64_t_u_u_ui2; + unsigned short __trans_tmp_16 = -__trans_tmp_15; + int __trans_tmp_7 + = (__trans_tmp_16 ^ 65535UL) - safe_sub_func_uint64_t_u_u_ui2; + *l_437 ^= (short)(__trans_tmp_7 ^ g_79_2); + } +} -- 2.36.3