This patch split a VLS avl_type from the NONVLMAX avl_type, denoting those RVV insn with length set to the number of units of VLS modes.
gcc/ChangeLog: * config/riscv/riscv-protos.h (enum avl_type): New VLS avl_type. * config/riscv/riscv-v.cc (autovec_use_vlmax_p): Move comments. --- gcc/config/riscv/riscv-protos.h | 21 +++++++++++++++++++-- gcc/config/riscv/riscv-v.cc | 25 ++++++------------------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 07b4ffe3edf..d8372a7886f 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -368,10 +368,27 @@ enum vlmul_type NUM_LMUL = 8 }; +/* The RISC-V vsetvli pass uses "known vlmax" operations for optimization. + Whether or not an instruction actually is a vlmax operation is not + recognizable from the length operand alone but the avl_type operand + is used instead. In general, there are two cases: + + - Emit a vlmax operation by calling emit_vlmax_insn[_lra]. Here we emit + a vsetvli with vlmax configuration and set the avl_type to VLMAX for + VLA modes or VLS for VLS modes. + - Emit an operation that uses the existing (last-set) length and + set the avl_type to NONVLMAX. + + Sometimes we also need to set the VLMAX or VLS avl_type to an operation that + already uses a given length register. This can happen during or after + register allocation when we are not allowed to create a new register. + For that case we also allow to set the avl_type to VLMAX or VLS. +*/ enum avl_type { - NONVLMAX, - VLMAX, + NONVLMAX = 0, + VLMAX = 1, + VLS = 2, }; /* Routines implemented in riscv-vector-builtins.cc. */ void init_builtins (void); diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index f63dec573ef..e8266218394 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -284,6 +284,7 @@ public: /* Add vl operand. */ rtx len = m_vl_op; + bool vls_p = false; if (m_vlmax_p) { if (riscv_v_ext_vls_mode_p (vtype_mode)) @@ -294,7 +295,7 @@ public: len = gen_int_mode (nunits, Pmode); if (!satisfies_constraint_K (len)) len = force_reg (Pmode, len); - m_vlmax_p = false; + vls_p = true; } else if (const_vlmax_p (vtype_mode)) { @@ -302,7 +303,7 @@ public: the vsetvli to obtain the value of vlmax. */ poly_uint64 nunits = GET_MODE_NUNITS (vtype_mode); len = gen_int_mode (nunits, Pmode); - m_vlmax_p = false; + vls_p = true; } else if (can_create_pseudo_p ()) { @@ -318,7 +319,9 @@ public: add_policy_operand (); /* Add avl_type operand. */ - add_avl_type_operand (m_vlmax_p ? avl_type::VLMAX : avl_type::NONVLMAX); + add_avl_type_operand ( + vls_p ? avl_type::VLS + : (m_vlmax_p ? avl_type::VLMAX : avl_type::NONVLMAX)); /* Add rounding mode operand. */ if (m_insn_flags & FRM_DYN_P) @@ -769,22 +772,6 @@ autovec_use_vlmax_p (void) || riscv_autovec_preference == RVV_FIXED_VLMAX); } -/* The RISC-V vsetvli pass uses "known vlmax" operations for optimization. - Whether or not an instruction actually is a vlmax operation is not - recognizable from the length operand alone but the avl_type operand - is used instead. In general, there are two cases: - - - Emit a vlmax operation by passing a NULL length. Here we emit - a vsetvli with vlmax configuration and set the avl_type to VLMAX. - - Emit an operation that uses the existing (last-set) length and - set the avl_type to NONVLMAX. - - Sometimes we also need to set the VLMAX avl_type to an operation that - already uses a given length register. This can happen during or after - register allocation when we are not allowed to create a new register. - For that case we also allow to set the avl_type to VLMAX. -*/ - /* This function emits VLMAX vrgather instruction. Emit vrgather.vx/vi when sel is a const duplicate vector. Otherwise, emit vrgather.vv. */ static void -- 2.36.3