tcg: Add all_outop[]

Add infrastructure for more consolidated output of opcodes.
The base structure allows for constraints to be either static
or dynamic, and for the existence of those constraints to
replace TCG_TARGET_HAS_* and the bulk of tcg_op_supported.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2025-01-03 14:55:56 -08:00
parent cf5c9f697f
commit 5500bd9e2e

View file

@ -861,6 +861,7 @@ static int tcg_out_pool_finalize(TCGContext *s)
#define C_N1_O1_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_n1_o1_i4_, O1, O2, I1, I2, I3, I4),
typedef enum {
C_Dynamic = -2,
C_NotImplemented = -1,
#include "tcg-target-con-set.h"
} TCGConstraintSetIndex;
@ -954,6 +955,29 @@ static const TCGConstraintSet constraint_sets[] = {
#define C_O2_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_o2_i4_, O1, O2, I1, I2, I3, I4)
#define C_N1_O1_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_n1_o1_i4_, O1, O2, I1, I2, I3, I4)
/*
* TCGOutOp is the base class for a set of structures that describe how
* to generate code for a given TCGOpcode.
*
* @static_constraint:
* C_NotImplemented: The TCGOpcode is not supported by the backend.
* C_Dynamic: Use @dynamic_constraint to select a constraint set
* based on any of @type, @flags, or host isa.
* Otherwise: The register allocation constrains for the TCGOpcode.
*
* Subclasses of TCGOutOp will define a set of output routines that may
* be used. Such routines will often be selected by the set of registers
* and constants that come out of register allocation. The set of
* routines that are provided will guide the set of constraints that are
* legal. In particular, assume that tcg_optimize() has done its job in
* swapping commutative operands and folding operations for which all
* operands are constant.
*/
typedef struct TCGOutOp {
TCGConstraintSetIndex static_constraint;
TCGConstraintSetIndex (*dynamic_constraint)(TCGType type, unsigned flags);
} TCGOutOp;
#include "tcg-target.c.inc"
#ifndef CONFIG_TCG_INTERPRETER
@ -963,6 +987,10 @@ QEMU_BUILD_BUG_ON((int)(offsetof(CPUNegativeOffsetState, tlb.f[0]) -
< MIN_TLB_MASK_TABLE_OFS);
#endif
/* Register allocation descriptions for every TCGOpcode. */
static const TCGOutOp * const all_outop[NB_OPS] = {
};
/*
* All TCG threads except the parent (i.e. the one that called tcg_context_init
* and registered the target's TCG globals) must register with this function
@ -2416,8 +2444,32 @@ bool tcg_op_supported(TCGOpcode op, TCGType type, unsigned flags)
return has_type && TCG_TARGET_HAS_cmpsel_vec;
default:
tcg_debug_assert(op > INDEX_op_last_generic && op < NB_OPS);
if (op < INDEX_op_last_generic) {
const TCGOutOp *outop;
TCGConstraintSetIndex con_set;
if (!has_type) {
return false;
}
outop = all_outop[op];
tcg_debug_assert(outop != NULL);
con_set = outop->static_constraint;
if (con_set == C_Dynamic) {
con_set = outop->dynamic_constraint(type, flags);
}
if (con_set >= 0) {
return true;
}
tcg_debug_assert(con_set == C_NotImplemented);
return false;
}
tcg_debug_assert(op < NB_OPS);
return true;
case INDEX_op_last_generic:
g_assert_not_reached();
}
}
@ -3335,19 +3387,27 @@ static void process_constraint_sets(void)
static const TCGArgConstraint *opcode_args_ct(const TCGOp *op)
{
const TCGOpDef *def = &tcg_op_defs[op->opc];
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;
#ifdef CONFIG_DEBUG_TCG
assert(tcg_op_supported(op->opc, TCGOP_TYPE(op), TCGOP_FLAGS(op)));
#endif
if (def->flags & TCG_OPF_NOT_PRESENT) {
return empty_cts;
}
con_set = tcg_target_op_def(op->opc, TCGOP_TYPE(op), TCGOP_FLAGS(op));
tcg_debug_assert(con_set >= 0 && con_set < ARRAY_SIZE(constraint_sets));
if (outop) {
con_set = outop->static_constraint;
if (con_set == C_Dynamic) {
con_set = outop->dynamic_constraint(type, flags);
}
} else {
con_set = tcg_target_op_def(opc, type, flags);
}
tcg_debug_assert(con_set >= 0);
tcg_debug_assert(con_set < ARRAY_SIZE(constraint_sets));
/* The constraint arguments must match TCGOpcode arguments. */
tcg_debug_assert(constraint_sets[con_set].nb_oargs == def->nb_oargs);