[COMMITTED,V2] RTL-SSA: Fix ICE on record_use of RTL_SSA for RISC-V VSETVL PASS

Message ID 20231211121903.1864526-1-juzhe.zhong@rivai.ai
State Accepted
Headers
Series [COMMITTED,V2] RTL-SSA: Fix ICE on record_use of RTL_SSA for RISC-V VSETVL PASS |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

juzhe.zhong@rivai.ai Dec. 11, 2023, 12:19 p.m. UTC
  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                          | 11 +++++++---
 .../riscv/rvv/vsetvl/vsetvl_bug-2.c           | 21 +++++++++++++++++++
 2 files changed, 29 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vsetvl/vsetvl_bug-2.c
  

Patch

diff --git a/gcc/rtl-ssa/insns.cc b/gcc/rtl-ssa/insns.cc
index 2fa48e0dacd..a54168d5c5f 100644
--- a/gcc/rtl-ssa/insns.cc
+++ b/gcc/rtl-ssa/insns.cc
@@ -520,9 +520,14 @@  function_info::record_use (build_info &bi, insn_info *insn,
       // the instruction (unusually) references the same register in two
       // different but equal-sized modes.
       gcc_checking_assert (use->insn () == insn);
-      if (HARD_REGISTER_NUM_P (regno)
-	  && partial_subreg_p (use->mode (), mode))
-	use->set_mode (mode);
+      if (HARD_REGISTER_NUM_P (regno))
+	{
+	  if (!ordered_p (GET_MODE_PRECISION (use->mode ()),
+			  GET_MODE_PRECISION (mode)))
+	    use->set_mode (reg_raw_mode[regno]);
+	  else if (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/vsetvl_bug-2.c b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/vsetvl_bug-2.c
new file mode 100644
index 00000000000..bbc02eab818
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/vsetvl_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);
+      }
+}