RTL-SSA: Fix ICE on record_use of RTL_SSA for RISC-V VSETVL PASS
commit0a569f87cd8436abaa6ac8c0da6e441152904e67
authorJuzhe-Zhong <juzhe.zhong@rivai.ai>
Mon, 11 Dec 2023 12:16:28 +0000 (11 20:16 +0800)
committerLehua Ding <lehua.ding@rivai.ai>
Mon, 11 Dec 2023 12:23:45 +0000 (11 20:23 +0800)
tree028a9810342c9a9ed34e8a15c00a55cfb4fddab0
parent4db744149b6ed46314107187bb25e142c729f442
RTL-SSA: Fix ICE on record_use of RTL_SSA for RISC-V VSETVL PASS

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.

Set the use mode as the biggest mode which is natural fall back mode.

gcc/ChangeLog:

* rtl-ssa/insns.cc (function_info::record_use): Add !ordered_p case.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/vsetvl/vsetvl_bug-2.c: New test.
gcc/rtl-ssa/insns.cc
gcc/testsuite/gcc.target/riscv/rvv/vsetvl/vsetvl_bug-2.c [new file with mode: 0644]