tcg: Add reachable_code_pass
Delete trivially dead code that follows unconditional branches and noreturn helpers. These can occur either via optimization or via the structure of a target's translator following an exception. Reviewed-by: Emilio G. Cota <cota@braap.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
d88a117eaa
commit
b4fc67c7af
76
tcg/tcg.c
76
tcg/tcg.c
@ -2239,6 +2239,81 @@ TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *old_op, TCGOpcode opc)
|
||||
return new_op;
|
||||
}
|
||||
|
||||
/* Reachable analysis : remove unreachable code. */
|
||||
static void reachable_code_pass(TCGContext *s)
|
||||
{
|
||||
TCGOp *op, *op_next;
|
||||
bool dead = false;
|
||||
|
||||
QTAILQ_FOREACH_SAFE(op, &s->ops, link, op_next) {
|
||||
bool remove = dead;
|
||||
TCGLabel *label;
|
||||
int call_flags;
|
||||
|
||||
switch (op->opc) {
|
||||
case INDEX_op_set_label:
|
||||
label = arg_label(op->args[0]);
|
||||
if (label->refs == 0) {
|
||||
/*
|
||||
* While there is an occasional backward branch, virtually
|
||||
* all branches generated by the translators are forward.
|
||||
* Which means that generally we will have already removed
|
||||
* all references to the label that will be, and there is
|
||||
* little to be gained by iterating.
|
||||
*/
|
||||
remove = true;
|
||||
} else {
|
||||
/* Once we see a label, insns become live again. */
|
||||
dead = 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, TCGOpHead, link);
|
||||
if (op_prev->opc == INDEX_op_br &&
|
||||
label == arg_label(op_prev->args[0])) {
|
||||
tcg_op_remove(s, op_prev);
|
||||
remove = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case INDEX_op_br:
|
||||
case INDEX_op_exit_tb:
|
||||
case INDEX_op_goto_ptr:
|
||||
/* Unconditional branches; everything following is dead. */
|
||||
dead = true;
|
||||
break;
|
||||
|
||||
case INDEX_op_call:
|
||||
/* Notice noreturn helper calls, raising exceptions. */
|
||||
call_flags = op->args[TCGOP_CALLO(op) + TCGOP_CALLI(op) + 1];
|
||||
if (call_flags & TCG_CALL_NO_RETURN) {
|
||||
dead = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case INDEX_op_insn_start:
|
||||
/* Never remove -- we need to keep these for unwind. */
|
||||
remove = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (remove) {
|
||||
tcg_op_remove(s, op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define TS_DEAD 1
|
||||
#define TS_MEM 2
|
||||
|
||||
@ -3515,6 +3590,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
|
||||
atomic_set(&prof->la_time, prof->la_time - profile_getclock());
|
||||
#endif
|
||||
|
||||
reachable_code_pass(s);
|
||||
liveness_pass_1(s);
|
||||
|
||||
if (s->nb_indirects > 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user