Avoid CFG reachability check after SCCP

SCCP eliminates unreachable BBs before the CFG constraction.
So ir_build_cfg() doesn't need to perforem reachability chececk if it
runs after SCCP, otherwise it starts call ir_remove_unreachable_blocks() if necessary.
User code dont have to call ir_remove_unreachable_blocks() anymore.
This commit is contained in:
Dmitry Stogov 2023-04-27 14:18:39 +03:00
parent b15d9d213f
commit 367d2e3246
5 changed files with 31 additions and 22 deletions

3
ir.h
View File

@ -483,6 +483,9 @@ void ir_strtab_free(ir_strtab *strtab);
#define IR_GEN_NATIVE (1<<21)
#define IR_GEN_C (1<<22)
/* Temporary: SCCP */
#define IR_SCCP_DONE (1<<25)
/* Temporary: Live Ranges */
#define IR_LR_HAVE_VARS (1<<25)
#define IR_LR_HAVE_DESSA_MOVES (1<<26)

View File

@ -101,6 +101,7 @@ int ir_build_cfg(ir_ctx *ctx)
uint32_t b;
ir_insn *insn;
ir_worklist worklist;
uint32_t bb_init_falgs;
uint32_t count, bb_count = 0;
uint32_t edges_count = 0;
ir_block *blocks, *bb;
@ -221,7 +222,6 @@ next_successor:
_ir_add_successors(ctx, ref, &worklist);
} while (ir_worklist_len(&worklist));
}
ir_worklist_clear(&worklist);
IR_ASSERT(bb_count > 0);
@ -230,6 +230,8 @@ next_successor:
b = 1;
bb = blocks + 1;
count = 0;
/* SCCP already removed UNREACHABKE blocks, otherwiseall blocks are marked as UNREACHABLE first */
bb_init_falgs = (ctx->flags & IR_SCCP_DONE) ? 0 : IR_BB_UNREACHABLE;
IR_BITSET_FOREACH(bb_starts, len, start) {
end = _blocks[start];
_blocks[start] = b;
@ -252,9 +254,8 @@ next_successor:
if (insn->op == IR_START) {
bb->flags = IR_BB_START;
bb->predecessors_count = 0;
ir_worklist_push(&worklist, b);
} else {
bb->flags = IR_BB_UNREACHABLE; /* all blocks are marked as UNREACHABLE first */
bb->flags = bb_init_falgs;
if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
n = insn->inputs_count;
bb->predecessors_count = n;
@ -312,22 +313,33 @@ next_successor:
ctx->cfg_edges = edges;
ctx->cfg_map = _blocks;
/* Mark reachable blocks */
while (ir_worklist_len(&worklist) != 0) {
uint32_t *p;
if (!(ctx->flags & IR_SCCP_DONE)) {
uint32_t reachable_count = 0;
b = ir_worklist_pop(&worklist);
bb = &blocks[b];
bb->flags &= ~IR_BB_UNREACHABLE;
n = bb->successors_count;
if (n > 1) {
for (p = edges + bb->successors; n > 0; p++, n--) {
ir_worklist_push(&worklist, *p);
/* Mark reachable blocks */
ir_worklist_clear(&worklist);
ir_worklist_push(&worklist, 1);
while (ir_worklist_len(&worklist) != 0) {
uint32_t *p;
reachable_count++;
b = ir_worklist_pop(&worklist);
bb = &blocks[b];
bb->flags &= ~IR_BB_UNREACHABLE;
n = bb->successors_count;
if (n > 1) {
for (p = edges + bb->successors; n > 0; p++, n--) {
ir_worklist_push(&worklist, *p);
}
} else if (n == 1) {
ir_worklist_push(&worklist, edges[bb->successors]);
}
} else if (n == 1) {
ir_worklist_push(&worklist, edges[bb->successors]);
}
if (reachable_count != ctx->cfg_blocks_count) {
ir_remove_unreachable_blocks(ctx);
}
}
ir_worklist_free(&worklist);
return 1;

View File

@ -165,10 +165,6 @@ int ir_compile_func(ir_ctx *ctx, int opt_level, uint32_t dump, const char *dump_
/* Schedule */
if (opt_level > 0) {
if (opt_level == 1) {
/* With -O2 unreachable blocks are removed by SCCP */
ir_remove_unreachable_blocks(ctx);
}
ir_build_dominators_tree(ctx);
ir_find_loops(ctx);
ir_gcm(ctx);

View File

@ -871,6 +871,7 @@ int ir_sccp(ir_ctx *ctx)
ir_bitqueue_free(&worklist);
ctx->flags &= ~IR_OPT_IN_SCCP;
ctx->flags |= IR_SCCP_DONE;
return 1;
}

View File

@ -169,9 +169,6 @@ int main(int argc, char **argv)
ir_sccp(&ctx);
}
ir_build_cfg(&ctx);
if (opt_level <= 1) {
ir_remove_unreachable_blocks(&ctx);
}
if (opt_level > 0) {
ir_build_dominators_tree(&ctx);
ir_find_loops(&ctx);