Use reference to previous instruction instead of its length

This commit is contained in:
Dmitry Stogov 2022-11-18 13:59:49 +03:00
parent ae19ad7c79
commit dde8309108
8 changed files with 33 additions and 28 deletions

6
ir.c
View File

@ -315,7 +315,7 @@ void ir_init(ir_ctx *ctx, ir_ref consts_limit, ir_ref insns_limit)
ctx->fixed_save_regset = 0;
ctx->live_intervals = NULL;
ctx->regs = NULL;
ctx->prev_insn_len = NULL;
ctx->prev_ref = NULL;
ctx->data = NULL;
ctx->code_buffer = NULL;
@ -376,8 +376,8 @@ void ir_free(ir_ctx *ctx)
if (ctx->regs) {
ir_mem_free(ctx->regs);
}
if (ctx->prev_insn_len) {
ir_mem_free(ctx->prev_insn_len);
if (ctx->prev_ref) {
ir_mem_free(ctx->prev_ref);
}
}

2
ir.h
View File

@ -483,7 +483,7 @@ typedef struct _ir_ctx {
uint64_t fixed_save_regset;
ir_live_interval **live_intervals;
ir_regs *regs;
ir_ref *prev_insn_len;
ir_ref *prev_ref;
void *data;
uint32_t rodata_offset;
uint32_t jmp_table_offset;

View File

@ -861,8 +861,8 @@ binop_fp:
if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UGT
// TODO: register allocator may clobber operands of CMP before they are used in the GUARD_CMP
&& (insn->op2 == ref - 1 ||
(insn->op2 == ref - ctx->prev_insn_len[ref] - 1
&& ctx->ir_base[ref - ctx->prev_insn_len[ref]].op == IR_SNAPSHOT))) {
(insn->op2 == ctx->prev_ref[ref] - 1
&& ctx->ir_base[ctx->prev_ref[ref]].op == IR_SNAPSHOT))) {
if (IR_IS_TYPE_INT(ctx->ir_base[op2_insn->op1].type)) {
if (insn->op1 > bb->start
&& insn->op1 < ref
@ -4777,7 +4777,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
if (bb->end - ctx->prev_insn_len[bb->end] == bb->start
if (ctx->prev_ref[bb->end] == bb->start
&& bb->successors_count == 1
&& !(bb->flags & (IR_BB_START|IR_BB_ENTRY|IR_BB_DESSA_MOVES))) {
continue;

View File

@ -662,7 +662,7 @@ int ir_schedule_blocks(ir_ctx *ctx)
list = ir_mem_malloc(sizeof(uint32_t) * (ctx->cfg_blocks_count + 1) * 2);
map = list + (ctx->cfg_blocks_count + 1);
for (b = 1, bb = &ctx->cfg_blocks[1]; b <= ctx->cfg_blocks_count; b++, bb++) {
if (bb->end - ctx->prev_insn_len[bb->end] == bb->start
if (ctx->prev_ref[bb->end] == bb->start
&& bb->successors_count == 1
&& !(bb->flags & IR_BB_DESSA_MOVES)) {
bb->flags |= IR_BB_EMPTY;
@ -806,7 +806,7 @@ uint32_t ir_skip_empty_target_blocks(ir_ctx *ctx, uint32_t b)
while (1) {
bb = &ctx->cfg_blocks[b];
if (bb->end - ctx->prev_insn_len[bb->end] == bb->start
if (ctx->prev_ref[bb->end] == bb->start
&& bb->successors_count == 1
&& !(bb->flags & (IR_BB_START|IR_BB_ENTRY|IR_BB_DESSA_MOVES))) {
b = ctx->cfg_edges[bb->successors];
@ -828,7 +828,7 @@ uint32_t ir_skip_empty_next_blocks(ir_ctx *ctx, uint32_t b)
bb = &ctx->cfg_blocks[b];
if (bb->end - ctx->prev_insn_len[bb->end] == bb->start
if (ctx->prev_ref[bb->end] == bb->start
&& bb->successors_count == 1
&& !(bb->flags & (IR_BB_START|/*IR_BB_ENTRY|*/IR_BB_DESSA_MOVES))) {
b++;

View File

@ -264,24 +264,26 @@ static void *ir_jmp_addr(ir_ctx *ctx, ir_insn *insn, ir_insn *addr_insn)
int ir_match(ir_ctx *ctx)
{
uint32_t b;
ir_ref i, n;
ir_ref i, n, prev;
ir_block *bb;
ir_insn *insn;
if (!ctx->prev_insn_len) {
ctx->prev_insn_len = ir_mem_malloc(ctx->insns_count * sizeof(uint32_t));
n = 1;
if (!ctx->prev_ref) {
ctx->prev_ref = ir_mem_malloc(ctx->insns_count * sizeof(ir_ref));
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;
prev = 0;
for (i = bb->start, insn = ctx->ir_base + i; i < bb->end;) {
ctx->prev_ref[i] = prev;
n = ir_operands_count(ctx, insn);
n = 1 + (n >> 2); // support for multi-word instructions like MERGE and PHI
prev = i;
i += n;
insn += n;
}
ctx->prev_ref[i] = prev;
}
}
@ -290,7 +292,7 @@ int ir_match(ir_ctx *ctx)
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
for (i = bb->end; i >= bb->start; i -= ctx->prev_insn_len[i]) {
for (i = bb->end; i >= bb->start; i = ctx->prev_ref[i]) {
insn = &ctx->ir_base[i];
if (!ctx->rules[i]) {
ctx->rules[i] = ir_match_insn(ctx, i, bb);

View File

@ -750,7 +750,7 @@ static int ir_emit_func(ir_ctx *ctx, FILE *f)
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
if (bb->end - ctx->prev_insn_len[bb->end] == bb->start
if (ctx->prev_ref[bb->end] == bb->start
&& bb->successors_count == 1
&& !(bb->flags & (IR_BB_START|IR_BB_ENTRY|IR_BB_DESSA_MOVES))) {
continue;

17
ir_ra.c
View File

@ -46,14 +46,14 @@ int ir_assign_virtual_registers(ir_ctx *ctx)
uint32_t *vregs;
uint32_t vregs_count = 0;
uint32_t b;
ir_ref i, n;
ir_ref i, n, prev;
ir_block *bb;
ir_insn *insn;
uint32_t flags;
/* Assign unique virtual register to each data node */
if (!ctx->prev_insn_len) {
ctx->prev_insn_len = ir_mem_malloc(ctx->insns_count * sizeof(uint32_t));
if (!ctx->prev_ref) {
ctx->prev_ref = ir_mem_malloc(ctx->insns_count * sizeof(ir_ref));
}
vregs = ir_mem_calloc(ctx->insns_count, sizeof(ir_ref));
n = 1;
@ -65,12 +65,14 @@ int ir_assign_virtual_registers(ir_ctx *ctx)
/* skip first instruction */
insn = ctx->ir_base + i;
ctx->prev_ref[i] = 0;
prev = i;
n = ir_operands_count(ctx, insn);
n = 1 + (n >> 2); // support for multi-word instructions like MERGE and PHI
i += n;
insn += n;
while (i < bb->end) {
ctx->prev_insn_len[i] = n;
ctx->prev_ref[i] = prev;
flags = ir_op_flags[insn->op];
if (((flags & IR_OP_FLAG_DATA) && ctx->use_lists[i].count > 0)
|| ((flags & IR_OP_FLAG_MEM) && ctx->use_lists[i].count > 1)) {
@ -80,10 +82,11 @@ int ir_assign_virtual_registers(ir_ctx *ctx)
}
n = ir_operands_count(ctx, insn);
n = 1 + (n >> 2); // support for multi-word instructions like MERGE and PHI
prev = i;
i += n;
insn += n;
}
ctx->prev_insn_len[i] = n;
ctx->prev_ref[i] = prev;
}
ctx->vregs_count = vregs_count;
ctx->vregs = vregs;
@ -454,9 +457,9 @@ int ir_compute_live_ranges(ir_ctx *ctx)
ref = bb->end;
insn = &ctx->ir_base[ref];
if (insn->op == IR_END || insn->op == IR_LOOP_END) {
ref -= ctx->prev_insn_len[ref];
ref = ctx->prev_ref[ref];
}
for (; ref > bb->start; ref -= ctx->prev_insn_len[ref]) {
for (; ref > bb->start; ref = ctx->prev_ref[ref]) {
uint32_t def_flags;
uint32_t flags;
ir_ref *p;

View File

@ -1701,8 +1701,8 @@ store_int:
if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UGT
// TODO: register allocator may clobber operands of CMP before they are used in the GUARD_CMP
&& (insn->op2 == ref - 1 ||
(insn->op2 == ref - ctx->prev_insn_len[ref] - 1
&& ctx->ir_base[ref - ctx->prev_insn_len[ref]].op == IR_SNAPSHOT))) {
(insn->op2 == ctx->prev_ref[ref] - 1
&& ctx->ir_base[ctx->prev_ref[ref]].op == IR_SNAPSHOT))) {
if (IR_IS_TYPE_INT(ctx->ir_base[op2_insn->op1].type)) {
if (op2_insn->op1 > bb->start
&& op2_insn->op1 < ref
@ -7266,7 +7266,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
if (bb->flags & IR_BB_UNREACHABLE) {
continue;
}
if (bb->end - ctx->prev_insn_len[bb->end] == bb->start
if (ctx->prev_ref[bb->end] == bb->start
&& bb->successors_count == 1
&& !(bb->flags & (IR_BB_START|IR_BB_ENTRY|IR_BB_DESSA_MOVES))) {
continue;