Better support for unreachable basic blocks

This commit is contained in:
Dmitry Stogov 2022-06-20 16:34:44 +03:00
parent f8a23e9fe4
commit 5ef1e97261
8 changed files with 108 additions and 14 deletions

View File

@ -977,6 +977,9 @@ int ir_match(ir_ctx *ctx)
ctx->prev_insn_len = ir_mem_malloc(ctx->insns_count * sizeof(uint32_t));
n = 1;
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
for (i = bb->start, insn = ctx->ir_base + i; i <= bb->end;) {
ctx->prev_insn_len[i] = n;
n = ir_operands_count(ctx, insn);
@ -989,6 +992,9 @@ int ir_match(ir_ctx *ctx)
ctx->rules = ir_mem_calloc(ctx->insns_count, sizeof(uint32_t));
for (b = ctx->cfg_blocks_count, bb = ctx->cfg_blocks + b; b > 0; b--, bb--) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
for (i = bb->end; i >= bb->start; i -= ctx->prev_insn_len[i]) {
insn = &ctx->ir_base[i];
if (!ctx->rules[i]) {
@ -3932,6 +3938,9 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx)
ctx->live_intervals = ir_mem_calloc(ctx->vregs_count + 1 + IR_REG_NUM, sizeof(ir_live_interval*));
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
bb->flags &= ~IR_BB_MAY_SKIP;
flags = IR_BB_MAY_SKIP;
if (bb->successors_count != 1 ||
@ -4121,6 +4130,9 @@ static void ir_mark_empty_blocks(ir_ctx *ctx)
uint32_t flags, *rule;
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
bb->flags &= ~IR_BB_MAY_SKIP;
if (bb->successors_count == 1
&& ctx->cfg_edges[bb->successors] == b + 1
@ -4281,6 +4293,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
}
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
// if (bb->flags & IR_BB_MAY_SKIP) {
// continue;
// }

View File

@ -108,11 +108,11 @@ int ir_build_cfg(ir_ctx *ctx)
/* Create array of basic blocks and count succcessor edges for each BB */
blocks = ir_mem_malloc((bb_count + 1) * sizeof(ir_block));
memset(blocks, 0, (bb_count + 1) * sizeof(ir_block));
uint32_t *_xlat = ir_mem_malloc(bb_count * sizeof(uint32_t));
memset(_xlat, 0, bb_count * sizeof(uint32_t));
uint32_t *_xlat = ir_mem_malloc((bb_count + 1) * sizeof(uint32_t));
memset(_xlat, 0, (bb_count + 1) * sizeof(uint32_t));
b = 0;
IR_BITSET_FOREACH(worklist.visited, ir_bitset_len(ctx->insns_count), ref) {
/* reorder blocks to reflect the original control flow (START - 0) */
/* reorder blocks to reflect the original control flow (START - 1) */
j = _blocks[ref];
n = _xlat[j];
if (n == 0) {
@ -130,8 +130,18 @@ int ir_build_cfg(ir_ctx *ctx)
ir_mem_free(_xlat);
ir_worklist_free(&worklist);
ir_worklist_init(&worklist, bb_count + 1);
for (b = 1, bb = blocks + 1; b <= bb_count; b++, bb++) {
insn = &ctx->ir_base[bb->start];
if (insn->op == IR_START) {
bb->flags |= IR_BB_START;
ir_worklist_push(&worklist, b);
} else if (insn->op == IR_ENTRY) {
bb->flags |= IR_BB_ENTRY;
ir_worklist_push(&worklist, b);
} else {
bb->flags |= IR_BB_UNREACHABLE; /* all blocks are marked as UNREACHABLE first */
}
flags = ir_op_flags[insn->op];
n = ir_input_edges_count(ctx, insn);
for (j = 1, p = insn->ops + 1; j <= n; j++, p++) {
@ -187,6 +197,25 @@ int ir_build_cfg(ir_ctx *ctx)
ctx->cfg_blocks = blocks;
ctx->cfg_edges = edges;
/* Mark reachable blocks */
while (ir_worklist_len(&worklist) != 0) {
uint32_t *p, succ_b;
ir_block *succ_bb;
b = ir_worklist_pop(&worklist);
bb = &blocks[b];
n = bb->successors_count;
for (p = ctx->cfg_edges + bb->successors; n > 0; p++, n--) {
succ_b = *p;
succ_bb = &blocks[succ_b];
if (succ_bb->flags & IR_BB_UNREACHABLE) {
succ_bb->flags &= ~IR_BB_UNREACHABLE;
ir_worklist_push(&worklist, succ_b);
}
}
}
ir_worklist_free(&worklist);
return 1;
}
@ -232,9 +261,9 @@ int ir_build_dominators_tree(ir_ctx *ctx)
changed = 0;
/* Iterating in Reverse Post Oorder */
for (b = 2, bb = &blocks[2]; b <= blocks_count; b++, bb++) {
// if (bb->flags & IR_BB_UNREACHABLE) {
// continue;
// }
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
if (bb->predecessors_count) {
int idom = 0;
uint32_t k = bb->predecessors_count;
@ -276,9 +305,9 @@ int ir_build_dominators_tree(ir_ctx *ctx)
/* Construct dominators tree */
for (b = 2, bb = &blocks[2]; b <= blocks_count; b++, bb++) {
// if (bb->flags & IR_BB_UNREACHABLE) {
// continue;
// }
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
if (bb->idom > 0) {
ir_block *idom_bb = &blocks[bb->idom];

View File

@ -221,6 +221,12 @@ void ir_dump_cfg(ir_ctx *ctx, FILE *f)
}
fprintf(f, "]\n");
}
if (bb->flags & IR_BB_ENTRY) {
fprintf(f, "\tENTRY\n");
}
if (bb->flags & IR_BB_UNREACHABLE) {
fprintf(f, "\tUNREACHABLE\n");
}
if (bb->flags & IR_BB_LOOP_HEADER) {
fprintf(f, "\tLOOP_HEADER\n");
}

View File

@ -720,6 +720,9 @@ static int ir_emit_func(ir_ctx *ctx, FILE *f)
/* Emit declarations for local variables */
vars = ir_bitset_malloc(ctx->vregs_count + 1);
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
bb->flags &= ~IR_BB_MAY_SKIP;
flags = IR_BB_MAY_SKIP;
if (bb->successors_count != 1
@ -785,7 +788,7 @@ static int ir_emit_func(ir_ctx *ctx, FILE *f)
ir_mem_free(vars);
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_MAY_SKIP) {
if (bb->flags & (IR_BB_MAY_SKIP|IR_BB_UNREACHABLE)) {
continue;
}
if (ir_needs_block_label(ctx, b)) {

View File

@ -121,6 +121,9 @@ int ir_gcm(ir_ctx *ctx)
/* pin control instructions and collect their direct inputs */
for (i = 1, bb = ctx->cfg_blocks + 1; i <= ctx->cfg_blocks_count; i++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
j = bb->end;
while (1) {
insn = &ctx->ir_base[j];
@ -163,6 +166,9 @@ int ir_gcm(ir_ctx *ctx)
visited = ir_bitset_malloc(ctx->insns_count);
ir_list_clear(&queue);
for (i = 1, bb = ctx->cfg_blocks + 1; i <= ctx->cfg_blocks_count; i++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
j = bb->end;
while (1) {
ir_bitset_incl(visited, j);
@ -403,6 +409,9 @@ int ir_schedule(ir_ctx *ctx)
/* Topological sort according dependencies inside each basic block */
ir_bitset scheduled = ir_bitset_malloc(ctx->insns_count);
for (b = 1, bb = ctx->cfg_blocks + 1; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
i = bb->start;
ir_bitset_incl(scheduled, i);
i = _next[i];

View File

@ -629,10 +629,12 @@ struct _ir_use_list {
((ir_op_flags[op] & IR_OP_FLAG_BB_END) != 0)
#define IR_BB_UNREACHABLE (1<<0)
#define IR_BB_LOOP_HEADER (1<<1)
#define IR_BB_IRREDUCIBLE_LOOP (1<<2)
#define IR_BB_DESSA_MOVES (1<<3) /* translation out of SSA requires MOVEs */
#define IR_BB_MAY_SKIP (1<<4) /* empty BB */
#define IR_BB_START (1<<1)
#define IR_BB_ENTRY (1<<2)
#define IR_BB_LOOP_HEADER (1<<3)
#define IR_BB_IRREDUCIBLE_LOOP (1<<4)
#define IR_BB_DESSA_MOVES (1<<5) /* translation out of SSA requires MOVEs */
#define IR_BB_MAY_SKIP (1<<6) /* empty BB */
struct _ir_block {
uint32_t flags;

15
ir_ra.c
View File

@ -40,6 +40,9 @@ int ir_assign_virtual_registers(ir_ctx *ctx)
vregs = ir_mem_calloc(ctx->insns_count, sizeof(ir_ref));
n = 1;
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
for (i = bb->start, insn = ctx->ir_base + i; i <= bb->end;) {
ctx->prev_insn_len[i] = n;
flags = ir_op_flags[insn->op];
@ -338,6 +341,9 @@ int ir_compute_live_ranges(ir_ctx *ctx)
ctx->live_intervals = ir_mem_calloc(ctx->vregs_count + 1 + IR_REG_NUM, sizeof(ir_live_interval*));
for (b = ctx->cfg_blocks_count; b > 0; b--) {
bb = &ctx->cfg_blocks[b];
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
/* for each successor of b */
ir_bitset_incl(visited, b);
ir_bitset_clear(live, len);
@ -896,6 +902,9 @@ int ir_coalesce(ir_ctx *ctx)
/* Collect a list of blocks which are predecossors to block with phi finctions */
ir_worklist_init(&blocks, ctx->cfg_blocks_count + 1);
for (b = 1, bb = &ctx->cfg_blocks[1]; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
if (bb->predecessors_count > 1) {
use_list = &ctx->use_lists[bb->start];
n = use_list->count;
@ -1028,6 +1037,9 @@ int ir_compute_dessa_moves(ir_ctx *ctx)
ir_insn *insn;
for (b = 1, bb = &ctx->cfg_blocks[1]; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
if (bb->predecessors_count > 1) {
use_list = &ctx->use_lists[bb->start];
n = use_list->count;
@ -2037,6 +2049,9 @@ static int ir_linear_scan(ir_ctx *ctx)
/* Add fixed intervals for temporary registers used for DESSA moves */
for (b = 1, bb = &ctx->cfg_blocks[1]; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
if (bb->flags & IR_BB_DESSA_MOVES) {
ctx->data = bb;
ir_gen_dessa_moves(ctx, b, ir_fix_dessa_tmps);

View File

@ -1765,6 +1765,9 @@ int ir_match(ir_ctx *ctx)
ctx->prev_insn_len = ir_mem_malloc(ctx->insns_count * sizeof(uint32_t));
n = 1;
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
for (i = bb->start, insn = ctx->ir_base + i; i <= bb->end;) {
ctx->prev_insn_len[i] = n;
n = ir_operands_count(ctx, insn);
@ -1777,6 +1780,9 @@ int ir_match(ir_ctx *ctx)
ctx->rules = ir_mem_calloc(ctx->insns_count, sizeof(uint32_t));
for (b = ctx->cfg_blocks_count, bb = ctx->cfg_blocks + b; b > 0; b--, bb--) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
for (i = bb->end; i >= bb->start; i -= ctx->prev_insn_len[i]) {
insn = &ctx->ir_base[i];
if (!ctx->rules[i]) {
@ -6044,6 +6050,9 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx)
ctx->live_intervals = ir_mem_calloc(ctx->vregs_count + 1 + IR_REG_NUM, sizeof(ir_live_interval*));
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
bb->flags &= ~IR_BB_MAY_SKIP;
flags = IR_BB_MAY_SKIP;
if (bb->successors_count != 1 ||
@ -6237,6 +6246,9 @@ static void ir_mark_empty_blocks(ir_ctx *ctx)
uint32_t flags, *rule;
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
bb->flags &= ~IR_BB_MAY_SKIP;
if (bb->successors_count == 1
&& ctx->cfg_edges[bb->successors] == b + 1
@ -6417,6 +6429,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
}
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
// if (bb->flags & IR_BB_MAY_SKIP) {
// continue;
// }