[v2] RISC-V: Fix ICE for unrecognizable insn `UNSPEC_VSETVL` for XTheadVector

Message ID 20241203063405.1235-1-jinma@linux.alibaba.com
State Superseded
Delegated to: Jeff Law
Headers
Series [v2] RISC-V: Fix ICE for unrecognizable insn `UNSPEC_VSETVL` for XTheadVector |

Checks

Context Check Description
rivoscibot/toolchain-ci-rivos-lint success Lint passed
rivoscibot/toolchain-ci-rivos-apply-patch success Patch applied
rivoscibot/toolchain-ci-rivos-build--newlib-rv64gcv-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv64gc_zba_zbb_zbc_zbs-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv64gcv-lp64d-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--newlib-rv64gc-lp64d-non-multilib success Build passed
rivoscibot/toolchain-ci-rivos-build--linux-rv64gc-lp64d-non-multilib success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
rivoscibot/toolchain-ci-rivos-test success Testing passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed

Commit Message

Jin Ma Dec. 3, 2024, 6:34 a.m. UTC
  Since XTheadvector does not support vsetivli, vl needs to be put into
registers during the expand phase.

	PR 116593

gcc/ChangeLog:

	* config/riscv/riscv-vector-builtins.cc (function_expander::add_input_operand):
	Put const to GPR for vl.
	* config/riscv/thead-vector.md (@th_pred_vl_mov<mode>): New.

gcc/testsuite/ChangeLog:

	* g++.target/riscv/xtheadvector/pr116593.C: New test.
	* g++.target/riscv/xtheadvector/xtheadvector.exp: New test.

Reported-by: nihui <shuizhuyuanluo@gmail.com>
---
 gcc/config/riscv/riscv-vector-builtins.cc     | 18 +++++++-
 gcc/config/riscv/thead-vector.md              | 13 ++++++
 .../g++.target/riscv/xtheadvector/pr116593.C  | 45 +++++++++++++++++++
 .../riscv/xtheadvector/xtheadvector.exp       | 37 +++++++++++++++
 4 files changed, 112 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.target/riscv/xtheadvector/pr116593.C
 create mode 100644 gcc/testsuite/g++.target/riscv/xtheadvector/xtheadvector.exp
  

Comments

Jeff Law Dec. 15, 2024, 12:33 a.m. UTC | #1
On 12/2/24 11:34 PM, Jin Ma wrote:
> Since XTheadvector does not support vsetivli, vl needs to be put into
> registers during the expand phase.
> 
> 	PR 116593
> 
> gcc/ChangeLog:
> 
> 	* config/riscv/riscv-vector-builtins.cc (function_expander::add_input_operand):
> 	Put const to GPR for vl.
> 	* config/riscv/thead-vector.md (@th_pred_vl_mov<mode>): New.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.target/riscv/xtheadvector/pr116593.C: New test.
> 	* g++.target/riscv/xtheadvector/xtheadvector.exp: New test.
> 
> Reported-by: nihui <shuizhuyuanluo@gmail.com>
> ---
>   gcc/config/riscv/riscv-vector-builtins.cc     | 18 +++++++-
>   gcc/config/riscv/thead-vector.md              | 13 ++++++
>   .../g++.target/riscv/xtheadvector/pr116593.C  | 45 +++++++++++++++++++
>   .../riscv/xtheadvector/xtheadvector.exp       | 37 +++++++++++++++
>   4 files changed, 112 insertions(+), 1 deletion(-)
>   create mode 100644 gcc/testsuite/g++.target/riscv/xtheadvector/pr116593.C
>   create mode 100644 gcc/testsuite/g++.target/riscv/xtheadvector/xtheadvector.exp
> 
> diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
> index b9b9d33adab6..cced0461a7bb 100644
> --- a/gcc/config/riscv/riscv-vector-builtins.cc
> +++ b/gcc/config/riscv/riscv-vector-builtins.cc
> @@ -4089,7 +4089,23 @@ function_expander::add_input_operand (unsigned argno)
>   {
>     tree arg = CALL_EXPR_ARG (exp, argno);
>     rtx x = expand_normal (arg);
> -  add_input_operand (TYPE_MODE (TREE_TYPE (arg)), x);
> +
> +  /* Since the parameter vl of XTheadVector does not support
> +     immediate numbers, we need to put it in the register
> +     in advance.  */
> +  if (TARGET_XTHEADVECTOR
> +      && CONST_INT_P (x)
> +      && base->apply_vl_p ()
> +      && argno == (unsigned) (call_expr_nargs (exp) - 1)
> +      && x != CONST0_RTX (GET_MODE (x)))
> +    {
> +      rtx tmp = gen_reg_rtx (word_mode);
> +      /* Use UNSPEC to avoid being optimized before vsetvl pass.  */
> +      emit_insn (gen_th_pred_vl_mov (word_mode, tmp, x));
> +      add_input_operand (TYPE_MODE (TREE_TYPE (arg)), tmp);
> +    }
> +  else
> +    add_input_operand (TYPE_MODE (TREE_TYPE (arg)), x);
>   }
So I would just do:


tmp = force_reg (word_mode, x);
add_input_operand (TYPE_MODE (TREE_TYPE (arg)), tmp);

In the thead specific code.  That generates the initial code correctly. 
At that point we just need to make sure nothing like combine, cprop, etc 
propagates the constant into the vsetvl.  The way to prevent that is 
with the operand predicates on the vsetvl insns.


jeff
  
Jin Ma Dec. 17, 2024, 6:35 a.m. UTC | #2
> So I would just do:
> 
> 
> tmp = force_reg (word_mode, x);
> add_input_operand (TYPE_MODE (TREE_TYPE (arg)), tmp);
> 
> In the thead specific code. That generates the initial code correctly.
> At that point we just need to make sure nothing like combine, cprop, etc
> propagates the constant into the vsetvl. The way to prevent that is
> with the operand predicates on the vsetvl insns.
>
> jeff
Thank you so much for your patient guidance. I understand what you mean and
will update the patch accordingly :)
BR
Jin
  
Jin Ma Dec. 17, 2024, 12:05 p.m. UTC | #3
> > --- a/gcc/config/riscv/riscv-vector-builtins.cc
> > +++ b/gcc/config/riscv/riscv-vector-builtins.cc
> > @@ -4089,7 +4089,23 @@ function_expander::add_input_operand (unsigned argno)
> >   {
> >     tree arg = CALL_EXPR_ARG (exp, argno);
> >     rtx x = expand_normal (arg);
> > -  add_input_operand (TYPE_MODE (TREE_TYPE (arg)), x);
> > +
> > +  /* Since the parameter vl of XTheadVector does not support
> > +     immediate numbers, we need to put it in the register
> > +     in advance.  */
> > +  if (TARGET_XTHEADVECTOR
> > +      && CONST_INT_P (x)
> > +      && base->apply_vl_p ()
> > +      && argno == (unsigned) (call_expr_nargs (exp) - 1)
> > +      && x != CONST0_RTX (GET_MODE (x)))
> > +    {
> > +      rtx tmp = gen_reg_rtx (word_mode);
> > +      /* Use UNSPEC to avoid being optimized before vsetvl pass.  */
> > +      emit_insn (gen_th_pred_vl_mov (word_mode, tmp, x));
> > +      add_input_operand (TYPE_MODE (TREE_TYPE (arg)), tmp);
> > +    }
> > +  else
> > +    add_input_operand (TYPE_MODE (TREE_TYPE (arg)), x);
> >   }
> So I would just do:
> 
> 
> tmp = force_reg (word_mode, x);
> add_input_operand (TYPE_MODE (TREE_TYPE (arg)), tmp);
> 
> In the thead specific code.  That generates the initial code correctly. 
> At that point we just need to make sure nothing like combine, cprop, etc 
> propagates the constant into the vsetvl.  The way to prevent that is 
> with the operand predicates on the vsetvl insns.
> 
> 
> jeff

Hi, jeff

I missed some information because of the long time.

As I said before, instead of using UNSPEC, In the curr_insn_transform function, the insn is transformed from:
(insn 69 67 225 12 (set (mem:RVVM8SF (reg/f:DI 218 [ _77 ]) [0  S[128, 128] A32])
        (if_then_else:RVVM8SF (unspec:RVVMF4BI [
                    (const_vector:RVVMF4BI repeat [
                            (const_int 1 [0x1])
                        ])
                    (reg:DI 209)
                    (const_int 0 [0])
                    (reg:SI 66 vl)
                    (reg:SI 67 vtype)
                ] UNSPEC_VPREDICATE)
            (reg/v:RVVM8SF 143 [ _xx ])
            (mem:RVVM8SF (reg/f:DI 218 [ _77 ]) [0  S[128, 128] A32]))) "pr116593.C":14:24 discrim 1 3883 {pred_storervvm8sf}
     (expr_list:REG_DEAD (reg/v:RVVM8SF 143 [ _xx ])
        (nil)))
to
(insn 69 284 225 11 (set (mem:RVVM8SF (reg/f:DI 18 s2 [orig:218 _77 ] [218]) [0  S[128, 128] A32])
        (if_then_else:RVVM8SF (unspec:RVVMF4BI [
                    (const_vector:RVVMF4BI repeat [
                            (const_int 1 [0x1])
                        ])
                    (const_int 1 [0x1])
                    (const_int 0 [0])
                    (reg:SI 66 vl)
                    (reg:SI 67 vtype)
                ] UNSPEC_VPREDICATE)
            (reg/v:RVVM8SF 104 v8 [orig:143 _xx ] [143])
            (mem:RVVM8SF (reg/f:DI 18 s2 [orig:218 _77 ] [218]) [0  S[128, 128] A32]))) "pr116593.C":14:24 discrim 1 3883 {pred_storervvm8sf}
     (nil))

Looking at the log for the reload pass, it is found that "Changing pseudo 209 in operand 3 of insn 69 on equiv 0x 1".
It converts the vl operand in insn from the expected register(reg:DI 209) to the constant 1(const_int 1 [0x1]).

This conversion occurs because, although the predicate for the vl operand is restricted by "vector_length_operand" in the pattern, 
the constraint is still "rK", which allows the transformation.

The issue is that changing the "rK" constraint to "rJ" for the constraint of vl operand in the pattern would prevent this conversion,
But unfortunately this will conflict with RVV (RISC-V Vector Extension).

This is why I initially considered using UNSPEC to address the XTheadVector problem while minimizing interference with RVV.

I'm not sure if there is a better way, do you have any suggestions?

BR
Jin
  
Robin Dapp Dec. 17, 2024, 12:26 p.m. UTC | #4
> Looking at the log for the reload pass, it is found that "Changing pseudo 209
> in operand 3 of insn 69 on equiv 0x 1". It converts the vl operand in insn
> from the expected register(reg:DI 209) to the constant 1(const_int 1 [0x1]).
>
> This conversion occurs because, although the predicate for the vl operand is
> restricted by "vector_length_operand" in the pattern, the constraint is still
> "rK", which allows the transformation.
>
> The issue is that changing the "rK" constraint to "rJ" for the constraint of
> vl operand in the pattern would prevent this conversion, But unfortunately
> this will conflict with RVV (RISC-V Vector Extension).
>
> This is why I initially considered using UNSPEC to address the XTheadVector
> problem while minimizing interference with RVV.
>
> I'm not sure if there is a better way, do you have any suggestions?

We'd probably need to disable the alternatives via the "spec_restriction"
attribute as we do for the fma ops.
  
Jeff Law Dec. 17, 2024, 4:24 p.m. UTC | #5
On 12/17/24 5:05 AM, Jin Ma wrote:

> 
> I missed some information because of the long time.
Happens to me all the time ;-)


> 
> As I said before, instead of using UNSPEC, In the curr_insn_transform function, the insn is transformed from:
> (insn 69 67 225 12 (set (mem:RVVM8SF (reg/f:DI 218 [ _77 ]) [0  S[128, 128] A32])
>          (if_then_else:RVVM8SF (unspec:RVVMF4BI [
>                      (const_vector:RVVMF4BI repeat [
>                              (const_int 1 [0x1])
>                          ])
>                      (reg:DI 209)
>                      (const_int 0 [0])
>                      (reg:SI 66 vl)
>                      (reg:SI 67 vtype)
>                  ] UNSPEC_VPREDICATE)
>              (reg/v:RVVM8SF 143 [ _xx ])
>              (mem:RVVM8SF (reg/f:DI 218 [ _77 ]) [0  S[128, 128] A32]))) "pr116593.C":14:24 discrim 1 3883 {pred_storervvm8sf}
>       (expr_list:REG_DEAD (reg/v:RVVM8SF 143 [ _xx ])
>          (nil)))
> to
> (insn 69 284 225 11 (set (mem:RVVM8SF (reg/f:DI 18 s2 [orig:218 _77 ] [218]) [0  S[128, 128] A32])
>          (if_then_else:RVVM8SF (unspec:RVVMF4BI [
>                      (const_vector:RVVMF4BI repeat [
>                              (const_int 1 [0x1])
>                          ])
>                      (const_int 1 [0x1])
>                      (const_int 0 [0])
>                      (reg:SI 66 vl)
>                      (reg:SI 67 vtype)
>                  ] UNSPEC_VPREDICATE)
>              (reg/v:RVVM8SF 104 v8 [orig:143 _xx ] [143])
>              (mem:RVVM8SF (reg/f:DI 18 s2 [orig:218 _77 ] [218]) [0  S[128, 128] A32]))) "pr116593.C":14:24 discrim 1 3883 {pred_storervvm8sf}
>       (nil))
> 
> Looking at the log for the reload pass, it is found that "Changing pseudo 209 in operand 3 of insn 69 on equiv 0x 1".
> It converts the vl operand in insn from the expected register(reg:DI 209) to the constant 1(const_int 1 [0x1]).
OK.  This is where we need to focus.

> 
> This conversion occurs because, although the predicate for the vl operand is restricted by "vector_length_operand" in the pattern,
> the constraint is still "rK", which allows the transformation.
That's a bit odd, I would have expected the predicate to be checked, but 
sometimes things are "odd" in reload.

> 
> The issue is that changing the "rK" constraint to "rJ" for the constraint of vl operand in the pattern would prevent this conversion,
> But unfortunately this will conflict with RVV (RISC-V Vector Extension).
> 
> This is why I initially considered using UNSPEC to address the XTheadVector problem while minimizing interference with RVV.
> 
> I'm not sure if there is a better way, do you have any suggestions?
I think Robin mentioned disabling certain alternatives which is one 
approach (I've never used that capability, but I know it exists and this 
would be a pretty good fit).  For this approach I'd suggest disabling 
the rK alternative for thead-vector and (if we don't have it) adding an 
alternative that only accepts a register.

We could also create a new constraint that mostly behaves like rK, but 
rejects (const_int 1) when thead-vector is enabled and use that in the 
vsetvl pattern instead of rK.

The brute force, but least favorite, approach would be to create two 
distinct patterns, one for thead the other for rvv.  Obviously the thead 
pattern would use different constraints to prevent replacing registers 
with constants.

Jeff

Jeff
  
Jin Ma Jan. 13, 2025, 5:56 a.m. UTC | #6
> > Looking at the log for the reload pass, it is found that "Changing pseudo 209
> > in operand 3 of insn 69 on equiv 0x 1". It converts the vl operand in insn
> > from the expected register(reg:DI 209) to the constant 1(const_int 1 [0x1]).
> >
> > This conversion occurs because, although the predicate for the vl operand is
> > restricted by "vector_length_operand" in the pattern, the constraint is still
> > "rK", which allows the transformation.
> >
> > The issue is that changing the "rK" constraint to "rJ" for the constraint of
> > vl operand in the pattern would prevent this conversion, But unfortunately
> > this will conflict with RVV (RISC-V Vector Extension).
> >
> > This is why I initially considered using UNSPEC to address the XTheadVector
> > problem while minimizing interference with RVV.
> >
> > I'm not sure if there is a better way, do you have any suggestions?
> 
> We'd probably need to disable the alternatives via the "spec_restriction"
> attribute as we do for the fma ops.

Hi, Robin
Thank you very much for your professional reply. I am trying to solve the problem
using the "spec_restriction" way. But unfortunately, I have a new problem. As
pattern below, how can I enable "r" and disable "K" when XTheadVector? "rK" already
seems to be the smallest unit and not able to be
controlled separately using spec_restriction?

(define_insn "@pred_madc<mode>"
  [(set (match_operand:<VM> 0 "register_operand"         "=vr, &vr, &vr")
	(unspec:<VM>
	   [(plus:VI
	     (match_operand:VI 1 "register_operand"     "  %0,  vr,  vr")
	     (match_operand:VI 2 "vector_arith_operand" "vrvi,  vr,  vi"))
	    (match_operand:<VM> 3 "register_operand"    "  vm,  vm,  vm")
	    (unspec:<VM>
	      [(match_operand 4 "vector_length_operand" "  rK,  rK,  rK")
	       (match_operand 5 "const_int_operand"     "   i,   i,   i")
	       (reg:SI VL_REGNUM)
	       (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMADC))]
  "TARGET_VECTOR"
  "vmadc.v%o2m\t%0,%1,%v2,%3"
  [(set_attr "type" "vicalu")
   (set_attr "mode" "<MODE>")
   (set_attr "vl_op_idx" "4")
   (set (attr "avl_type_idx") (const_int 5))
   (set_attr "spec_restriction" "thv,none,none")])
  
BR
Jin

> --
> Regards
> Robin
>
  
Robin Dapp Jan. 13, 2025, 8:20 a.m. UTC | #7
> Thank you very much for your professional reply. I am trying to solve the problem
> using the "spec_restriction" way. But unfortunately, I have a new problem. As
> pattern below, how can I enable "r" and disable "K" when XTheadVector? "rK" already
> seems to be the smallest unit and not able to be
> controlled separately using spec_restriction?
>
> (define_insn "@pred_madc<mode>"
>   [(set (match_operand:<VM> 0 "register_operand"         "=vr, &vr, &vr")
> 	(unspec:<VM>
> 	   [(plus:VI
> 	     (match_operand:VI 1 "register_operand"     "  %0,  vr,  vr")
> 	     (match_operand:VI 2 "vector_arith_operand" "vrvi,  vr,  vi"))
> 	    (match_operand:<VM> 3 "register_operand"    "  vm,  vm,  vm")
> 	    (unspec:<VM>
> 	      [(match_operand 4 "vector_length_operand" "  rK,  rK,  rK")
> 	       (match_operand 5 "const_int_operand"     "   i,   i,   i")
> 	       (reg:SI VL_REGNUM)
> 	       (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMADC))]
>   "TARGET_VECTOR"
>   "vmadc.v%o2m\t%0,%1,%v2,%3"
>   [(set_attr "type" "vicalu")
>    (set_attr "mode" "<MODE>")
>    (set_attr "vl_op_idx" "4")
>    (set (attr "avl_type_idx") (const_int 5))
>    (set_attr "spec_restriction" "thv,none,none")])

"rK" can be split up further into "r" and "K" so I'd say you
need to adjust (and split) the alternatives accordingly.  The new "r"
alternative would have spec_restriction "none" and the "K" alternative "rvv".
  
Jin Ma Jan. 13, 2025, 8:41 a.m. UTC | #8
> > Thank you very much for your professional reply. I am trying to solve the problem
> > using the "spec_restriction" way. But unfortunately, I have a new problem. As
> > pattern below, how can I enable "r" and disable "K" when XTheadVector? "rK" already
> > seems to be the smallest unit and not able to be
> > controlled separately using spec_restriction?
> >
> > (define_insn "@pred_madc<mode>"
> >   [(set (match_operand:<VM> 0 "register_operand"         "=vr, &vr, &vr")
> >  (unspec:<VM>
> >     [(plus:VI
> >       (match_operand:VI 1 "register_operand"     "  %0,  vr,  vr")
> >       (match_operand:VI 2 "vector_arith_operand" "vrvi,  vr,  vi"))
> >      (match_operand:<VM> 3 "register_operand"    "  vm,  vm,  vm")
> >      (unspec:<VM>
> >        [(match_operand 4 "vector_length_operand" "  rK,  rK,  rK")
> >         (match_operand 5 "const_int_operand"     "   i,   i,   i")
> >         (reg:SI VL_REGNUM)
> >         (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMADC))]
> >   "TARGET_VECTOR"
> >   "vmadc.v%o2m\t%0,%1,%v2,%3"
> >   [(set_attr "type" "vicalu")
> >    (set_attr "mode" "<MODE>")
> >    (set_attr "vl_op_idx" "4")
> >    (set (attr "avl_type_idx") (const_int 5))
> >    (set_attr "spec_restriction" "thv,none,none")])
> 
> "rK" can be split up further into "r" and "K" so I'd say you
> need to adjust (and split) the alternatives accordingly.  The new "r"
> alternative would have spec_restriction "none" and the "K" alternative "rvv".

Yes. This will solve the problem, but it will lead to very large-scale changes
(splitting each rK, adding 1 column constraint), and make the pattern more complex
and more difficult to maintain. In contrast, how about replacing "rK" with a new
constrain in the way jeff mentioned? For example, "Vvl".

Jeff: We could also create a new constraint that mostly behaves like rK, but 
rejects (const_int 1) when thead-vector is enabled and use that in the 
vsetvl pattern instead of rK. ( https://gcc.gnu.org/pipermail/gcc-patches/2024-December/671836.html )

BR
Jin

> -- 
> Regards
>  Robin
  
Robin Dapp Jan. 13, 2025, 4:38 p.m. UTC | #9
> Yes. This will solve the problem, but it will lead to very large-scale changes
> (splitting each rK, adding 1 column constraint), and make the pattern more complex
> and more difficult to maintain. In contrast, how about replacing "rK" with a new
> constrain in the way jeff mentioned? For example, "Vvl".

> Jeff: We could also create a new constraint that mostly behaves like rK, but 
> rejects (const_int 1) when thead-vector is enabled and use that in the 
> vsetvl pattern instead of rK. ( https://gcc.gnu.org/pipermail/gcc-patches/2024-December/671836.html )

If you need to change every rK, then yeah, spec_restriction seem reasonable and
a new constraint seems better.
  
Jeff Law Jan. 13, 2025, 5:04 p.m. UTC | #10
On 1/13/25 1:41 AM, Jin Ma wrote:
>>> Thank you very much for your professional reply. I am trying to solve the problem
>>> using the "spec_restriction" way. But unfortunately, I have a new problem. As
>>> pattern below, how can I enable "r" and disable "K" when XTheadVector? "rK" already
>>> seems to be the smallest unit and not able to be
>>> controlled separately using spec_restriction?
>>>
>>> (define_insn "@pred_madc<mode>"
>>>    [(set (match_operand:<VM> 0 "register_operand"         "=vr, &vr, &vr")
>>>   (unspec:<VM>
>>>      [(plus:VI
>>>        (match_operand:VI 1 "register_operand"     "  %0,  vr,  vr")
>>>        (match_operand:VI 2 "vector_arith_operand" "vrvi,  vr,  vi"))
>>>       (match_operand:<VM> 3 "register_operand"    "  vm,  vm,  vm")
>>>       (unspec:<VM>
>>>         [(match_operand 4 "vector_length_operand" "  rK,  rK,  rK")
>>>          (match_operand 5 "const_int_operand"     "   i,   i,   i")
>>>          (reg:SI VL_REGNUM)
>>>          (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMADC))]
>>>    "TARGET_VECTOR"
>>>    "vmadc.v%o2m\t%0,%1,%v2,%3"
>>>    [(set_attr "type" "vicalu")
>>>     (set_attr "mode" "<MODE>")
>>>     (set_attr "vl_op_idx" "4")
>>>     (set (attr "avl_type_idx") (const_int 5))
>>>     (set_attr "spec_restriction" "thv,none,none")])
>>
>> "rK" can be split up further into "r" and "K" so I'd say you
>> need to adjust (and split) the alternatives accordingly.  The new "r"
>> alternative would have spec_restriction "none" and the "K" alternative "rvv".
> 
> Yes. This will solve the problem, but it will lead to very large-scale changes
> (splitting each rK, adding 1 column constraint), and make the pattern more complex
> and more difficult to maintain. In contrast, how about replacing "rK" with a new
> constrain in the way jeff mentioned? For example, "Vvl".
> 
> Jeff: We could also create a new constraint that mostly behaves like rK, but
> rejects (const_int 1) when thead-vector is enabled and use that in the
> vsetvl pattern instead of rK. ( https://gcc.gnu.org/pipermail/gcc-patches/2024-December/671836.html )
I think both roughly end up being the same amount of work.  I'm not too 
worried about the extra alternatives and such, risc-v is pretty 
reasonable in that regard if you compare it to some other ports.

Both ultimately end up forcing us to adjust the constraints on every 
affected pattern.  I think that's unavoidable.

jeff
  

Patch

diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
index b9b9d33adab6..cced0461a7bb 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -4089,7 +4089,23 @@  function_expander::add_input_operand (unsigned argno)
 {
   tree arg = CALL_EXPR_ARG (exp, argno);
   rtx x = expand_normal (arg);
-  add_input_operand (TYPE_MODE (TREE_TYPE (arg)), x);
+
+  /* Since the parameter vl of XTheadVector does not support
+     immediate numbers, we need to put it in the register
+     in advance.  */
+  if (TARGET_XTHEADVECTOR
+      && CONST_INT_P (x)
+      && base->apply_vl_p ()
+      && argno == (unsigned) (call_expr_nargs (exp) - 1)
+      && x != CONST0_RTX (GET_MODE (x)))
+    {
+      rtx tmp = gen_reg_rtx (word_mode);
+      /* Use UNSPEC to avoid being optimized before vsetvl pass.  */
+      emit_insn (gen_th_pred_vl_mov (word_mode, tmp, x));
+      add_input_operand (TYPE_MODE (TREE_TYPE (arg)), tmp);
+    }
+  else
+    add_input_operand (TYPE_MODE (TREE_TYPE (arg)), x);
 }
 
 /* Since we may normalize vop/vop_tu/vop_m/vop_tumu.. into a single patter.
diff --git a/gcc/config/riscv/thead-vector.md b/gcc/config/riscv/thead-vector.md
index 5fe9ba08c4eb..0e00514c6b2d 100644
--- a/gcc/config/riscv/thead-vector.md
+++ b/gcc/config/riscv/thead-vector.md
@@ -25,6 +25,7 @@  (define_c_enum "unspec" [
   UNSPEC_TH_VSUXW
 
   UNSPEC_TH_VWLDST
+  UNSPEC_TH_VL_MOV
 ])
 
 (define_int_iterator UNSPEC_TH_VLMEM_OP [
@@ -93,6 +94,18 @@  (define_int_iterator UNSPEC_TH_VSXMEM_OP [
 (define_mode_iterator V_VLS_VT [V VLS VT])
 (define_mode_iterator V_VB_VLS_VT [V VB VLS VT])
 
+(define_insn_and_split "@th_pred_vl_mov<mode>"
+  [(set (match_operand:P 0 "register_operand"    "=r")
+	(unspec:P
+	  [(match_operand:P 1 "const_int_operand" " i")]
+	UNSPEC_TH_VL_MOV))]
+  "TARGET_XTHEADVECTOR"
+  "li\t%0,%1"
+  "&& epilogue_completed"
+  [(set (match_dup 0) (match_dup 1))]
+  {}
+  [(set_attr "type" "arith")])
+
 (define_split
   [(set (match_operand:V_VB_VLS_VT 0 "reg_or_mem_operand")
 	(match_operand:V_VB_VLS_VT 1 "reg_or_mem_operand"))]
diff --git a/gcc/testsuite/g++.target/riscv/xtheadvector/pr116593.C b/gcc/testsuite/g++.target/riscv/xtheadvector/pr116593.C
new file mode 100644
index 000000000000..e44e7437ad70
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/xtheadvector/pr116593.C
@@ -0,0 +1,45 @@ 
+/* Test that we do not have ice when compile */
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zfh_xtheadvector -mabi=ilp32d -O2" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_zfh_xtheadvector -mabi=lp64d -O2" { target { rv64 } } } */
+
+#include <math.h>
+#include <riscv_vector.h>
+#include <vector>
+
+static vfloat32m8_t atan2_ps(vfloat32m8_t a, vfloat32m8_t b, size_t vl)
+{
+  std::vector<float> tmpx(vl);
+  std::vector<float> tmpy(vl);
+  __riscv_vse32_v_f32m8(tmpx.data(), a, vl);
+  __riscv_vse32_v_f32m8(tmpy.data(), b, vl);
+  for (size_t i = 0; i < vl; i++)
+  {
+    tmpx[i] = atan2(tmpx[i], tmpy[i]);
+  }
+  return __riscv_vle32_v_f32m8(tmpx.data(), vl);
+}
+
+void atan2(const float *x, const float *y, float *out, int size, int ch)
+{
+  for (int i = 0; i < ch; i++)
+  {
+    const float *xx = x + size * i;
+    const float *yy = y + size * i;
+    float *zz = out + size * i;
+
+    int n = size;
+    while (n > 0)
+    {
+      size_t vl = __riscv_vsetvl_e32m8(n);
+      vfloat32m8_t _xx = __riscv_vle32_v_f32m8(xx, vl);
+      vfloat32m8_t _yy = __riscv_vle32_v_f32m8(yy, vl);
+      vfloat32m8_t _zz = atan2_ps(_xx, _yy, vl);
+      __riscv_vse32_v_f32m8(zz, _zz, vl);
+      n -= vl;
+      xx += vl;
+      yy += vl;
+      zz += vl;
+    }
+  }
+}
diff --git a/gcc/testsuite/g++.target/riscv/xtheadvector/xtheadvector.exp b/gcc/testsuite/g++.target/riscv/xtheadvector/xtheadvector.exp
new file mode 100644
index 000000000000..551fd9c92670
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/xtheadvector/xtheadvector.exp
@@ -0,0 +1,37 @@ 
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Test the front-end for C++.
+# We don't need to test back-end code-gen in RV32 system for C++
+# Because it is already tested in C.
+# Exit immediately if this isn't a RISC-V target.
+if ![istarget riscv*-*-*] then {
+  return
+}
+
+# Load support procs.
+load_lib g++-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] "" ""
+
+# All done.
+dg-finish