From 83ead0842f090c3ab6611b33ae19627ffa02eb39 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Dec 2012 15:28:39 +0900 Subject: [PATCH] Remove the dead block removal code. It has proven to be too naive as it is unable to remove unreachable loops. --- tools/qfcc/source/statements.c | 172 +-------------------------------- 1 file changed, 4 insertions(+), 168 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 84a5d3d2e..3939873e3 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -281,7 +281,7 @@ free_statement (statement_t *s) // free_operand (s->opc); FREE (statements, s); } - +#if 0 static void free_sblock (sblock_t *sblock) { @@ -292,7 +292,7 @@ free_sblock (sblock_t *sblock) } FREE (sblocks, sblock); } - +#endif operand_t * def_operand (def_t *def, type_t *type) { @@ -473,7 +473,7 @@ statement_get_targetlist (statement_t *s) } return target_list; } - +#if 0 static void invert_conditional (statement_t *s) { @@ -490,7 +490,7 @@ invert_conditional (statement_t *s) else if (!strcmp (s->opcode, "")) s->opcode = ""; } - +#endif typedef sblock_t *(*statement_f) (sblock_t *, expr_t *); typedef sblock_t *(*expr_f) (sblock_t *, expr_t *, operand_t **); @@ -1360,165 +1360,6 @@ thread_jumps (sblock_t *blocks) } } -static void -join_blocks (sblock_t *sblock, sblock_t *dest) -{ - statement_t **s; - statement_t *g; - expr_t *label; - - for (s = &sblock->statements; (*s) != (statement_t *) sblock->tail; - s = &(*s)->next) - ; - debug (0, "joining blocks %p %p", sblock, dest); - unuse_label ((*s)->opa->o.label); - free_statement (*s); - sblock->tail = s; - // append dest's statements to sblock - *sblock->tail = dest->statements; - sblock->tail = dest->tail; - // clear dest's statement list - dest->tail = &dest->statements; - dest->statements = 0; - // put a goto statement into dest incase the code in sblock flows into dest - // the goto will jump to dest's old - label = new_label_expr (); - label->e.label.dest = dest->next; - label->e.label.next = dest->next->labels; - label->e.label.used++; - dest->next->labels = &label->e.label; - g = new_statement (st_flow, "", 0); - g->opa = new_operand (op_label); - g->opa->o.label = &label->e.label; - sblock_add_statement (dest, g); - // stich dest back into the block list immediately after sblock - dest->next = sblock->next; - sblock->next = dest; -} - -static int -merge_blocks (sblock_t *blocks) -{ - sblock_t *sblock; - int did_something = 0; - - if (!blocks) - return 0; - for (sblock = blocks; sblock; sblock = sblock->next) { - statement_t *s; - sblock_t *dest; - sblock_t *sb; - - if (!sblock->statements) - continue; - s = (statement_t *) sblock->tail; - if (!statement_is_goto (s)) - continue; - dest = s->opa->o.label->dest; - // The destination block must not be the current block - if (dest == sblock) { - warning (0, "infinite loop detected"); - continue; - } - // the destiniation block must have only one label and one user for - // that label (ie, no other branch statement jumps to the block). - // also, don't try to move a marker end-block - if (dest->labels->next || dest->labels->used > 1 || !dest->statements) - continue; - // the destination block must be otherwise unreachable (preceeded by - // an unconditional jump (goto or return)) - if (dest == blocks) - continue; - for (sb = blocks; sb; sb = sb->next) - if (sb->next == dest) - break; - if (!sb) // dest is - internal_error (0, "dangling label"); - if (!sb->statements) - continue; - s = (statement_t *) sb->tail; - if (!statement_is_goto (s) && !statement_is_return (s)) - continue; - // desination block is reachable only via goto of the current block - if (!dest->next) - dest->next = new_sblock (); - sb->next = dest->next; // pull dest out of the chain - join_blocks (sblock, dest); - did_something = 1; - } - return did_something; -} - -static void -remove_dead_blocks (sblock_t *blocks) -{ - sblock_t *sblock; - int did_something; - int pass = 0; - - if (!blocks) - return; - - do { - debug (0, "dead block pass %d", pass++); - did_something = 0; - blocks->reachable = 1; - for (sblock = blocks; sblock->next; sblock = sblock->next) { - sblock_t *sb = sblock->next; - statement_t *s; - - if (sb->labels) { - sb->reachable = 1; - continue; - } - if (!sblock->statements) { - sb->reachable = 1; - continue; - } - s = (statement_t *) sblock->tail; - if (statement_is_cond (s) - && sb->statements && statement_is_goto (sb->statements) - && s->opb->o.label->dest == sb->next) { - debug (0, "merging if/goto %p %p", sblock, sb); - unuse_label (s->opb->o.label); - s->opb->o.label = sb->statements->opa->o.label; - s->opb->o.label->used++; - invert_conditional (s); - sb->reachable = 0; - for (sb = sb->next; sb; sb = sb->next) - sb->reachable = 1; - break; - } else if (!statement_is_goto (s) && !statement_is_return (s)) { - sb->reachable = 1; - continue; - } - sb->reachable = 0; - } - for (sblock = blocks; sblock; sblock = sblock->next) { - while (sblock->next && !sblock->next->reachable) { - sblock_t *sb = sblock->next; - statement_t *s; - ex_label_t *label = 0; - - debug (0, "removing dead block %p", sb); - - if (sb->statements) { - s = (statement_t *) sb->tail; - if (statement_is_goto (s)) - label = s->opa->o.label; - else if (statement_is_cond (s)) - label = s->opb->o.label; - } - unuse_label (label); - did_something = 1; - - sblock->next = sb->next; - free_sblock (sb); - } - } - } while (did_something); -} - static void check_final_block (sblock_t *sblock) { @@ -1572,11 +1413,6 @@ make_statements (expr_t *e) thread_jumps (sblock); if (options.block_dot.thread) dump_dot ("thread", sblock, dump_dot_sblock); - do { - remove_dead_blocks (sblock); - } while (merge_blocks (sblock)); - if (options.block_dot.dead) - dump_dot ("dead", sblock, dump_dot_sblock); check_final_block (sblock); if (options.block_dot.final) dump_dot ("final", sblock, dump_dot_sblock);