mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 00:03:54 -06:00
target/arm: Vectorize integer comparison vs zero
These instructions are often used in glibc's string routines. They were the final uses of the 32-bit at a time neon helpers. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20200418162808.4680-1-richard.henderson@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
59ab136a9e
commit
6b375d3546
6 changed files with 278 additions and 123 deletions
|
@ -3917,6 +3917,205 @@ static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void gen_ceq0_i32(TCGv_i32 d, TCGv_i32 a)
|
||||
{
|
||||
tcg_gen_setcondi_i32(TCG_COND_EQ, d, a, 0);
|
||||
tcg_gen_neg_i32(d, d);
|
||||
}
|
||||
|
||||
static void gen_ceq0_i64(TCGv_i64 d, TCGv_i64 a)
|
||||
{
|
||||
tcg_gen_setcondi_i64(TCG_COND_EQ, d, a, 0);
|
||||
tcg_gen_neg_i64(d, d);
|
||||
}
|
||||
|
||||
static void gen_ceq0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
|
||||
{
|
||||
TCGv_vec zero = tcg_const_zeros_vec_matching(d);
|
||||
tcg_gen_cmp_vec(TCG_COND_EQ, vece, d, a, zero);
|
||||
tcg_temp_free_vec(zero);
|
||||
}
|
||||
|
||||
static const TCGOpcode vecop_list_cmp[] = {
|
||||
INDEX_op_cmp_vec, 0
|
||||
};
|
||||
|
||||
const GVecGen2 ceq0_op[4] = {
|
||||
{ .fno = gen_helper_gvec_ceq0_b,
|
||||
.fniv = gen_ceq0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_8 },
|
||||
{ .fno = gen_helper_gvec_ceq0_h,
|
||||
.fniv = gen_ceq0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_16 },
|
||||
{ .fni4 = gen_ceq0_i32,
|
||||
.fniv = gen_ceq0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_32 },
|
||||
{ .fni8 = gen_ceq0_i64,
|
||||
.fniv = gen_ceq0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.prefer_i64 = TCG_TARGET_REG_BITS == 64,
|
||||
.vece = MO_64 },
|
||||
};
|
||||
|
||||
static void gen_cle0_i32(TCGv_i32 d, TCGv_i32 a)
|
||||
{
|
||||
tcg_gen_setcondi_i32(TCG_COND_LE, d, a, 0);
|
||||
tcg_gen_neg_i32(d, d);
|
||||
}
|
||||
|
||||
static void gen_cle0_i64(TCGv_i64 d, TCGv_i64 a)
|
||||
{
|
||||
tcg_gen_setcondi_i64(TCG_COND_LE, d, a, 0);
|
||||
tcg_gen_neg_i64(d, d);
|
||||
}
|
||||
|
||||
static void gen_cle0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
|
||||
{
|
||||
TCGv_vec zero = tcg_const_zeros_vec_matching(d);
|
||||
tcg_gen_cmp_vec(TCG_COND_LE, vece, d, a, zero);
|
||||
tcg_temp_free_vec(zero);
|
||||
}
|
||||
|
||||
const GVecGen2 cle0_op[4] = {
|
||||
{ .fno = gen_helper_gvec_cle0_b,
|
||||
.fniv = gen_cle0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_8 },
|
||||
{ .fno = gen_helper_gvec_cle0_h,
|
||||
.fniv = gen_cle0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_16 },
|
||||
{ .fni4 = gen_cle0_i32,
|
||||
.fniv = gen_cle0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_32 },
|
||||
{ .fni8 = gen_cle0_i64,
|
||||
.fniv = gen_cle0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.prefer_i64 = TCG_TARGET_REG_BITS == 64,
|
||||
.vece = MO_64 },
|
||||
};
|
||||
|
||||
static void gen_cge0_i32(TCGv_i32 d, TCGv_i32 a)
|
||||
{
|
||||
tcg_gen_setcondi_i32(TCG_COND_GE, d, a, 0);
|
||||
tcg_gen_neg_i32(d, d);
|
||||
}
|
||||
|
||||
static void gen_cge0_i64(TCGv_i64 d, TCGv_i64 a)
|
||||
{
|
||||
tcg_gen_setcondi_i64(TCG_COND_GE, d, a, 0);
|
||||
tcg_gen_neg_i64(d, d);
|
||||
}
|
||||
|
||||
static void gen_cge0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
|
||||
{
|
||||
TCGv_vec zero = tcg_const_zeros_vec_matching(d);
|
||||
tcg_gen_cmp_vec(TCG_COND_GE, vece, d, a, zero);
|
||||
tcg_temp_free_vec(zero);
|
||||
}
|
||||
|
||||
const GVecGen2 cge0_op[4] = {
|
||||
{ .fno = gen_helper_gvec_cge0_b,
|
||||
.fniv = gen_cge0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_8 },
|
||||
{ .fno = gen_helper_gvec_cge0_h,
|
||||
.fniv = gen_cge0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_16 },
|
||||
{ .fni4 = gen_cge0_i32,
|
||||
.fniv = gen_cge0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_32 },
|
||||
{ .fni8 = gen_cge0_i64,
|
||||
.fniv = gen_cge0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.prefer_i64 = TCG_TARGET_REG_BITS == 64,
|
||||
.vece = MO_64 },
|
||||
};
|
||||
|
||||
static void gen_clt0_i32(TCGv_i32 d, TCGv_i32 a)
|
||||
{
|
||||
tcg_gen_setcondi_i32(TCG_COND_LT, d, a, 0);
|
||||
tcg_gen_neg_i32(d, d);
|
||||
}
|
||||
|
||||
static void gen_clt0_i64(TCGv_i64 d, TCGv_i64 a)
|
||||
{
|
||||
tcg_gen_setcondi_i64(TCG_COND_LT, d, a, 0);
|
||||
tcg_gen_neg_i64(d, d);
|
||||
}
|
||||
|
||||
static void gen_clt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
|
||||
{
|
||||
TCGv_vec zero = tcg_const_zeros_vec_matching(d);
|
||||
tcg_gen_cmp_vec(TCG_COND_LT, vece, d, a, zero);
|
||||
tcg_temp_free_vec(zero);
|
||||
}
|
||||
|
||||
const GVecGen2 clt0_op[4] = {
|
||||
{ .fno = gen_helper_gvec_clt0_b,
|
||||
.fniv = gen_clt0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_8 },
|
||||
{ .fno = gen_helper_gvec_clt0_h,
|
||||
.fniv = gen_clt0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_16 },
|
||||
{ .fni4 = gen_clt0_i32,
|
||||
.fniv = gen_clt0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_32 },
|
||||
{ .fni8 = gen_clt0_i64,
|
||||
.fniv = gen_clt0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.prefer_i64 = TCG_TARGET_REG_BITS == 64,
|
||||
.vece = MO_64 },
|
||||
};
|
||||
|
||||
static void gen_cgt0_i32(TCGv_i32 d, TCGv_i32 a)
|
||||
{
|
||||
tcg_gen_setcondi_i32(TCG_COND_GT, d, a, 0);
|
||||
tcg_gen_neg_i32(d, d);
|
||||
}
|
||||
|
||||
static void gen_cgt0_i64(TCGv_i64 d, TCGv_i64 a)
|
||||
{
|
||||
tcg_gen_setcondi_i64(TCG_COND_GT, d, a, 0);
|
||||
tcg_gen_neg_i64(d, d);
|
||||
}
|
||||
|
||||
static void gen_cgt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
|
||||
{
|
||||
TCGv_vec zero = tcg_const_zeros_vec_matching(d);
|
||||
tcg_gen_cmp_vec(TCG_COND_GT, vece, d, a, zero);
|
||||
tcg_temp_free_vec(zero);
|
||||
}
|
||||
|
||||
const GVecGen2 cgt0_op[4] = {
|
||||
{ .fno = gen_helper_gvec_cgt0_b,
|
||||
.fniv = gen_cgt0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_8 },
|
||||
{ .fno = gen_helper_gvec_cgt0_h,
|
||||
.fniv = gen_cgt0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_16 },
|
||||
{ .fni4 = gen_cgt0_i32,
|
||||
.fniv = gen_cgt0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.vece = MO_32 },
|
||||
{ .fni8 = gen_cgt0_i64,
|
||||
.fniv = gen_cgt0_vec,
|
||||
.opt_opc = vecop_list_cmp,
|
||||
.prefer_i64 = TCG_TARGET_REG_BITS == 64,
|
||||
.vece = MO_64 },
|
||||
};
|
||||
|
||||
static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
|
||||
{
|
||||
tcg_gen_vec_sar8i_i64(a, a, shift);
|
||||
|
@ -6481,6 +6680,27 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
|||
tcg_gen_gvec_abs(size, rd_ofs, rm_ofs, vec_size, vec_size);
|
||||
break;
|
||||
|
||||
case NEON_2RM_VCEQ0:
|
||||
tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
|
||||
vec_size, &ceq0_op[size]);
|
||||
break;
|
||||
case NEON_2RM_VCGT0:
|
||||
tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
|
||||
vec_size, &cgt0_op[size]);
|
||||
break;
|
||||
case NEON_2RM_VCLE0:
|
||||
tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
|
||||
vec_size, &cle0_op[size]);
|
||||
break;
|
||||
case NEON_2RM_VCGE0:
|
||||
tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
|
||||
vec_size, &cge0_op[size]);
|
||||
break;
|
||||
case NEON_2RM_VCLT0:
|
||||
tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
|
||||
vec_size, &clt0_op[size]);
|
||||
break;
|
||||
|
||||
default:
|
||||
elementwise:
|
||||
for (pass = 0; pass < (q ? 4 : 2); pass++) {
|
||||
|
@ -6543,42 +6763,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
|||
default: abort();
|
||||
}
|
||||
break;
|
||||
case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
|
||||
tmp2 = tcg_const_i32(0);
|
||||
switch(size) {
|
||||
case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
|
||||
case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
|
||||
case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
|
||||
default: abort();
|
||||
}
|
||||
tcg_temp_free_i32(tmp2);
|
||||
if (op == NEON_2RM_VCLE0) {
|
||||
tcg_gen_not_i32(tmp, tmp);
|
||||
}
|
||||
break;
|
||||
case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
|
||||
tmp2 = tcg_const_i32(0);
|
||||
switch(size) {
|
||||
case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
|
||||
case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
|
||||
case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
|
||||
default: abort();
|
||||
}
|
||||
tcg_temp_free_i32(tmp2);
|
||||
if (op == NEON_2RM_VCLT0) {
|
||||
tcg_gen_not_i32(tmp, tmp);
|
||||
}
|
||||
break;
|
||||
case NEON_2RM_VCEQ0:
|
||||
tmp2 = tcg_const_i32(0);
|
||||
switch(size) {
|
||||
case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
|
||||
case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
|
||||
case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
|
||||
default: abort();
|
||||
}
|
||||
tcg_temp_free_i32(tmp2);
|
||||
break;
|
||||
case NEON_2RM_VCGT0_F:
|
||||
{
|
||||
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue