From 968f305e089eea6b1c4104bf741bf0e18692c0c5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 3 Mar 2023 14:22:02 -0800 Subject: [PATCH] tcg: Merge two sequential labels Remove the first label and redirect all uses to the second. Tested-by: Taylor Simpson Reviewed-by: Taylor Simpson Signed-off-by: Richard Henderson --- tcg/tcg.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 0b93359d3c..cd8f356adb 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -2628,6 +2628,31 @@ TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *old_op, return new_op; } +static void move_label_uses(TCGLabel *to, TCGLabel *from) +{ + TCGLabelUse *u; + + QSIMPLEQ_FOREACH(u, &from->branches, next) { + TCGOp *op = u->op; + switch (op->opc) { + case INDEX_op_br: + op->args[0] = label_arg(to); + break; + case INDEX_op_brcond_i32: + case INDEX_op_brcond_i64: + op->args[3] = label_arg(to); + break; + case INDEX_op_brcond2_i32: + op->args[5] = label_arg(to); + break; + default: + g_assert_not_reached(); + } + } + + QSIMPLEQ_CONCAT(&to->branches, &from->branches); +} + /* Reachable analysis : remove unreachable code. */ static void __attribute__((noinline)) reachable_code_pass(TCGContext *s) @@ -2643,6 +2668,24 @@ reachable_code_pass(TCGContext *s) case INDEX_op_set_label: label = arg_label(op->args[0]); + /* + * Note that the first op in the TB is always a load, + * so there is always something before a label. + */ + op_prev = QTAILQ_PREV(op, link); + + /* + * If we find two sequential labels, move all branches to + * reference the second label and remove the first label. + * Do this before branch to next optimization, so that the + * middle label is out of the way. + */ + if (op_prev->opc == INDEX_op_set_label) { + move_label_uses(label, arg_label(op_prev->args[0])); + tcg_op_remove(s, op_prev); + op_prev = QTAILQ_PREV(op, link); + } + /* * Optimization can fold conditional branches to unconditional. * If we find a label which is preceded by an unconditional @@ -2650,7 +2693,6 @@ reachable_code_pass(TCGContext *s) * processing the branch because any dead code between the branch * and label had not yet been removed. */ - op_prev = QTAILQ_PREV(op, link); if (op_prev->opc == INDEX_op_br && label == arg_label(op_prev->args[0])) { tcg_op_remove(s, op_prev); -- 2.39.5