tcg: Merge INDEX_op_sextract_{i32,i64}

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2025-01-12 11:50:09 -08:00
parent 05a1129e23
commit fa361eefac
7 changed files with 19 additions and 46 deletions

View file

@ -458,7 +458,7 @@ Misc
* - extract *dest*, *t1*, *pos*, *len* * - extract *dest*, *t1*, *pos*, *len*
sextract_i32/i64 *dest*, *t1*, *pos*, *len* sextract *dest*, *t1*, *pos*, *len*
- | Extract a bitfield from *t1*, placing the result in *dest*. - | Extract a bitfield from *t1*, placing the result in *dest*.
| |

View file

@ -74,6 +74,7 @@ DEF(rotl, 1, 2, 0, TCG_OPF_INT)
DEF(rotr, 1, 2, 0, TCG_OPF_INT) DEF(rotr, 1, 2, 0, TCG_OPF_INT)
DEF(sar, 1, 2, 0, TCG_OPF_INT) DEF(sar, 1, 2, 0, TCG_OPF_INT)
DEF(setcond, 1, 2, 1, TCG_OPF_INT) DEF(setcond, 1, 2, 1, TCG_OPF_INT)
DEF(sextract, 1, 1, 2, TCG_OPF_INT)
DEF(shl, 1, 2, 0, TCG_OPF_INT) DEF(shl, 1, 2, 0, TCG_OPF_INT)
DEF(shr, 1, 2, 0, TCG_OPF_INT) DEF(shr, 1, 2, 0, TCG_OPF_INT)
DEF(sub, 1, 2, 0, TCG_OPF_INT) DEF(sub, 1, 2, 0, TCG_OPF_INT)
@ -90,7 +91,6 @@ DEF(st16_i32, 0, 2, 1, 0)
DEF(st_i32, 0, 2, 1, 0) DEF(st_i32, 0, 2, 1, 0)
/* shifts/rotates */ /* shifts/rotates */
DEF(deposit_i32, 1, 2, 2, 0) DEF(deposit_i32, 1, 2, 2, 0)
DEF(sextract_i32, 1, 1, 2, 0)
DEF(extract2_i32, 1, 2, 1, 0) DEF(extract2_i32, 1, 2, 1, 0)
DEF(add2_i32, 2, 4, 0, 0) DEF(add2_i32, 2, 4, 0, 0)
@ -112,7 +112,6 @@ DEF(st32_i64, 0, 2, 1, 0)
DEF(st_i64, 0, 2, 1, 0) DEF(st_i64, 0, 2, 1, 0)
/* shifts/rotates */ /* shifts/rotates */
DEF(deposit_i64, 1, 2, 2, 0) DEF(deposit_i64, 1, 2, 2, 0)
DEF(sextract_i64, 1, 1, 2, 0)
DEF(extract2_i64, 1, 2, 1, 0) DEF(extract2_i64, 1, 2, 1, 0)
/* size changing ops */ /* size changing ops */

View file

@ -2317,7 +2317,6 @@ static int fold_setcond_zmask(OptContext *ctx, TCGOp *op, bool neg)
static void fold_setcond_tst_pow2(OptContext *ctx, TCGOp *op, bool neg) static void fold_setcond_tst_pow2(OptContext *ctx, TCGOp *op, bool neg)
{ {
TCGOpcode sext_opc = 0;
TCGCond cond = op->args[3]; TCGCond cond = op->args[3];
TCGArg ret, src1, src2; TCGArg ret, src1, src2;
TCGOp *op2; TCGOp *op2;
@ -2336,27 +2335,12 @@ static void fold_setcond_tst_pow2(OptContext *ctx, TCGOp *op, bool neg)
} }
sh = ctz64(val); sh = ctz64(val);
switch (ctx->type) {
case TCG_TYPE_I32:
if (TCG_TARGET_sextract_valid(TCG_TYPE_I32, sh, 1)) {
sext_opc = INDEX_op_sextract_i32;
}
break;
case TCG_TYPE_I64:
if (TCG_TARGET_sextract_valid(TCG_TYPE_I64, sh, 1)) {
sext_opc = INDEX_op_sextract_i64;
}
break;
default:
g_assert_not_reached();
}
ret = op->args[0]; ret = op->args[0];
src1 = op->args[1]; src1 = op->args[1];
inv = cond == TCG_COND_TSTEQ; inv = cond == TCG_COND_TSTEQ;
if (sh && sext_opc && neg && !inv) { if (sh && neg && !inv && TCG_TARGET_sextract_valid(ctx->type, sh, 1)) {
op->opc = sext_opc; op->opc = INDEX_op_sextract;
op->args[1] = src1; op->args[1] = src1;
op->args[2] = sh; op->args[2] = sh;
op->args[3] = 1; op->args[3] = 1;
@ -3019,7 +3003,7 @@ void tcg_optimize(TCGContext *s)
case INDEX_op_bitsel_vec: case INDEX_op_bitsel_vec:
done = fold_bitsel_vec(&ctx, op); done = fold_bitsel_vec(&ctx, op);
break; break;
CASE_OP_32_64(sextract): case INDEX_op_sextract:
done = fold_sextract(&ctx, op); done = fold_sextract(&ctx, op);
break; break;
case INDEX_op_sub: case INDEX_op_sub:

View file

@ -1043,19 +1043,19 @@ void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg,
} }
if (TCG_TARGET_sextract_valid(TCG_TYPE_I32, ofs, len)) { if (TCG_TARGET_sextract_valid(TCG_TYPE_I32, ofs, len)) {
tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len); tcg_gen_op4ii_i32(INDEX_op_sextract, ret, arg, ofs, len);
return; return;
} }
/* Assume that sign-extension, if available, is cheaper than a shift. */ /* Assume that sign-extension, if available, is cheaper than a shift. */
if (TCG_TARGET_sextract_valid(TCG_TYPE_I32, 0, ofs + len)) { if (TCG_TARGET_sextract_valid(TCG_TYPE_I32, 0, ofs + len)) {
tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, 0, ofs + len); tcg_gen_op4ii_i32(INDEX_op_sextract, ret, arg, 0, ofs + len);
tcg_gen_sari_i32(ret, ret, ofs); tcg_gen_sari_i32(ret, ret, ofs);
return; return;
} }
if (TCG_TARGET_sextract_valid(TCG_TYPE_I32, 0, len)) { if (TCG_TARGET_sextract_valid(TCG_TYPE_I32, 0, len)) {
tcg_gen_shri_i32(ret, arg, ofs); tcg_gen_shri_i32(ret, arg, ofs);
tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, ret, 0, len); tcg_gen_op4ii_i32(INDEX_op_sextract, ret, ret, 0, len);
return; return;
} }
@ -2747,19 +2747,19 @@ void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg,
} }
if (TCG_TARGET_sextract_valid(TCG_TYPE_I64, ofs, len)) { if (TCG_TARGET_sextract_valid(TCG_TYPE_I64, ofs, len)) {
tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len); tcg_gen_op4ii_i64(INDEX_op_sextract, ret, arg, ofs, len);
return; return;
} }
/* Assume that sign-extension, if available, is cheaper than a shift. */ /* Assume that sign-extension, if available, is cheaper than a shift. */
if (TCG_TARGET_sextract_valid(TCG_TYPE_I64, 0, ofs + len)) { if (TCG_TARGET_sextract_valid(TCG_TYPE_I64, 0, ofs + len)) {
tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, 0, ofs + len); tcg_gen_op4ii_i64(INDEX_op_sextract, ret, arg, 0, ofs + len);
tcg_gen_sari_i64(ret, ret, ofs); tcg_gen_sari_i64(ret, ret, ofs);
return; return;
} }
if (TCG_TARGET_sextract_valid(TCG_TYPE_I64, 0, len)) { if (TCG_TARGET_sextract_valid(TCG_TYPE_I64, 0, len)) {
tcg_gen_shri_i64(ret, arg, ofs); tcg_gen_shri_i64(ret, arg, ofs);
tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, ret, 0, len); tcg_gen_op4ii_i64(INDEX_op_sextract, ret, ret, 0, len);
return; return;
} }

View file

@ -1111,8 +1111,7 @@ static const TCGOutOp * const all_outop[NB_OPS] = {
OUTOP(INDEX_op_rotr, TCGOutOpBinary, outop_rotr), OUTOP(INDEX_op_rotr, TCGOutOpBinary, outop_rotr),
OUTOP(INDEX_op_sar, TCGOutOpBinary, outop_sar), OUTOP(INDEX_op_sar, TCGOutOpBinary, outop_sar),
OUTOP(INDEX_op_setcond, TCGOutOpSetcond, outop_setcond), OUTOP(INDEX_op_setcond, TCGOutOpSetcond, outop_setcond),
OUTOP(INDEX_op_sextract_i32, TCGOutOpExtract, outop_sextract), OUTOP(INDEX_op_sextract, TCGOutOpExtract, outop_sextract),
OUTOP(INDEX_op_sextract_i64, TCGOutOpExtract, outop_sextract),
OUTOP(INDEX_op_shl, TCGOutOpBinary, outop_shl), OUTOP(INDEX_op_shl, TCGOutOpBinary, outop_shl),
OUTOP(INDEX_op_shr, TCGOutOpBinary, outop_shr), OUTOP(INDEX_op_shr, TCGOutOpBinary, outop_shr),
OUTOP(INDEX_op_sub, TCGOutOpSubtract, outop_sub), OUTOP(INDEX_op_sub, TCGOutOpSubtract, outop_sub),
@ -2333,6 +2332,7 @@ bool tcg_op_supported(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_negsetcond: case INDEX_op_negsetcond:
case INDEX_op_or: case INDEX_op_or:
case INDEX_op_setcond: case INDEX_op_setcond:
case INDEX_op_sextract:
case INDEX_op_xor: case INDEX_op_xor:
return has_type; return has_type;
@ -2344,7 +2344,6 @@ bool tcg_op_supported(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_st8_i32: case INDEX_op_st8_i32:
case INDEX_op_st16_i32: case INDEX_op_st16_i32:
case INDEX_op_st_i32: case INDEX_op_st_i32:
case INDEX_op_sextract_i32:
case INDEX_op_deposit_i32: case INDEX_op_deposit_i32:
return true; return true;
@ -2372,7 +2371,6 @@ bool tcg_op_supported(TCGOpcode op, TCGType type, unsigned flags)
case INDEX_op_st_i64: case INDEX_op_st_i64:
case INDEX_op_ext_i32_i64: case INDEX_op_ext_i32_i64:
case INDEX_op_extu_i32_i64: case INDEX_op_extu_i32_i64:
case INDEX_op_sextract_i64:
case INDEX_op_deposit_i64: case INDEX_op_deposit_i64:
return TCG_TARGET_REG_BITS == 64; return TCG_TARGET_REG_BITS == 64;
@ -5520,8 +5518,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
break; break;
case INDEX_op_extract: case INDEX_op_extract:
case INDEX_op_sextract_i32: case INDEX_op_sextract:
case INDEX_op_sextract_i64:
{ {
const TCGOutOpExtract *out = const TCGOutOpExtract *out =
container_of(all_outop[op->opc], TCGOutOpExtract, base); container_of(all_outop[op->opc], TCGOutOpExtract, base);

View file

@ -28,6 +28,7 @@
#define ctpop_tr glue(ctpop, TCG_TARGET_REG_BITS) #define ctpop_tr glue(ctpop, TCG_TARGET_REG_BITS)
#define extract_tr glue(extract, TCG_TARGET_REG_BITS) #define extract_tr glue(extract, TCG_TARGET_REG_BITS)
#define sextract_tr glue(sextract, TCG_TARGET_REG_BITS)
/* /*
* Enable TCI assertions only when debugging TCG (and without NDEBUG defined). * Enable TCI assertions only when debugging TCG (and without NDEBUG defined).
@ -661,9 +662,9 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
tci_args_rrbb(insn, &r0, &r1, &pos, &len); tci_args_rrbb(insn, &r0, &r1, &pos, &len);
regs[r0] = extract_tr(regs[r1], pos, len); regs[r0] = extract_tr(regs[r1], pos, len);
break; break;
case INDEX_op_sextract_i32: case INDEX_op_sextract:
tci_args_rrbb(insn, &r0, &r1, &pos, &len); tci_args_rrbb(insn, &r0, &r1, &pos, &len);
regs[r0] = sextract32(regs[r1], pos, len); regs[r0] = sextract_tr(regs[r1], pos, len);
break; break;
case INDEX_op_brcond: case INDEX_op_brcond:
tci_args_rl(insn, tb_ptr, &r0, &ptr); tci_args_rl(insn, tb_ptr, &r0, &ptr);
@ -773,10 +774,6 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len); tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len);
regs[r0] = deposit64(regs[r1], pos, len, regs[r2]); regs[r0] = deposit64(regs[r1], pos, len, regs[r2]);
break; break;
case INDEX_op_sextract_i64:
tci_args_rrbb(insn, &r0, &r1, &pos, &len);
regs[r0] = sextract64(regs[r1], pos, len);
break;
case INDEX_op_ext_i32_i64: case INDEX_op_ext_i32_i64:
tci_args_rr(insn, &r0, &r1); tci_args_rr(insn, &r0, &r1);
regs[r0] = (int32_t)regs[r1]; regs[r0] = (int32_t)regs[r1];
@ -1055,8 +1052,7 @@ int print_insn_tci(bfd_vma addr, disassemble_info *info)
break; break;
case INDEX_op_extract: case INDEX_op_extract:
case INDEX_op_sextract_i32: case INDEX_op_sextract:
case INDEX_op_sextract_i64:
tci_args_rrbb(insn, &r0, &r1, &pos, &len); tci_args_rrbb(insn, &r0, &r1, &pos, &len);
info->fprintf_func(info->stream, "%-12s %s,%s,%d,%d", info->fprintf_func(info->stream, "%-12s %s,%s,%d,%d",
op_name, str_r(r0), str_r(r1), pos, len); op_name, str_r(r0), str_r(r1), pos, len);

View file

@ -445,10 +445,7 @@ static const TCGOutOpExtract outop_extract = {
static void tcg_out_sextract(TCGContext *s, TCGType type, TCGReg rd, static void tcg_out_sextract(TCGContext *s, TCGType type, TCGReg rd,
TCGReg rs, unsigned pos, unsigned len) TCGReg rs, unsigned pos, unsigned len)
{ {
TCGOpcode opc = type == TCG_TYPE_I32 ? tcg_out_op_rrbb(s, INDEX_op_sextract, rd, rs, pos, len);
INDEX_op_sextract_i32 :
INDEX_op_sextract_i64;
tcg_out_op_rrbb(s, opc, rd, rs, pos, len);
} }
static const TCGOutOpExtract outop_sextract = { static const TCGOutOpExtract outop_sextract = {