From 69b5a852e579cf1aab26931d68526b5b8d5735f4 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 6 May 2022 16:19:57 +0300 Subject: [PATCH] Make DESSA API use "ir_ref" instead of "virtual register number" (0 - is still a temporary register) --- ir.h | 2 +- ir_dump.c | 10 +-- ir_emit_c.c | 6 +- ir_ra.c | 32 ++++----- ir_x86.dasc | 135 +++++++++++--------------------------- tests/debug/dessa_003.irt | 6 +- 6 files changed, 66 insertions(+), 125 deletions(-) diff --git a/ir.h b/ir.h index 99eb171..354fb1f 100644 --- a/ir.h +++ b/ir.h @@ -723,7 +723,7 @@ int ir_gcm(ir_ctx *ctx); int ir_schedule(ir_ctx *ctx); /* Liveness & Register Allocation (implementation in ir_ra.c) */ -typedef int (*emit_copy_t)(ir_ctx *ctx, uint8_t type, int from, int to); +typedef int (*emit_copy_t)(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to); #ifdef IR_DEBUG extern uint32_t debug_regset; diff --git a/ir_dump.c b/ir_dump.c index 234500a..658591d 100644 --- a/ir_dump.c +++ b/ir_dump.c @@ -146,7 +146,7 @@ void ir_dump_use_lists(ir_ctx *ctx, FILE *f) } } -static int ir_dump_dessa_move(ir_ctx *ctx, uint8_t type, int from, int to) +static int ir_dump_dessa_move(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to) { FILE *f = ctx->data; int8_t reg; @@ -154,8 +154,8 @@ static int ir_dump_dessa_move(ir_ctx *ctx, uint8_t type, int from, int to) if (IR_IS_CONST_REF(from)) { fprintf(f, "\tmov c_%d -> ", -from); } else if (from) { - fprintf(f, "\tmov R%d", from); - reg = ctx->live_intervals[from]->reg; + fprintf(f, "\tmov R%d", ctx->vregs[from]); + reg = ctx->live_intervals[ctx->vregs[from]]->reg; if (reg >= 0) { fprintf(f, " [%%%s]", ir_reg_name(reg, type)); } @@ -165,8 +165,8 @@ static int ir_dump_dessa_move(ir_ctx *ctx, uint8_t type, int from, int to) } if (to) { - fprintf(f, "R%d", to); - reg = ctx->live_intervals[to]->reg; + fprintf(f, "R%d", ctx->vregs[to]); + reg = ctx->live_intervals[ctx->vregs[to]]->reg; if (reg >= 0) { fprintf(f, " [%%%s]", ir_reg_name(reg, type)); } diff --git a/ir_emit_c.c b/ir_emit_c.c index 7bf303d..edae95e 100644 --- a/ir_emit_c.c +++ b/ir_emit_c.c @@ -1,12 +1,12 @@ #include "ir.h" #include "ir_private.h" -static int ir_emit_dessa_move(ir_ctx *ctx, uint8_t type, int from, int to) +static int ir_emit_dessa_move(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to) { FILE *f = ctx->data; if (to) { - fprintf(f, "\td_%d = ", to); + fprintf(f, "\td_%d = ", ctx->vregs[to]); } else { fprintf(f, "\ttmp = "); } @@ -14,7 +14,7 @@ static int ir_emit_dessa_move(ir_ctx *ctx, uint8_t type, int from, int to) ir_print_const(ctx, &ctx->ir_base[from], f); fprintf(f, ";\n"); } else if (from) { - fprintf(f, "d_%d;\n", from); + fprintf(f, "d_%d;\n", ctx->vregs[from]); } else { fprintf(f, "tmp;\n"); } diff --git a/ir_ra.c b/ir_ra.c index 354750d..70502a4 100644 --- a/ir_ra.c +++ b/ir_ra.c @@ -951,8 +951,7 @@ int ir_gen_dessa_moves(ir_ctx *ctx, int b, emit_copy_t emit_copy) int succ, j, k = 0, n = 0; ir_block *bb, *succ_bb; ir_use_list *use_list; - uint8_t *type; - uint32_t *loc, *pred; + ir_ref *loc, *pred; uint32_t len; ir_bitset todo, ready; @@ -974,12 +973,11 @@ int ir_gen_dessa_moves(ir_ctx *ctx, int b, emit_copy_t emit_copy) } IR_ASSERT(k != 0); - type = ir_mem_calloc((ctx->vregs_count + 1), sizeof(uint8_t)); - loc = ir_mem_calloc((ctx->vregs_count + 1) * 2, sizeof(uint32_t)); - pred = loc + (ctx->vregs_count + 1); - len = ir_bitset_len(ctx->vregs_count + 1); - todo = ir_bitset_malloc(ctx->vregs_count + 1); - ready = ir_bitset_malloc(ctx->vregs_count + 1); + loc = ir_mem_calloc(ctx->insns_count * 2, sizeof(ir_ref)); + pred = loc + ctx->insns_count; + len = ir_bitset_len(ctx->insns_count); + todo = ir_bitset_malloc(ctx->insns_count); + ready = ir_bitset_malloc(ctx->insns_count); for (j = 0; j < use_list->count; j++) { ir_ref ref = ctx->use_edges[use_list->refs + j]; @@ -987,12 +985,11 @@ int ir_gen_dessa_moves(ir_ctx *ctx, int b, emit_copy_t emit_copy) if (insn->op == IR_PHI) { ir_ref input = insn->ops[k]; if (IR_IS_CONST_REF(input)) { - emit_copy(ctx, insn->type, input, ctx->vregs[ref]); + emit_copy(ctx, insn->type, input, ref); } else if (ctx->vregs[input] != ctx->vregs[ref]) { - loc[ctx->vregs[input]] = ctx->vregs[input]; - pred[ctx->vregs[ref]] = ctx->vregs[input]; - type[ctx->vregs[ref]] = insn->type; - ir_bitset_incl(todo, ctx->vregs[ref]); + loc[input] = input; + pred[ref] = input; + ir_bitset_incl(todo, ref); n++; } } @@ -1011,7 +1008,7 @@ int ir_gen_dessa_moves(ir_ctx *ctx, int b, emit_copy_t emit_copy) b = ir_bitset_pop_first(ready, len); a = pred[b]; c = loc[a]; - emit_copy(ctx, type[b], c, b); + emit_copy(ctx, ctx->ir_base[b].type, c, b); loc[a] = b; if (a == c && pred[a]) { ir_bitset_incl(ready, a); @@ -1019,7 +1016,7 @@ int ir_gen_dessa_moves(ir_ctx *ctx, int b, emit_copy_t emit_copy) } b = ir_bitset_pop_first(todo, len); if (b != loc[pred[b]]) { - emit_copy(ctx, type[b], b, 0); + emit_copy(ctx, ctx->ir_base[b].type, b, 0); loc[b] = 0; ir_bitset_incl(ready, b); } @@ -1028,7 +1025,6 @@ int ir_gen_dessa_moves(ir_ctx *ctx, int b, emit_copy_t emit_copy) ir_mem_free(ready); ir_mem_free(todo); ir_mem_free(loc); - ir_mem_free(type); return 1; } @@ -1639,7 +1635,7 @@ static ir_reg ir_allocate_blocked_reg(ir_ctx *ctx, int current, uint32_t len, ir IR_LOG_LSRA(" ---- Spill", i, other, ""); other = child; } else { - // TODO: this may cause enless loop + // TODO: this may cause endless loop } if (other) { @@ -1685,7 +1681,7 @@ static int ir_live_range_cmp(const void *r1, const void *r2, void *data) return lrg2->start - lrg1->start; } -static int ir_fix_dessa_tmps(ir_ctx *ctx, uint8_t type, int from, int to) +static int ir_fix_dessa_tmps(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to) { if (to == 0) { ir_block *bb = ctx->data; diff --git a/ir_x86.dasc b/ir_x86.dasc index e55232e..4cf5a08 100644 --- a/ir_x86.dasc +++ b/ir_x86.dasc @@ -402,32 +402,6 @@ || } |.endmacro -|.macro ASM_FP_REG_VREG_MOV, type, dst, src -|| do { -|| ir_reg _reg = ir_vreg_reg(ctx, src); -|| if (_reg >= 0) { -| ASM_FP_REG_REG_OP movaps, movapd, vmovaps, vmovapd, type, dst, _reg -|| } else { -|| int32_t offset = ir_vreg_spill_slot(ctx, src); -|| ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_RBP : IR_REG_RSP; -| ASM_FP_REG_MEM_OP movss, movsd, vmovss, vmovsd, type, dst, [Ra(fp)+offset] -|| } -|| } while (0); -|.endmacro - -|.macro ASM_FP_VREG_REG_MOV, type, dst, src -|| do { -|| ir_reg _reg = ir_vreg_reg(ctx, dst); -|| if (_reg >= 0) { -| ASM_FP_REG_REG_OP movaps, movapd, vmovaps, vmovapd, type, _reg, src -|| } else { -|| int32_t offset = ir_vreg_spill_slot(ctx, dst); -|| ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_RBP : IR_REG_RSP; -| ASM_FP_MEM_REG_OP movss, movsd, vmovss, vmovsd, type, [Ra(fp)+offset], src -|| } -|| } while (0); -|.endmacro - typedef struct _ir_backend_data { int32_t stack_frame_size; int32_t stack_frame_alignment; @@ -1409,26 +1383,6 @@ static int ir_skip_empty_blocks(ir_ctx *ctx, int b) return b; } -static ir_reg ir_vreg_reg(ir_ctx *ctx, ir_ref v) -{ - return v < 0 ? IR_REG_NONE : ctx->live_intervals[v]->reg; -} - -static ir_reg ir_vreg_spill_slot(ir_ctx *ctx, ir_ref v) -{ - ir_backend_data *data = ctx->data; - int32_t offset; - - IR_ASSERT(v >= 0); - offset = ctx->live_intervals[v]->stack_spill_pos; - IR_ASSERT(offset != 0); - if (ctx->flags & IR_USE_FRAME_POINTER) { - return offset - data->stack_frame_size - data->stack_frame_alignment - sizeof(void*); - } else { - return offset + data->stack_frame_alignment - sizeof(void*); - } -} - static ir_reg ir_ref_reg(ir_ctx *ctx, ir_ref ref) { return ref < 0 ? IR_REG_NONE : ctx->live_intervals[ctx->vregs[ref]]->reg; @@ -3773,69 +3727,60 @@ static void ir_emit_tailcall(ir_ctx *ctx, ir_ref def, ir_insn *insn) // } } -static int ir_emit_dessa_move(ir_ctx *ctx, uint8_t type, int from, int to) +static int ir_emit_dessa_move(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to) { ir_backend_data *data = ctx->data; dasm_State **Dst = &data->dasm_state; - ir_insn *from_insn; int8_t to_reg, from_reg; - ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_RBP : IR_REG_RSP; - from_insn =&ctx->ir_base[from]; if (IR_IS_TYPE_INT(type)) { - to_reg = to ? ir_vreg_reg(ctx, to) : IR_REG_RAX; // %rax is a temporary register - from_reg = from ? ir_vreg_reg(ctx, from) : IR_REG_RAX; // %rax is a temporary register + to_reg = to ? ir_ref_reg(ctx, to) : IR_REG_RAX; // TODO: %rax is a temporary register (see ir_fix_dessa_tmps) + from_reg = from ? ir_ref_reg(ctx, from) : IR_REG_RAX; // TODO: %rax is a temporary register (see ir_fix_dessa_tmps) + if (from > 0 && from_reg >= 0 && ctx->live_intervals[ctx->vregs[from]]->top->stack_spill_pos) { + ir_emit_spill_load(ctx, type, from, from_reg); + } if (from_reg >= 0 && to_reg >= 0) { - | ASM_REG_REG_OP mov, type, to_reg, from_reg - return 1; - } else if (IR_IS_CONST_REF(from)) { - if (to_reg >= 0) { - ir_emit_load(ctx, type, from, to_reg); - return 1; - } else { - ir_insn *_insn = &ctx->ir_base[from]; - int32_t offset = ir_vreg_spill_slot(ctx, to); - if (ir_type_size[type] == 8 && !IR_IS_SIGNED_32BIT(_insn->val.i64)) { - from_reg = IR_REG_RDX; // TODO temporary register 2 - ir_emit_load(ctx, type, from, from_reg); - } else { - | ASM_MEM_IMM_OP mov, type, [Ra(fp)+offset], _insn->val.i32 - return 1; - } + if (from_reg != to_reg) { + | ASM_REG_REG_OP mov, type, to_reg, from_reg } + } else if (to_reg >= 0) { + ir_emit_load(ctx, type, from, to_reg); + } else if (from_reg >= 0) { + ir_emit_store(ctx, type, from_reg, to); + } else if (IR_IS_CONST_REF(from) && (ir_type_size[type] != 8 || IR_IS_SIGNED_32BIT(ctx->ir_base[from].val.i64))) { + | ASM_MREF_IMM_OP mov, type, to, ctx->ir_base[from].val.i32 + } else if (IR_IS_CONST_REF(from) && ir_type_size[type] == 8 && IR_IS_UNSIGNED_32BIT(ctx->ir_base[from].val.u64)) { + | mov Rd(to), ctx->ir_base[from].val.u32 + } else { + from_reg = IR_REG_RDX; // TODO temporary register 2 + ir_emit_load(ctx, type, from, from_reg); + ir_emit_store(ctx, type, from_reg, to); } - if (from_reg < 0) { - int32_t offset = ir_vreg_spill_slot(ctx, from); - from_reg = to_reg >= 0 ? to_reg : IR_REG_RDX; // TODO temporary register 2 - | ASM_REG_MEM_OP mov, type, from_reg, [Ra(fp)+offset] - } - if (from_reg != to_reg) { - int32_t offset = ir_vreg_spill_slot(ctx, to); - | ASM_MEM_REG_OP mov, type, [Ra(fp)+offset], from_reg + if (to > 0 && to_reg >= 0 && ctx->live_intervals[ctx->vregs[to]]->top->stack_spill_pos) { + ir_emit_spill_store(ctx, type, to_reg, to); } } else { - to_reg = to ? ir_vreg_reg(ctx, to) : IR_REG_XMM0; // %xmm0 is a temporary register - from_reg = from ? ir_vreg_reg(ctx, from) : IR_REG_XMM0; // %xmm0 is a temporary register - if (from_reg < 0) { - from_reg = (to_reg >= 0) ? to_reg : IR_REG_XMM0; // TODO: temporary register 2 - - if (IR_IS_CONST_REF(from)) { - ir_emit_fp_load(ctx, from_insn->type, from, from_reg); - } else { - | ASM_FP_REG_VREG_MOV type, from_reg, from + to_reg = to ? ir_ref_reg(ctx, to) : IR_REG_XMM0; // TODO: %xmm0 is a temporary register (see ir_fix_dessa_tmps) + from_reg = from ? ir_ref_reg(ctx, from) : IR_REG_XMM0; // TODO: %xmm0 is a temporary register (see ir_fix_dessa_tmps) + if (from > 0 && from_reg >= 0 && ctx->live_intervals[ctx->vregs[from]]->top->stack_spill_pos) { + ir_emit_spill_load(ctx, type, from, from_reg); + } + if (from_reg >= 0 && to_reg >= 0) { + if (from_reg != to_reg) { + | ASM_FP_REG_REG_OP movaps, movapd, vmovaps, vmovapd, type, to_reg, from_reg } + } else if (to_reg >= 0) { + ir_emit_fp_load(ctx, type, from, to_reg); + } else if (from_reg >= 0) { + ir_emit_fp_store(ctx, type, from_reg, to); + } else { + from_reg = IR_REG_XMM0; // TODO temporary register 2 + ir_emit_fp_load(ctx, type, from, from_reg); + ir_emit_fp_store(ctx, type, from_reg, to); } - if (from_reg != to_reg) { - | ASM_FP_VREG_REG_MOV type, to, from_reg + if (to > 0 && to_reg >= 0 && ctx->live_intervals[ctx->vregs[to]]->top->stack_spill_pos) { + ir_emit_spill_store(ctx, type, to_reg, to); } -#if 1 - if (to_reg >= 0 && ctx->live_intervals[to]->top->stack_spill_pos) { - /* spill store */ - int32_t offset = ir_vreg_spill_slot(ctx, to); - - | ASM_FP_MEM_REG_OP movss, movsd, vmovss, vmovsd, type, [Ra(fp)+offset], to_reg - } -#endif } return 1; } diff --git a/tests/debug/dessa_003.irt b/tests/debug/dessa_003.irt index c432eac..ff7a73d 100644 --- a/tests/debug/dessa_003.irt +++ b/tests/debug/dessa_003.irt @@ -41,9 +41,9 @@ test: .L1: testl %ecx, %ecx je .L2 - movl %esi, %eax - movl %edx, %esi - movl %eax, %edx + movl %edx, %eax + movl %esi, %edx + movl %eax, %esi jmp .L1 .L2: movl %edx, %eax