tcg/riscv/tcg-target.c.inc | 10 +++++++--- tcg/riscv/tcg-target.h | 1 + 2 files changed, 8 insertions(+), 3 deletions(-)
From: Zhijin Zeng <zengzhijin@linux.spacemit.com>
The RISC-V target currently uses register t6 as the destination for vsetvli and
vsetvl instructions to capture the resulting vector length (vl).
However, in the tcg_out_dupm_vec function, t6 is also used as a temporary
register. Since tcg_out_dup_vec may emit a vsetvli or vsetvl instruction
internally, the value previously written to t6 (e.g., by an earlier ld in
the same translation block) can be unintentionally overwritten.
This patch reserves the t3 register to be used as the destination for vsetvli
and vsetvl instructions.
Signed-off-by: Zhijin Zeng <zengzhijin@linux.spacemit.com>
---
tcg/riscv/tcg-target.c.inc | 10 +++++++---
tcg/riscv/tcg-target.h | 1 +
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 31b9f7d87a..359021aa76 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -3022,10 +3022,12 @@ static void probe_frac_lmul_1(TCGType type, MemOp vsew)
p->vset_insn = encode_vseti(OPC_VSETIVLI, TCG_REG_ZERO, avl, vtype);
} else if (lmul_eq_avl) {
/* rd != 0 and rs1 == 0 uses vlmax */
- p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_TMP0, TCG_REG_ZERO, vtype);
+ p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_TMP3, TCG_REG_ZERO,
+ vtype);
} else {
- p->movi_insn = encode_i(OPC_ADDI, TCG_REG_TMP0, TCG_REG_ZERO, avl);
- p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_ZERO, TCG_REG_TMP0, vtype);
+ p->movi_insn = encode_i(OPC_ADDI, TCG_REG_TMP3, TCG_REG_ZERO, avl);
+ p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_ZERO, TCG_REG_TMP3,
+ vtype);
}
}
@@ -3070,6 +3072,8 @@ static void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP);
if (cpuinfo & CPUINFO_ZVE64X) {
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP3);
+
switch (riscv_lg2_vlenb) {
case TCG_TYPE_V64:
tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
index 6dc77d944b..0f2dced8e2 100644
--- a/tcg/riscv/tcg-target.h
+++ b/tcg/riscv/tcg-target.h
@@ -55,6 +55,7 @@ typedef enum {
TCG_REG_TMP0 = TCG_REG_T6,
TCG_REG_TMP1 = TCG_REG_T5,
TCG_REG_TMP2 = TCG_REG_T4,
+ TCG_REG_TMP3 = TCG_REG_T3,
} TCGReg;
#define TCG_REG_ZERO TCG_REG_ZERO
--
2.43.0
On 12/29/25 19:47, zengzhijin@linux.spacemit.com wrote: > From: Zhijin Zeng <zengzhijin@linux.spacemit.com> > > The RISC-V target currently uses register t6 as the destination for vsetvli and > vsetvl instructions to capture the resulting vector length (vl). > > However, in the tcg_out_dupm_vec function, t6 is also used as a temporary > register. Since tcg_out_dup_vec may emit a vsetvli or vsetvl instruction > internally, the value previously written to t6 (e.g., by an earlier ld in > the same translation block) can be unintentionally overwritten. > > This patch reserves the t3 register to be used as the destination for vsetvli > and vsetvl instructions. > > Signed-off-by: Zhijin Zeng <zengzhijin@linux.spacemit.com> You don't need to reserve a new register. There are only two places where a tmp register is live across set_vtype: dupm and dupi. Both of those places can be changed to use TCG_REG_TMP1 instead, with a comment. r~
On 12/29/2025 4:47 PM, zengzhijin@linux.spacemit.com wrote:
> From: Zhijin Zeng <zengzhijin@linux.spacemit.com>
>
> The RISC-V target currently uses register t6 as the destination for vsetvli and
> vsetvl instructions to capture the resulting vector length (vl).
>
> However, in the tcg_out_dupm_vec function, t6 is also used as a temporary
> register. Since tcg_out_dup_vec may emit a vsetvli or vsetvl instruction
> internally, the value previously written to t6 (e.g., by an earlier ld in
> the same translation block) can be unintentionally overwritten.
>
> This patch reserves the t3 register to be used as the destination for vsetvli
> and vsetvl instructions.
>
> Signed-off-by: Zhijin Zeng <zengzhijin@linux.spacemit.com>
> ---
> tcg/riscv/tcg-target.c.inc | 10 +++++++---
> tcg/riscv/tcg-target.h | 1 +
> 2 files changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> index 31b9f7d87a..359021aa76 100644
> --- a/tcg/riscv/tcg-target.c.inc
> +++ b/tcg/riscv/tcg-target.c.inc
> @@ -3022,10 +3022,12 @@ static void probe_frac_lmul_1(TCGType type, MemOp vsew)
> p->vset_insn = encode_vseti(OPC_VSETIVLI, TCG_REG_ZERO, avl, vtype);
> } else if (lmul_eq_avl) {
> /* rd != 0 and rs1 == 0 uses vlmax */
> - p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_TMP0, TCG_REG_ZERO, vtype);
> + p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_TMP3, TCG_REG_ZERO,
> + vtype);
> } else {
> - p->movi_insn = encode_i(OPC_ADDI, TCG_REG_TMP0, TCG_REG_ZERO, avl);
> - p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_ZERO, TCG_REG_TMP0, vtype);
> + p->movi_insn = encode_i(OPC_ADDI, TCG_REG_TMP3, TCG_REG_ZERO, avl);
> + p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_ZERO, TCG_REG_TMP3,
> + vtype);
> }
> }
>
> @@ -3070,6 +3072,8 @@ static void tcg_target_init(TCGContext *s)
> tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP);
>
> if (cpuinfo & CPUINFO_ZVE64X) {
> + tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP3);
> +
> switch (riscv_lg2_vlenb) {
> case TCG_TYPE_V64:
> tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index 6dc77d944b..0f2dced8e2 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -55,6 +55,7 @@ typedef enum {
> TCG_REG_TMP0 = TCG_REG_T6,
> TCG_REG_TMP1 = TCG_REG_T5,
> TCG_REG_TMP2 = TCG_REG_T4,
> + TCG_REG_TMP3 = TCG_REG_T3,
> } TCGReg;
>
> #define TCG_REG_ZERO TCG_REG_ZERO
LGTM. :)
Thanks,
Chao
© 2016 - 2026 Red Hat, Inc.