mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-09-09 08:17:53 -06:00
tcg: Merge two sequential labels
Remove the first label and redirect all uses to the second. Tested-by: Taylor Simpson <tsimpson@quicinc.com> Reviewed-by: Taylor Simpson <tsimpson@quicinc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
f85b1fc4a0
commit
968f305e08
1 changed files with 43 additions and 1 deletions
44
tcg/tcg.c
44
tcg/tcg.c
|
@ -2628,6 +2628,31 @@ TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *old_op,
|
||||||
return new_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. */
|
/* Reachable analysis : remove unreachable code. */
|
||||||
static void __attribute__((noinline))
|
static void __attribute__((noinline))
|
||||||
reachable_code_pass(TCGContext *s)
|
reachable_code_pass(TCGContext *s)
|
||||||
|
@ -2643,6 +2668,24 @@ reachable_code_pass(TCGContext *s)
|
||||||
case INDEX_op_set_label:
|
case INDEX_op_set_label:
|
||||||
label = arg_label(op->args[0]);
|
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.
|
* Optimization can fold conditional branches to unconditional.
|
||||||
* If we find a label which is preceded by an 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
|
* processing the branch because any dead code between the branch
|
||||||
* and label had not yet been removed.
|
* and label had not yet been removed.
|
||||||
*/
|
*/
|
||||||
op_prev = QTAILQ_PREV(op, link);
|
|
||||||
if (op_prev->opc == INDEX_op_br &&
|
if (op_prev->opc == INDEX_op_br &&
|
||||||
label == arg_label(op_prev->args[0])) {
|
label == arg_label(op_prev->args[0])) {
|
||||||
tcg_op_remove(s, op_prev);
|
tcg_op_remove(s, op_prev);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue