aboutsummaryrefslogtreecommitdiff
path: root/tcg
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2023-01-29 11:50:20 -1000
committerRichard Henderson <richard.henderson@linaro.org>2023-03-01 07:33:27 -1000
commit874b85746107d4acf6ad6f28393cf45ef833e1ee (patch)
treed8bd1e597df7fe7839f7ce98a4d2e985b271c295 /tcg
parent9bbee4c01c2c249ec800ca10ae6d37ca1b8d0732 (diff)
downloadqemu-874b85746107d4acf6ad6f28393cf45ef833e1ee.zip
qemu-874b85746107d4acf6ad6f28393cf45ef833e1ee.tar.gz
qemu-874b85746107d4acf6ad6f28393cf45ef833e1ee.tar.bz2
tcg: Add liveness_pass_0
Attempt to reduce the lifetime of TEMP_TB. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'tcg')
-rw-r--r--tcg/tcg.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 71b6843..1dbb242 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -2857,6 +2857,75 @@ static void la_cross_call(TCGContext *s, int nt)
}
}
+/*
+ * Liveness analysis: Verify the lifetime of TEMP_TB, and reduce
+ * to TEMP_EBB, if possible.
+ */
+static void __attribute__((noinline))
+liveness_pass_0(TCGContext *s)
+{
+ void * const multiple_ebb = (void *)(uintptr_t)-1;
+ int nb_temps = s->nb_temps;
+ TCGOp *op, *ebb;
+
+ for (int i = s->nb_globals; i < nb_temps; ++i) {
+ s->temps[i].state_ptr = NULL;
+ }
+
+ /*
+ * Represent each EBB by the op at which it begins. In the case of
+ * the first EBB, this is the first op, otherwise it is a label.
+ * Collect the uses of each TEMP_TB: NULL for unused, EBB for use
+ * within a single EBB, else MULTIPLE_EBB.
+ */
+ ebb = QTAILQ_FIRST(&s->ops);
+ QTAILQ_FOREACH(op, &s->ops, link) {
+ const TCGOpDef *def;
+ int nb_oargs, nb_iargs;
+
+ switch (op->opc) {
+ case INDEX_op_set_label:
+ ebb = op;
+ continue;
+ case INDEX_op_discard:
+ continue;
+ case INDEX_op_call:
+ nb_oargs = TCGOP_CALLO(op);
+ nb_iargs = TCGOP_CALLI(op);
+ break;
+ default:
+ def = &tcg_op_defs[op->opc];
+ nb_oargs = def->nb_oargs;
+ nb_iargs = def->nb_iargs;
+ break;
+ }
+
+ for (int i = 0; i < nb_oargs + nb_iargs; ++i) {
+ TCGTemp *ts = arg_temp(op->args[i]);
+
+ if (ts->kind != TEMP_TB) {
+ continue;
+ }
+ if (ts->state_ptr == NULL) {
+ ts->state_ptr = ebb;
+ } else if (ts->state_ptr != ebb) {
+ ts->state_ptr = multiple_ebb;
+ }
+ }
+ }
+
+ /*
+ * For TEMP_TB that turned out not to be used beyond one EBB,
+ * reduce the liveness to TEMP_EBB.
+ */
+ for (int i = s->nb_globals; i < nb_temps; ++i) {
+ TCGTemp *ts = &s->temps[i];
+ if (ts->kind == TEMP_TB && ts->state_ptr != multiple_ebb) {
+ ts->kind = TEMP_EBB;
+ }
+ }
+}
+
/* Liveness analysis : update the opc_arg_life array to tell if a
given input arguments is dead. Instructions updating dead
temporaries are removed. */
@@ -4872,6 +4941,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start)
#endif
reachable_code_pass(s);
+ liveness_pass_0(s);
liveness_pass_1(s);
if (s->nb_indirects > 0) {