Instead of assuming only small immediates are available for AND, consult the backend in order to decide between SHL/SHR and SHR/AND.
Signed-off-by: Paolo Bonzini <[email protected]> --- include/tcg/tcg.h | 2 ++ tcg/tcg-op.c | 30 ++++++++++++++---------------- tcg/tcg.c | 23 +++++++++++++++++++---- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index a6d9aa50d47..6ca5bf7f67b 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -795,6 +795,8 @@ bool tcg_op_supported(TCGOpcode op, TCGType type, unsigned flags); */ bool tcg_op_deposit_valid(TCGType type, unsigned ofs, unsigned len); +bool tcg_op_imm_match(TCGOpcode op, TCGType type, tcg_target_ulong imm); + void tcg_gen_call0(void *func, TCGHelperInfo *, TCGTemp *ret); void tcg_gen_call1(void *func, TCGHelperInfo *, TCGTemp *ret, TCGTemp *); void tcg_gen_call2(void *func, TCGHelperInfo *, TCGTemp *ret, diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c index ab7b409be61..ccf66382623 100644 --- a/tcg/tcg-op.c +++ b/tcg/tcg-op.c @@ -995,18 +995,17 @@ void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg, return; } - /* ??? Ideally we'd know what values are available for immediate AND. - Assume that 8 bits are available, plus the special case of 16, - so that we get ext8u, ext16u. */ - switch (len) { - case 1 ... 8: case 16: + /* + * Use TCG_TARGET_extract_valid to check for 8- and 16-bit extension + * opcodes, which tcg_gen_andi_i32 can produce. + */ + if (TCG_TARGET_extract_valid(TCG_TYPE_I32, 0, len) || + tcg_op_imm_match(INDEX_op_and, TCG_TYPE_I32, (1u << len) - 1)) { tcg_gen_shri_i32(ret, arg, ofs); tcg_gen_andi_i32(ret, ret, (1u << len) - 1); - break; - default: + } else { tcg_gen_shli_i32(ret, arg, 32 - len - ofs); tcg_gen_shri_i32(ret, ret, 32 - len); - break; } } @@ -2690,18 +2689,17 @@ void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg, return; } - /* ??? Ideally we'd know what values are available for immediate AND. - Assume that 8 bits are available, plus the special cases of 16 and 32, - so that we get ext8u, ext16u, and ext32u. */ - switch (len) { - case 1 ... 8: case 16: case 32: + /* + * Use TCG_TARGET_extract_valid to check for 8-, 16- and 32-bit extension + * opcodes, which tcg_gen_andi_i64 can produce. + */ + if (TCG_TARGET_extract_valid(TCG_TYPE_I64, 0, len) || + tcg_op_imm_match(INDEX_op_and, TCG_TYPE_I64, (1ull << len) - 1)) { tcg_gen_shri_i64(ret, arg, ofs); tcg_gen_andi_i64(ret, ret, (1ull << len) - 1); - break; - default: + } else { tcg_gen_shli_i64(ret, arg, 64 - len - ofs); tcg_gen_shri_i64(ret, ret, 64 - len); - break; } } diff --git a/tcg/tcg.c b/tcg/tcg.c index fbf09f5c826..79ca49154a2 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -3509,11 +3509,8 @@ static void process_constraint_sets(void) } } -static const TCGArgConstraint *opcode_args_ct(const TCGOp *op) +static const TCGArgConstraint *op_args_ct(TCGOpcode opc, TCGType type, unsigned flags) { - TCGOpcode opc = op->opc; - TCGType type = TCGOP_TYPE(op); - unsigned flags = TCGOP_FLAGS(op); const TCGOpDef *def = &tcg_op_defs[opc]; const TCGOutOp *outop = all_outop[opc]; TCGConstraintSetIndex con_set; @@ -3540,6 +3537,24 @@ static const TCGArgConstraint *opcode_args_ct(const TCGOp *op) return all_cts[con_set]; } +static const TCGArgConstraint *opcode_args_ct(const TCGOp *op) +{ + return op_args_ct(op->opc, TCGOP_TYPE(op), TCGOP_FLAGS(op)); +} + +/* Return true if the backend can efficiently handle IMM as an immediate + for OP. */ +bool tcg_op_imm_match(TCGOpcode opc, TCGType type, tcg_target_ulong imm) +{ + const TCGOpDef * const def = &tcg_op_defs[opc]; + const TCGArgConstraint *args_ct = op_args_ct(opc, type, 0); + + tcg_debug_assert(def->nb_iargs == 2); + return tcg_target_const_match( + imm, args_ct[def->nb_oargs + 2].ct, + type, 0, 0); +} + static void remove_label_use(TCGOp *op, int idx) { TCGLabel *label = arg_label(op->args[idx]); -- 2.52.0
