mirror of
https://github.com/danog/ir.git
synced 2025-01-22 05:31:32 +01:00
Make DESSA API use "ir_ref" instead of "virtual register number"
(0 - is still a temporary register)
This commit is contained in:
parent
b2033ebaf9
commit
69b5a852e5
2
ir.h
2
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;
|
||||
|
10
ir_dump.c
10
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));
|
||||
}
|
||||
|
@ -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
32
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;
|
||||
|
135
ir_x86.dasc
135
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user