Make DESSA API use "ir_ref" instead of "virtual register number"

(0 - is still a temporary register)
This commit is contained in:
Dmitry Stogov 2022-05-06 16:19:57 +03:00
parent b2033ebaf9
commit 69b5a852e5
6 changed files with 66 additions and 125 deletions

2
ir.h
View File

@ -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;

View File

@ -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));
}

View File

@ -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");
}

32
ir_ra.c
View File

@ -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;

View File

@ -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;
}

View File

@ -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