mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 16:53:55 -06:00
tcg: Remove branch-to-next regardless of reference count
Just because the label reference count is more than 1 does not mean we cannot remove a branch-to-next. By doing this first, the label reference count may drop to 0, and then the label itself gets removed as before. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
9b1890ad90
commit
4d89d0bb8f
1 changed files with 17 additions and 16 deletions
33
tcg/tcg.c
33
tcg/tcg.c
|
@ -2637,7 +2637,7 @@ TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *old_op,
|
||||||
/* Reachable analysis : remove unreachable code. */
|
/* Reachable analysis : remove unreachable code. */
|
||||||
static void reachable_code_pass(TCGContext *s)
|
static void reachable_code_pass(TCGContext *s)
|
||||||
{
|
{
|
||||||
TCGOp *op, *op_next;
|
TCGOp *op, *op_next, *op_prev;
|
||||||
bool dead = false;
|
bool dead = false;
|
||||||
|
|
||||||
QTAILQ_FOREACH_SAFE(op, &s->ops, link, op_next) {
|
QTAILQ_FOREACH_SAFE(op, &s->ops, link, op_next) {
|
||||||
|
@ -2647,6 +2647,22 @@ static void reachable_code_pass(TCGContext *s)
|
||||||
switch (op->opc) {
|
switch (op->opc) {
|
||||||
case INDEX_op_set_label:
|
case INDEX_op_set_label:
|
||||||
label = arg_label(op->args[0]);
|
label = arg_label(op->args[0]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Optimization can fold conditional branches to unconditional.
|
||||||
|
* If we find a label which is preceded by an unconditional
|
||||||
|
* branch to next, remove the branch. We couldn't do this when
|
||||||
|
* 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);
|
||||||
|
/* Fall through means insns become live again. */
|
||||||
|
dead = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (label->refs == 0) {
|
if (label->refs == 0) {
|
||||||
/*
|
/*
|
||||||
* While there is an occasional backward branch, virtually
|
* While there is an occasional backward branch, virtually
|
||||||
|
@ -2660,21 +2676,6 @@ static void reachable_code_pass(TCGContext *s)
|
||||||
/* Once we see a label, insns become live again. */
|
/* Once we see a label, insns become live again. */
|
||||||
dead = false;
|
dead = false;
|
||||||
remove = false;
|
remove = false;
|
||||||
|
|
||||||
/*
|
|
||||||
* Optimization can fold conditional branches to unconditional.
|
|
||||||
* If we find a label with one reference which is preceded by
|
|
||||||
* an unconditional branch to it, remove both. This needed to
|
|
||||||
* wait until the dead code in between them was removed.
|
|
||||||
*/
|
|
||||||
if (label->refs == 1) {
|
|
||||||
TCGOp *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);
|
|
||||||
remove = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue