aboutsummaryrefslogtreecommitdiff
path: root/tcg
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2022-12-18 22:18:32 +0100
committerRichard Henderson <richard.henderson@linaro.org>2023-01-05 11:41:29 -0800
commitcb10bc63b70737eafaceac1bf1d97730ce6d3393 (patch)
tree862d1d2a6059143f2153522f02f557e46e3bf1d8 /tcg
parentd44789434bbf51bb4d4a3402066d281fa0efc88c (diff)
downloadqemu-cb10bc63b70737eafaceac1bf1d97730ce6d3393.zip
qemu-cb10bc63b70737eafaceac1bf1d97730ce6d3393.tar.gz
qemu-cb10bc63b70737eafaceac1bf1d97730ce6d3393.tar.bz2
tcg: Vary the allocation size for TCGOp
We have been allocating a worst case number of arguments to support calls. Instead, allow the size to vary. By default leave space for 4 args, to maximize reuse, but allow calls to increase the number of args to 32. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> [PMD: Split patch in two] Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20221218211832.73312-3-philmd@linaro.org>
Diffstat (limited to 'tcg')
-rw-r--r--tcg/tcg.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/tcg/tcg.c b/tcg/tcg.c
index ecbbe99..be55e14 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1513,7 +1513,12 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
}
}
- max_args = ARRAY_SIZE(op->args);
+ /*
+ * A Call op needs up to 4 + 2N parameters on 32-bit archs,
+ * and up to 4 + N parameters on 64-bit archs
+ * (N = number of input arguments + output arguments).
+ */
+ max_args = (64 / TCG_TARGET_REG_BITS) * nargs + 4;
op = tcg_emit_op(INDEX_op_call, max_args);
pi = 0;
@@ -2298,19 +2303,31 @@ void tcg_remove_ops_after(TCGOp *op)
static TCGOp *tcg_op_alloc(TCGOpcode opc, unsigned nargs)
{
TCGContext *s = tcg_ctx;
- TCGOp *op;
-
- assert(nargs < ARRAY_SIZE(op->args));
- if (likely(QTAILQ_EMPTY(&s->free_ops))) {
- op = tcg_malloc(sizeof(TCGOp));
- } else {
- op = QTAILQ_FIRST(&s->free_ops);
- QTAILQ_REMOVE(&s->free_ops, op, link);
+ TCGOp *op = NULL;
+
+ if (unlikely(!QTAILQ_EMPTY(&s->free_ops))) {
+ QTAILQ_FOREACH(op, &s->free_ops, link) {
+ if (nargs <= op->nargs) {
+ QTAILQ_REMOVE(&s->free_ops, op, link);
+ nargs = op->nargs;
+ goto found;
+ }
+ }
}
+
+ /* Most opcodes have 3 or 4 operands: reduce fragmentation. */
+ nargs = MAX(4, nargs);
+ op = tcg_malloc(sizeof(TCGOp) + sizeof(TCGArg) * nargs);
+
+ found:
memset(op, 0, offsetof(TCGOp, link));
op->opc = opc;
- s->nb_ops++;
+ op->nargs = nargs;
+
+ /* Check for bitfield overflow. */
+ tcg_debug_assert(op->nargs == nargs);
+ s->nb_ops++;
return op;
}