diff mbox series

[4/4] tcg: Add reachable_code_pass

Message ID 20181126230450.672-5-richard.henderson@linaro.org
State Superseded
Headers show
Series tcg: Remove unreachable code | expand

Commit Message

Richard Henderson Nov. 26, 2018, 11:04 p.m. UTC
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.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

---
 tcg/tcg.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

-- 
2.17.2

Comments

Emilio Cota Dec. 24, 2018, 10:10 p.m. UTC | #1
On Mon, Nov 26, 2018 at 15:04:50 -0800, Richard Henderson wrote:
> 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.

> 

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

> ---

(snip)
> +                /*

> +                 * Optimization can fold conditional branches to unconditional.

> +                 * If we find a label with one reference which is preceeded by


s/preceeded/preceded/

Reviewed-by: Emilio G. Cota <cota@braap.org>


for the series.

Thanks,

		E.
diff mbox series

Patch

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 31b9b58240..ffbf8f01ad 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -2301,6 +2301,81 @@  static void tcg_la_bb_end(TCGContext *s)
     }
 }
 
+/* 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 preceeded 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);
+        }
+    }
+}
+
 /* Liveness analysis : update the opc_arg_life array to tell if a
    given input arguments is dead. Instructions updating dead
    temporaries are removed. */
@@ -3537,6 +3612,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) {