Message ID | 20250107080112.1175095-51-richard.henderson@linaro.org |
---|---|
State | New |
Headers | show |
Series | tcg: Merge *_i32 and *_i64 opcodes | expand |
On 7/1/25 09:00, Richard Henderson wrote: > 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. > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > tcg/tcg.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++------- > 1 file changed, 53 insertions(+), 7 deletions(-) > +static const TCGOutOp outop_notreached = { > + .static_constraint = C_NotReached, > +}; > + > +static const TCGOutOp * const all_outop[NB_OPS] = { > + [0 ... NB_OPS - 1] = &outop_notreached, > +}; > @@ -3331,18 +3370,25 @@ static void process_constraint_sets(TCGContext *s) > > 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)); > + if (outop) { Always true, > + 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); so unreachable. Gremlins? > + }
On 1/9/25 15:21, Philippe Mathieu-Daudé wrote: > On 7/1/25 09:00, Richard Henderson wrote: >> 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. >> >> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> >> --- >> tcg/tcg.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++------- >> 1 file changed, 53 insertions(+), 7 deletions(-) > > >> +static const TCGOutOp outop_notreached = { >> + .static_constraint = C_NotReached, >> +}; >> + >> +static const TCGOutOp * const all_outop[NB_OPS] = { >> + [0 ... NB_OPS - 1] = &outop_notreached, >> +}; > > >> @@ -3331,18 +3370,25 @@ static void process_constraint_sets(TCGContext *s) >> 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)); >> + if (outop) { > > Always true, > >> + 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); > > so unreachable. Gremlins? Yes, this was the midnight gremlin of which we spoke. The outop_unreached thing has to wait until the end of the conversion. r~
diff --git a/tcg/tcg.c b/tcg/tcg.c index 1736cf664b..7effb17b32 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -862,6 +862,8 @@ 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_NotReached = -3, + C_Dynamic = -2, C_NotImplemented = -1, #include "tcg-target-con-set.h" } TCGConstraintSetIndex; @@ -955,6 +957,11 @@ 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) +typedef struct TCGOutOp { + TCGConstraintSetIndex static_constraint; + TCGConstraintSetIndex (*dynamic_constraint)(TCGType type, unsigned flags); +} TCGOutOp; + #include "tcg-target.c.inc" #ifndef CONFIG_TCG_INTERPRETER @@ -964,6 +971,14 @@ QEMU_BUILD_BUG_ON((int)(offsetof(CPUNegativeOffsetState, tlb.f[0]) - < MIN_TLB_MASK_TABLE_OFS); #endif +static const TCGOutOp outop_notreached = { + .static_constraint = C_NotReached, +}; + +static const TCGOutOp * const all_outop[NB_OPS] = { + [0 ... NB_OPS - 1] = &outop_notreached, +}; + /* * 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 @@ -2410,8 +2425,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(); } } @@ -3331,18 +3370,25 @@ static void process_constraint_sets(TCGContext *s) 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)); + 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 && con_set < ARRAY_SIZE(constraint_sets)); /* The constraint arguments must match TCGOpcode arguments. */
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. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- tcg/tcg.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 7 deletions(-)