mirror of
https://github.com/danog/ir.git
synced 2024-11-26 20:34:53 +01:00
Better support for unreachable basic blocks
This commit is contained in:
parent
f8a23e9fe4
commit
5ef1e97261
@ -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;
|
||||
// }
|
||||
|
47
ir_cfg.c
47
ir_cfg.c
@ -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];
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
9
ir_gcm.c
9
ir_gcm.c
@ -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];
|
||||
|
10
ir_private.h
10
ir_private.h
@ -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
15
ir_ra.c
@ -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);
|
||||
|
15
ir_x86.dasc
15
ir_x86.dasc
@ -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;
|
||||
// }
|
||||
|
Loading…
Reference in New Issue
Block a user