The Arm MVE VDUP implementation would like to be able to emit code to duplicate a byte or halfword value into an i32. We have code to do this already in tcg-op-gvec.c, so all we need to do is make the functions global.
For consistency with other functions made available to the frontends: * we rename to tcg_gen_dup_* * we expose both the _i32 and _i64 forms * we provide the #define for a _tl form Suggested-by: Richard Henderson <richard.hender...@linaro.org> Reviewed-by: Richard Henderson <richard.hender...@linaro.org> Signed-off-by: Peter Maydell <peter.mayd...@linaro.org> Message-id: 20210617121628.20116-10-peter.mayd...@linaro.org --- include/tcg/tcg-op.h | 8 ++++++++ include/tcg/tcg.h | 1 - tcg/tcg-op-gvec.c | 20 ++++++++++---------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h index ef8a008ea74..1a2ae937583 100644 --- a/include/tcg/tcg-op.h +++ b/include/tcg/tcg-op.h @@ -338,6 +338,9 @@ void tcg_gen_umin_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2); void tcg_gen_umax_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2); void tcg_gen_abs_i32(TCGv_i32, TCGv_i32); +/* Replicate a value of size @vece from @in to all the lanes in @out */ +void tcg_gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in); + static inline void tcg_gen_discard_i32(TCGv_i32 arg) { tcg_gen_op1_i32(INDEX_op_discard, arg); @@ -534,6 +537,9 @@ void tcg_gen_umin_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2); void tcg_gen_umax_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2); void tcg_gen_abs_i64(TCGv_i64, TCGv_i64); +/* Replicate a value of size @vece from @in to all the lanes in @out */ +void tcg_gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in); + #if TCG_TARGET_REG_BITS == 64 static inline void tcg_gen_discard_i64(TCGv_i64 arg) { @@ -1127,6 +1133,7 @@ void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset, TCGType t); #define tcg_gen_atomic_smax_fetch_tl tcg_gen_atomic_smax_fetch_i64 #define tcg_gen_atomic_umax_fetch_tl tcg_gen_atomic_umax_fetch_i64 #define tcg_gen_dup_tl_vec tcg_gen_dup_i64_vec +#define tcg_gen_dup_tl tcg_gen_dup_i64 #else #define tcg_gen_movi_tl tcg_gen_movi_i32 #define tcg_gen_mov_tl tcg_gen_mov_i32 @@ -1241,6 +1248,7 @@ void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset, TCGType t); #define tcg_gen_atomic_smax_fetch_tl tcg_gen_atomic_smax_fetch_i32 #define tcg_gen_atomic_umax_fetch_tl tcg_gen_atomic_umax_fetch_i32 #define tcg_gen_dup_tl_vec tcg_gen_dup_i32_vec +#define tcg_gen_dup_tl tcg_gen_dup_i32 #endif #if UINTPTR_MAX == UINT32_MAX diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index 064dab383bc..483e1e1f24e 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -1331,7 +1331,6 @@ uint64_t dup_const(unsigned vece, uint64_t c); : (qemu_build_not_reached_always(), 0)) \ : dup_const(VECE, C)) - /* * Memory helpers that will be used by TCG generated code. */ diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c index 498a959839f..515db120cc6 100644 --- a/tcg/tcg-op-gvec.c +++ b/tcg/tcg-op-gvec.c @@ -386,7 +386,7 @@ uint64_t (dup_const)(unsigned vece, uint64_t c) } /* Duplicate IN into OUT as per VECE. */ -static void gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in) +void tcg_gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in) { switch (vece) { case MO_8: @@ -404,7 +404,7 @@ static void gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in) } } -static void gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in) +void tcg_gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in) { switch (vece) { case MO_8: @@ -578,15 +578,15 @@ static void do_dup(unsigned vece, uint32_t dofs, uint32_t oprsz, && (vece != MO_32 || !check_size_impl(oprsz, 4))) { t_64 = tcg_temp_new_i64(); tcg_gen_extu_i32_i64(t_64, in_32); - gen_dup_i64(vece, t_64, t_64); + tcg_gen_dup_i64(vece, t_64, t_64); } else { t_32 = tcg_temp_new_i32(); - gen_dup_i32(vece, t_32, in_32); + tcg_gen_dup_i32(vece, t_32, in_32); } } else if (in_64) { /* We are given a 64-bit variable input. */ t_64 = tcg_temp_new_i64(); - gen_dup_i64(vece, t_64, in_64); + tcg_gen_dup_i64(vece, t_64, in_64); } else { /* We are given a constant input. */ /* For 64-bit hosts, use 64-bit constants for "simple" constants @@ -1311,14 +1311,14 @@ void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz, } else if (g->fni8 && check_size_impl(oprsz, 8)) { TCGv_i64 t64 = tcg_temp_new_i64(); - gen_dup_i64(g->vece, t64, c); + tcg_gen_dup_i64(g->vece, t64, c); expand_2s_i64(dofs, aofs, oprsz, t64, g->scalar_first, g->fni8); tcg_temp_free_i64(t64); } else if (g->fni4 && check_size_impl(oprsz, 4)) { TCGv_i32 t32 = tcg_temp_new_i32(); tcg_gen_extrl_i64_i32(t32, c); - gen_dup_i32(g->vece, t32, t32); + tcg_gen_dup_i32(g->vece, t32, t32); expand_2s_i32(dofs, aofs, oprsz, t32, g->scalar_first, g->fni4); tcg_temp_free_i32(t32); } else { @@ -2538,7 +2538,7 @@ void tcg_gen_gvec_ands(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) { TCGv_i64 tmp = tcg_temp_new_i64(); - gen_dup_i64(vece, tmp, c); + tcg_gen_dup_i64(vece, tmp, c); tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ands); tcg_temp_free_i64(tmp); } @@ -2562,7 +2562,7 @@ void tcg_gen_gvec_xors(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) { TCGv_i64 tmp = tcg_temp_new_i64(); - gen_dup_i64(vece, tmp, c); + tcg_gen_dup_i64(vece, tmp, c); tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_xors); tcg_temp_free_i64(tmp); } @@ -2586,7 +2586,7 @@ void tcg_gen_gvec_ors(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i64 c, uint32_t oprsz, uint32_t maxsz) { TCGv_i64 tmp = tcg_temp_new_i64(); - gen_dup_i64(vece, tmp, c); + tcg_gen_dup_i64(vece, tmp, c); tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ors); tcg_temp_free_i64(tmp); } -- 2.20.1