mirror of
https://github.com/danog/ir.git
synced 2024-11-26 20:34:53 +01:00
Fixed SSA deconstruction
Previously we performed parallel copy for virtual registers, now we do the same for the target CPU registers.
This commit is contained in:
parent
af7117a3b7
commit
c9fa8dfebd
124
ir_aarch64.dasc
124
ir_aarch64.dasc
@ -3387,7 +3387,7 @@ static int ir_parallel_copy(ir_ctx *ctx, ir_copy *copies, int count, ir_reg tmp_
|
||||
if (from_reg != to) {
|
||||
loc[from_reg] = from_reg;
|
||||
pred[to] = from_reg;
|
||||
types[to] = copies[i].type;
|
||||
types[from_reg] = copies[i].type;
|
||||
IR_REGSET_INCL(todo, to);
|
||||
}
|
||||
}
|
||||
@ -3404,8 +3404,8 @@ static int ir_parallel_copy(ir_ctx *ctx, ir_copy *copies, int count, ir_reg tmp_
|
||||
while (ready != IR_REGSET_EMPTY) {
|
||||
to = ir_regset_pop_first(&ready);
|
||||
from_reg = pred[to];
|
||||
type = types[to];
|
||||
c = loc[from_reg];
|
||||
type = types[from_reg];
|
||||
if (IR_IS_TYPE_INT(type)) {
|
||||
ir_emit_mov(ctx, type, to, c);
|
||||
} else {
|
||||
@ -3424,7 +3424,7 @@ static int ir_parallel_copy(ir_ctx *ctx, ir_copy *copies, int count, ir_reg tmp_
|
||||
to = ir_regset_pop_first(&todo);
|
||||
from_reg = pred[to];
|
||||
IR_ASSERT(to != loc[from_reg]);
|
||||
type = types[to];
|
||||
type = types[from_reg];
|
||||
if (IR_IS_TYPE_INT(type)) {
|
||||
IR_ASSERT(tmp_reg != IR_REG_NONE);
|
||||
IR_ASSERT(tmp_reg >= IR_REG_GP_FIRST && tmp_reg <= IR_REG_GP_LAST);
|
||||
@ -4179,107 +4179,6 @@ static void ir_emit_exitcall(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
}
|
||||
|
||||
static int ir_emit_dessa_move(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
uint32_t from_block = data->dessa_from_block;
|
||||
ir_block *from_bb = &ctx->cfg_blocks[from_block];
|
||||
ir_ref ref = from_bb->end;
|
||||
int8_t to_reg, from_reg;
|
||||
ir_block *to_bb;
|
||||
int j, k;
|
||||
ir_ref phi = 0;
|
||||
bool spill_store = 0;
|
||||
|
||||
IR_ASSERT(from_bb->successors_count == 1);
|
||||
to_bb = &ctx->cfg_blocks[ctx->cfg_edges[from_bb->successors]];
|
||||
k = ir_phi_input_number(ctx, to_bb, from_block);
|
||||
if (to) {
|
||||
phi = to;
|
||||
} else {
|
||||
ir_use_list *use_list = &ctx->use_lists[from];
|
||||
|
||||
for (j = 0; j < use_list->count; j++) {
|
||||
ir_ref use = ctx->use_edges[use_list->refs + j];
|
||||
ir_insn *insn = &ctx->ir_base[use];
|
||||
if (insn->op == IR_PHI && ir_insn_op(insn, k) == from && insn->op1 == to_bb->start) {
|
||||
phi = use;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
IR_ASSERT(phi != 0);
|
||||
|
||||
if (IR_IS_TYPE_INT(type)) {
|
||||
to_reg = to ? ctx->regs[phi][0] : ctx->regs[ref][0]; /* temporary register for integer swap (see ir_fix_dessa_tmps) */
|
||||
from_reg = from ? ir_get_alocated_reg(ctx, phi, k) : ctx->regs[ref][0]; /* temporary register for integer swap (see ir_fix_dessa_tmps) */
|
||||
if (from_reg != IR_REG_NONE && (from_reg & IR_REG_SPILL_LOAD)) {
|
||||
from_reg &= ~IR_REG_SPILL_LOAD;
|
||||
ir_emit_load(ctx, type, from_reg, from);
|
||||
}
|
||||
if (to_reg != IR_REG_NONE && (to_reg & IR_REG_SPILL_STORE)) {
|
||||
if (from_reg != IR_REG_NONE) {
|
||||
/* store directly into spill slot (valid only when to_reg register is not reused) */
|
||||
to_reg = IR_REG_NONE;
|
||||
} else {
|
||||
to_reg &= ~IR_REG_SPILL_STORE;
|
||||
spill_store = 1;
|
||||
}
|
||||
}
|
||||
if (from_reg != IR_REG_NONE && to_reg != IR_REG_NONE) {
|
||||
if (from_reg != to_reg) {
|
||||
ir_emit_mov(ctx, type, to_reg, from_reg);
|
||||
}
|
||||
} else if (to_reg != IR_REG_NONE) {
|
||||
ir_emit_load(ctx, type, to_reg, from);
|
||||
} else if (from_reg != IR_REG_NONE) {
|
||||
ir_emit_store(ctx, type, to, from_reg);
|
||||
} else if (IR_IS_CONST_REF(from) || !ir_is_same_mem(ctx, from, to)) {
|
||||
from_reg = ctx->regs[ref][1]; /* temporary register for int mem->mem (see ir_fix_dessa_tmps) */
|
||||
IR_ASSERT(from_reg != IR_REG_NONE);
|
||||
ir_emit_load(ctx, type, from_reg, from);
|
||||
ir_emit_store(ctx, type, to, from_reg);
|
||||
}
|
||||
if (spill_store) {
|
||||
ir_emit_store(ctx, type, to, to_reg);
|
||||
}
|
||||
} else {
|
||||
to_reg = to ? ctx->regs[phi][0] : ctx->regs[ref][2]; /* temporary register for fp swap (see ir_fix_dessa_tmps) */
|
||||
from_reg = from ? ir_get_alocated_reg(ctx, phi, k) : ctx->regs[ref][2]; /* temporary register for fp swap (see ir_fix_dessa_tmps) */
|
||||
if (from_reg != IR_REG_NONE && (from_reg & IR_REG_SPILL_LOAD)) {
|
||||
from_reg &= ~IR_REG_SPILL_LOAD;
|
||||
ir_emit_load(ctx, type, from_reg, from);
|
||||
}
|
||||
if (to_reg != IR_REG_NONE && (to_reg & IR_REG_SPILL_STORE)) {
|
||||
if (from_reg != IR_REG_NONE) {
|
||||
/* store directly into spill slot (valid only when to_reg register is not reused) */
|
||||
to_reg = IR_REG_NONE;
|
||||
} else {
|
||||
to_reg &= ~IR_REG_SPILL_STORE;
|
||||
spill_store = 1;
|
||||
}
|
||||
}
|
||||
if (from_reg != IR_REG_NONE && to_reg != IR_REG_NONE) {
|
||||
if (from_reg != to_reg) {
|
||||
ir_emit_fp_mov(ctx, type, to_reg, from_reg);
|
||||
}
|
||||
} else if (to_reg != IR_REG_NONE) {
|
||||
ir_emit_load(ctx, type, to_reg, from);
|
||||
} else if (from_reg != IR_REG_NONE) {
|
||||
ir_emit_store(ctx, type, to, from_reg);
|
||||
} else if (IR_IS_CONST_REF(from) || !ir_is_same_mem(ctx, from, to)) {
|
||||
from_reg = ctx->regs[ref][3]; /* temporary register for fp mem->mem (see ir_fix_dessa_tmps) */
|
||||
IR_ASSERT(from_reg != IR_REG_NONE);
|
||||
ir_emit_load(ctx, type, from_reg, from);
|
||||
ir_emit_store(ctx, type, to, from_reg);
|
||||
}
|
||||
if (spill_store) {
|
||||
ir_emit_store(ctx, type, to, to_reg);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ir_emit_param_move(ir_ctx *ctx, uint8_t type, ir_reg from_reg, ir_reg to_reg, ir_ref to, int32_t offset)
|
||||
{
|
||||
ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER;
|
||||
@ -4394,11 +4293,11 @@ static int ir_fix_dessa_tmps(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to)
|
||||
if (to == 0) {
|
||||
if (IR_IS_TYPE_INT(type)) {
|
||||
if (ctx->regs[ref][0] == IR_REG_NONE) {
|
||||
ctx->regs[ref][0] = ctx->regs[ref][1] != IR_REG_X0 ? IR_REG_X0 : IR_REG_X1; //???
|
||||
ctx->regs[ref][0] = IR_REG_X0;
|
||||
}
|
||||
} else if (IR_IS_TYPE_FP(type)) {
|
||||
if (ctx->regs[ref][2] == IR_REG_NONE) {
|
||||
ctx->regs[ref][2] = ctx->regs[ref][3] != IR_REG_V0 ? IR_REG_V0 : IR_REG_V1; //???
|
||||
if (ctx->regs[ref][1] == IR_REG_NONE) {
|
||||
ctx->regs[ref][1] = IR_REG_V0;
|
||||
}
|
||||
} else {
|
||||
IR_ASSERT(0);
|
||||
@ -4406,12 +4305,12 @@ static int ir_fix_dessa_tmps(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to)
|
||||
}
|
||||
} else if (from != 0) {
|
||||
if (IR_IS_TYPE_INT(type)) {
|
||||
if (ctx->regs[ref][1] == IR_REG_NONE) {
|
||||
ctx->regs[ref][1] = ctx->regs[ref][0] != IR_REG_X0 ? IR_REG_X0 : IR_REG_X1; //???
|
||||
if (ctx->regs[ref][0] == IR_REG_NONE) {
|
||||
ctx->regs[ref][0] = IR_REG_X0;
|
||||
}
|
||||
} else if (IR_IS_TYPE_FP(type)) {
|
||||
if (ctx->regs[ref][3] == IR_REG_NONE) {
|
||||
ctx->regs[ref][3] = ctx->regs[ref][2] != IR_REG_V0 ? IR_REG_V0 : IR_REG_V1; //???
|
||||
if (ctx->regs[ref][1] == IR_REG_NONE) {
|
||||
ctx->regs[ref][1] = IR_REG_V0;
|
||||
}
|
||||
} else {
|
||||
IR_ASSERT(0);
|
||||
@ -4986,8 +4885,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
|
||||
ir_emit_osr_entry_loads(ctx, b, bb);
|
||||
}
|
||||
if (bb->flags & IR_BB_DESSA_MOVES) {
|
||||
data.dessa_from_block = b;
|
||||
ir_gen_dessa_moves(ctx, b, ir_emit_dessa_move);
|
||||
ir_emit_dessa_moves(ctx, b, bb);
|
||||
}
|
||||
do {
|
||||
ir_ref succ = ctx->cfg_edges[bb->successors];
|
||||
|
125
ir_emit.c
125
ir_emit.c
@ -320,6 +320,7 @@ static void *ir_jmp_addr(ir_ctx *ctx, ir_insn *insn, ir_insn *addr_insn)
|
||||
|
||||
/* Forward Declarations */
|
||||
static void ir_emit_osr_entry_loads(ir_ctx *ctx, int b, ir_block *bb);
|
||||
static void ir_emit_dessa_moves(ir_ctx *ctx, int b, ir_block *bb);
|
||||
|
||||
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
|
||||
# include "ir_emit_x86.h"
|
||||
@ -370,6 +371,130 @@ static IR_NEVER_INLINE void ir_emit_osr_entry_loads(ir_ctx *ctx, int b, ir_block
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_emit_dessa_moves(ir_ctx *ctx, int b, ir_block *bb)
|
||||
{
|
||||
uint32_t succ, k, n = 0;
|
||||
ir_block *succ_bb;
|
||||
ir_use_list *use_list;
|
||||
ir_ref i, *p, ref, input;
|
||||
ir_insn *insn;
|
||||
bool do_third_pass = 0;
|
||||
ir_copy *copies;
|
||||
ir_reg tmp_reg = ctx->regs[bb->end][0];
|
||||
ir_reg tmp_fp_reg = ctx->regs[bb->end][1];
|
||||
ir_reg src, dst;
|
||||
|
||||
IR_ASSERT(bb->successors_count == 1);
|
||||
succ = ctx->cfg_edges[bb->successors];
|
||||
succ_bb = &ctx->cfg_blocks[succ];
|
||||
IR_ASSERT(succ_bb->predecessors_count > 1);
|
||||
use_list = &ctx->use_lists[succ_bb->start];
|
||||
k = ir_phi_input_number(ctx, succ_bb, b);
|
||||
|
||||
copies = ir_mem_malloc(use_list->count * sizeof(ir_copy));
|
||||
|
||||
for (i = 0, p = &ctx->use_edges[use_list->refs]; i < use_list->count; i++, p++) {
|
||||
ref = *p;
|
||||
insn = &ctx->ir_base[ref];
|
||||
if (insn->op == IR_PHI) {
|
||||
input = ir_insn_op(insn, k);
|
||||
if (IR_IS_CONST_REF(input)) {
|
||||
do_third_pass = 1;
|
||||
} else {
|
||||
dst = IR_REG_NUM(ctx->regs[ref][0]);
|
||||
src = ir_get_alocated_reg(ctx, ref, k);
|
||||
|
||||
if (dst == IR_REG_NONE) {
|
||||
/* STORE to memory */
|
||||
if (src == IR_REG_NONE) {
|
||||
if (!ir_is_same_mem(ctx, input, ref)) {
|
||||
ir_reg tmp = IR_IS_TYPE_INT(insn->type) ? tmp_reg : tmp_fp_reg;
|
||||
|
||||
IR_ASSERT(tmp != IR_REG_NONE);
|
||||
ir_emit_load(ctx, insn->type, tmp, input);
|
||||
ir_emit_store(ctx, insn->type, ref, tmp);
|
||||
}
|
||||
} else {
|
||||
if (src & IR_REG_SPILL_LOAD) {
|
||||
src &= ~IR_REG_SPILL_LOAD;
|
||||
ir_emit_load(ctx, insn->type, src, input);
|
||||
if (ir_is_same_mem(ctx, input, ref)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ir_emit_store(ctx, insn->type, src, ref);
|
||||
}
|
||||
} else {
|
||||
if (src == IR_REG_NONE) {
|
||||
do_third_pass = 1;
|
||||
} else {
|
||||
if (src & IR_REG_SPILL_LOAD) {
|
||||
src &= ~IR_REG_SPILL_LOAD;
|
||||
ir_emit_load(ctx, insn->type, src, input);
|
||||
}
|
||||
if (src != dst) {
|
||||
copies[n].type = insn->type;
|
||||
copies[n].from = src;
|
||||
copies[n].to = dst;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ctx->regs[ref][0] & IR_REG_SPILL_STORE) {
|
||||
do_third_pass = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
ir_parallel_copy(ctx, copies, n, tmp_reg, tmp_fp_reg);
|
||||
}
|
||||
ir_mem_free(copies);
|
||||
|
||||
if (do_third_pass) {
|
||||
for (i = 0, p = &ctx->use_edges[use_list->refs]; i < use_list->count; i++, p++) {
|
||||
ref = *p;
|
||||
insn = &ctx->ir_base[ref];
|
||||
if (insn->op == IR_PHI) {
|
||||
input = ir_insn_op(insn, k);
|
||||
dst = IR_REG_NUM(ctx->regs[ref][0]);
|
||||
|
||||
if (IR_IS_CONST_REF(input)) {
|
||||
if (dst == IR_REG_NONE) {
|
||||
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
|
||||
if (IR_IS_TYPE_INT(insn->type) && (ir_type_size[insn->type] != 8 || IR_IS_SIGNED_32BIT(ctx->ir_base[input].val.i64))) {
|
||||
ir_emit_store_imm(ctx, insn->type, ref, ctx->ir_base[input].val.i32);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
ir_reg tmp = IR_IS_TYPE_INT(insn->type) ? tmp_reg : tmp_fp_reg;
|
||||
|
||||
IR_ASSERT(tmp != IR_REG_NONE);
|
||||
ir_emit_load(ctx, insn->type, tmp, input);
|
||||
ir_emit_store(ctx, insn->type, ref, tmp);
|
||||
} else {
|
||||
ir_emit_load(ctx, insn->type, dst, input);
|
||||
}
|
||||
} else if (dst != IR_REG_NONE) {
|
||||
src = ir_get_alocated_reg(ctx, ref, k);
|
||||
|
||||
if (src == IR_REG_NONE) {
|
||||
if ((ctx->regs[ref][0] & IR_REG_SPILL_STORE) && ir_is_same_mem(ctx, input, ref)) {
|
||||
/* avoid LOAD and SAVE to the same memory */
|
||||
continue;
|
||||
}
|
||||
ir_emit_load(ctx, insn->type, dst, input);
|
||||
}
|
||||
}
|
||||
if (dst != IR_REG_NONE && (ctx->regs[ref][0] & IR_REG_SPILL_STORE)) {
|
||||
ir_emit_store(ctx, insn->type, ref, dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ir_match(ir_ctx *ctx)
|
||||
{
|
||||
uint32_t b;
|
||||
|
99
ir_ra.c
99
ir_ra.c
@ -2007,6 +2007,7 @@ int ir_gen_dessa_moves(ir_ctx *ctx, uint32_t b, emit_copy_t emit_copy)
|
||||
ir_insn *insn;
|
||||
uint32_t len;
|
||||
ir_bitset todo, ready;
|
||||
bool have_constants = 0;
|
||||
|
||||
bb = &ctx->cfg_blocks[b];
|
||||
if (!(bb->flags & IR_BB_DESSA_MOVES)) {
|
||||
@ -2031,7 +2032,7 @@ int ir_gen_dessa_moves(ir_ctx *ctx, uint32_t b, emit_copy_t emit_copy)
|
||||
if (insn->op == IR_PHI) {
|
||||
input = ir_insn_op(insn, k);
|
||||
if (IR_IS_CONST_REF(input)) {
|
||||
emit_copy(ctx, insn->type, input, ref);
|
||||
have_constants = 1;
|
||||
} else if (ctx->vregs[input] != ctx->vregs[ref]) {
|
||||
loc[ref] = pred[input] = 0;
|
||||
ir_bitset_incl(todo, ref);
|
||||
@ -2040,54 +2041,64 @@ int ir_gen_dessa_moves(ir_ctx *ctx, uint32_t b, emit_copy_t emit_copy)
|
||||
}
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
ir_mem_free(todo);
|
||||
ir_mem_free(loc);
|
||||
return 1;
|
||||
}
|
||||
if (n > 0) {
|
||||
ready = ir_bitset_malloc(ctx->insns_count);
|
||||
IR_BITSET_FOREACH(todo, len, ref) {
|
||||
insn = &ctx->ir_base[ref];
|
||||
IR_ASSERT(insn->op == IR_PHI);
|
||||
input = ir_insn_op(insn, k);
|
||||
loc[input] = input;
|
||||
pred[ref] = input;
|
||||
} IR_BITSET_FOREACH_END();
|
||||
|
||||
ready = ir_bitset_malloc(ctx->insns_count);
|
||||
IR_BITSET_FOREACH(todo, len, ref) {
|
||||
insn = &ctx->ir_base[ref];
|
||||
IR_ASSERT(insn->op == IR_PHI);
|
||||
input = ir_insn_op(insn, k);
|
||||
loc[input] = input;
|
||||
pred[ref] = input;
|
||||
} IR_BITSET_FOREACH_END();
|
||||
|
||||
IR_BITSET_FOREACH(todo, len, i) {
|
||||
if (!loc[i]) {
|
||||
ir_bitset_incl(ready, i);
|
||||
}
|
||||
} IR_BITSET_FOREACH_END();
|
||||
|
||||
while (1) {
|
||||
ir_ref a, b, c;
|
||||
|
||||
while ((b = ir_bitset_pop_first(ready, len)) >= 0) {
|
||||
a = pred[b];
|
||||
c = loc[a];
|
||||
emit_copy(ctx, ctx->ir_base[b].type, c, b);
|
||||
ir_bitset_excl(todo, b);
|
||||
loc[a] = b;
|
||||
if (a == c && pred[a]) {
|
||||
ir_bitset_incl(ready, a);
|
||||
IR_BITSET_FOREACH(todo, len, i) {
|
||||
if (!loc[i]) {
|
||||
ir_bitset_incl(ready, i);
|
||||
}
|
||||
} IR_BITSET_FOREACH_END();
|
||||
|
||||
while (1) {
|
||||
ir_ref a, b, c;
|
||||
|
||||
while ((b = ir_bitset_pop_first(ready, len)) >= 0) {
|
||||
a = pred[b];
|
||||
c = loc[a];
|
||||
emit_copy(ctx, ctx->ir_base[b].type, c, b);
|
||||
ir_bitset_excl(todo, b);
|
||||
loc[a] = b;
|
||||
if (a == c && pred[a]) {
|
||||
ir_bitset_incl(ready, a);
|
||||
}
|
||||
}
|
||||
b = ir_bitset_pop_first(todo, len);
|
||||
if (b < 0) {
|
||||
break;
|
||||
}
|
||||
IR_ASSERT(b != loc[pred[b]]);
|
||||
emit_copy(ctx, ctx->ir_base[b].type, b, 0);
|
||||
loc[b] = 0;
|
||||
ir_bitset_incl(ready, b);
|
||||
}
|
||||
b = ir_bitset_pop_first(todo, len);
|
||||
if (b < 0) {
|
||||
break;
|
||||
}
|
||||
IR_ASSERT(b != loc[pred[b]]);
|
||||
emit_copy(ctx, ctx->ir_base[b].type, b, 0);
|
||||
loc[b] = 0;
|
||||
ir_bitset_incl(ready, b);
|
||||
|
||||
ir_mem_free(ready);
|
||||
}
|
||||
|
||||
ir_mem_free(ready);
|
||||
ir_mem_free(todo);
|
||||
ir_mem_free(loc);
|
||||
|
||||
if (have_constants) {
|
||||
for (i = 0, p = &ctx->use_edges[use_list->refs]; i < use_list->count; i++, p++) {
|
||||
ref = *p;
|
||||
insn = &ctx->ir_base[ref];
|
||||
if (insn->op == IR_PHI) {
|
||||
input = ir_insn_op(insn, k);
|
||||
if (IR_IS_CONST_REF(input)) {
|
||||
emit_copy(ctx, insn->type, input, ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -3080,7 +3091,7 @@ static int ir_fix_dessa_tmps(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to)
|
||||
tmp_reg.start = IR_DEF_SUB_REF;
|
||||
tmp_reg.end = IR_SAVE_SUB_REF;
|
||||
} else if (IR_IS_TYPE_FP(type)) {
|
||||
tmp_reg.num = 2;
|
||||
tmp_reg.num = 1;
|
||||
tmp_reg.type = type;
|
||||
tmp_reg.start = IR_DEF_SUB_REF;
|
||||
tmp_reg.end = IR_SAVE_SUB_REF;
|
||||
@ -3090,12 +3101,12 @@ static int ir_fix_dessa_tmps(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to)
|
||||
}
|
||||
} else if (from != 0) {
|
||||
if (IR_IS_TYPE_INT(type)) {
|
||||
tmp_reg.num = 1;
|
||||
tmp_reg.num = 0;
|
||||
tmp_reg.type = type;
|
||||
tmp_reg.start = IR_DEF_SUB_REF;
|
||||
tmp_reg.end = IR_SAVE_SUB_REF;
|
||||
} else if (IR_IS_TYPE_FP(type)) {
|
||||
tmp_reg.num = 3;
|
||||
tmp_reg.num = 1;
|
||||
tmp_reg.type = type;
|
||||
tmp_reg.start = IR_DEF_SUB_REF;
|
||||
tmp_reg.end = IR_SAVE_SUB_REF;
|
||||
|
149
ir_x86.dasc
149
ir_x86.dasc
@ -2003,6 +2003,20 @@ static void ir_emit_store(ir_ctx *ctx, ir_type type, ir_ref dst, ir_reg reg)
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_emit_store_imm(ir_ctx *ctx, ir_type type, ir_ref dst, int32_t imm)
|
||||
{
|
||||
int32_t offset;
|
||||
ir_reg fp;
|
||||
ir_backend_data *data = ctx->data;
|
||||
dasm_State **Dst = &data->dasm_state;
|
||||
|
||||
IR_ASSERT(dst >= 0);
|
||||
IR_ASSERT(IR_IS_TYPE_INT(type));
|
||||
offset = ir_ref_spill_slot(ctx, dst, &fp);
|
||||
|
||||
| ASM_MEM_IMM_OP mov, type, [Ra(fp)+offset], imm
|
||||
}
|
||||
|
||||
static void ir_emit_mov(ir_ctx *ctx, ir_type type, ir_reg dst, ir_reg src)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
@ -5162,21 +5176,16 @@ static void ir_emit_vload(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
|
||||
static void ir_emit_vstore_int(ir_ctx *ctx, ir_ref ref, ir_insn *insn)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
dasm_State **Dst = &data->dasm_state;
|
||||
ir_insn *val_insn = &ctx->ir_base[insn->op3];
|
||||
ir_ref type = val_insn->type;
|
||||
ir_reg op3_reg = ctx->regs[ref][3];
|
||||
int32_t offset;
|
||||
ir_reg fp;
|
||||
|
||||
if ((op3_reg == IR_REG_NONE || (op3_reg & IR_REG_SPILL_LOAD))
|
||||
&& !IR_IS_CONST_REF(insn->op3) && ir_is_same_mem(ctx, insn->op3, insn->op2)) {
|
||||
return; // fake store
|
||||
}
|
||||
if (IR_IS_CONST_REF(insn->op3) && IR_IS_32BIT(type, val_insn->val)) {
|
||||
offset = ir_ref_spill_slot(ctx, insn->op2, &fp);
|
||||
| ASM_MEM_IMM_OP mov, type, [Ra(fp)+offset], val_insn->val.i32
|
||||
ir_emit_store_imm(ctx, type, insn->op2, val_insn->val.i32);
|
||||
} else {
|
||||
IR_ASSERT(op3_reg != IR_REG_NONE);
|
||||
if ((op3_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(insn->op3)) {
|
||||
@ -5816,7 +5825,7 @@ static int ir_parallel_copy(ir_ctx *ctx, ir_copy *copies, int count, ir_reg tmp_
|
||||
to = ir_regset_pop_first(&ready);
|
||||
from_reg = pred[to];
|
||||
c = loc[from_reg];
|
||||
type = types[c];
|
||||
type = types[from_reg];
|
||||
if (IR_IS_TYPE_INT(type)) {
|
||||
if (ir_type_size[type] > 2) {
|
||||
ir_emit_mov(ctx, type, to, c);
|
||||
@ -5841,7 +5850,6 @@ static int ir_parallel_copy(ir_ctx *ctx, ir_copy *copies, int count, ir_reg tmp_
|
||||
ir_emit_fp_mov(ctx, type, to, c);
|
||||
}
|
||||
IR_REGSET_EXCL(todo, to);
|
||||
types[to] = type;
|
||||
loc[from_reg] = to;
|
||||
if (from_reg == c && pred[from_reg] != IR_REG_NONE) {
|
||||
IR_REGSET_INCL(ready, from_reg);
|
||||
@ -5859,7 +5867,6 @@ static int ir_parallel_copy(ir_ctx *ctx, ir_copy *copies, int count, ir_reg tmp_
|
||||
IR_ASSERT(tmp_reg != IR_REG_NONE);
|
||||
IR_ASSERT(tmp_reg >= IR_REG_GP_FIRST && tmp_reg <= IR_REG_GP_LAST);
|
||||
ir_emit_mov(ctx, type, tmp_reg, to);
|
||||
types[tmp_reg] = type;
|
||||
loc[to] = tmp_reg;
|
||||
} else {
|
||||
IR_ASSERT(tmp_fp_reg != IR_REG_NONE);
|
||||
@ -7197,113 +7204,6 @@ static void ir_emit_exitcall(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
uint32_t from_block = data->dessa_from_block;
|
||||
ir_block *from_bb = &ctx->cfg_blocks[from_block];
|
||||
ir_ref ref = from_bb->end;
|
||||
int8_t to_reg, from_reg;
|
||||
ir_block *to_bb;
|
||||
int j, k;
|
||||
ir_ref phi = 0;
|
||||
bool spill_store = 0;
|
||||
|
||||
IR_ASSERT(from_bb->successors_count == 1);
|
||||
to_bb = &ctx->cfg_blocks[ctx->cfg_edges[from_bb->successors]];
|
||||
k = ir_phi_input_number(ctx, to_bb, from_block);
|
||||
if (to) {
|
||||
phi = to;
|
||||
} else {
|
||||
ir_use_list *use_list = &ctx->use_lists[from];
|
||||
|
||||
for (j = 0; j < use_list->count; j++) {
|
||||
ir_ref use = ctx->use_edges[use_list->refs + j];
|
||||
ir_insn *insn = &ctx->ir_base[use];
|
||||
if (insn->op == IR_PHI && ir_insn_op(insn, k) == from && insn->op1 == to_bb->start) {
|
||||
phi = use;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
IR_ASSERT(phi != 0);
|
||||
|
||||
if (IR_IS_TYPE_INT(type)) {
|
||||
to_reg = to ? ctx->regs[phi][0] : ctx->regs[ref][0]; /* temporary register for integer swap (see ir_fix_dessa_tmps) */
|
||||
from_reg = from ? ir_get_alocated_reg(ctx, phi, k) : ctx->regs[ref][0]; /* temporary register for integer swap (see ir_fix_dessa_tmps) */
|
||||
if (from_reg != IR_REG_NONE && (from_reg & IR_REG_SPILL_LOAD)) {
|
||||
from_reg &= ~IR_REG_SPILL_LOAD;
|
||||
ir_emit_load(ctx, type, from_reg, from);
|
||||
}
|
||||
if (to_reg != IR_REG_NONE && (to_reg & IR_REG_SPILL_STORE)) {
|
||||
if (from_reg != IR_REG_NONE) {
|
||||
/* store directly into spill slot (valid only when to_reg register is not reused) */
|
||||
to_reg = IR_REG_NONE;
|
||||
} else {
|
||||
to_reg &= ~IR_REG_SPILL_STORE;
|
||||
spill_store = 1;
|
||||
}
|
||||
}
|
||||
if (from_reg != IR_REG_NONE && to_reg != IR_REG_NONE) {
|
||||
if (from_reg != to_reg) {
|
||||
ir_emit_mov(ctx, type, to_reg, from_reg);
|
||||
}
|
||||
} else if (to_reg != IR_REG_NONE) {
|
||||
ir_emit_load(ctx, type, to_reg, from);
|
||||
} else if (from_reg != IR_REG_NONE) {
|
||||
ir_emit_store(ctx, type, to, from_reg);
|
||||
} else if (IR_IS_CONST_REF(from) && (ir_type_size[type] != 8 || IR_IS_SIGNED_32BIT(ctx->ir_base[from].val.i64))) {
|
||||
ir_reg fp;
|
||||
int32_t offset = ir_ref_spill_slot(ctx, to, &fp);
|
||||
|
||||
| ASM_MEM_IMM_OP mov, type, [Ra(fp)+offset], ctx->ir_base[from].val.i32
|
||||
} else if (IR_IS_CONST_REF(from) || !ir_is_same_mem(ctx, from, to)) {
|
||||
from_reg = ctx->regs[ref][1]; /* temporary register for int mem->mem (see ir_fix_dessa_tmps) */
|
||||
IR_ASSERT(from_reg != IR_REG_NONE);
|
||||
ir_emit_load(ctx, type, from_reg, from);
|
||||
ir_emit_store(ctx, type, to, from_reg);
|
||||
}
|
||||
if (spill_store) {
|
||||
ir_emit_store(ctx, type, to, to_reg);
|
||||
}
|
||||
} else {
|
||||
to_reg = to ? ctx->regs[phi][0] : ctx->regs[ref][2]; /* temporary register for fp swap (see ir_fix_dessa_tmps) */
|
||||
from_reg = from ? ir_get_alocated_reg(ctx, phi, k) : ctx->regs[ref][2]; /* temporary register for fp swap (see ir_fix_dessa_tmps) */
|
||||
if (from_reg != IR_REG_NONE && (from_reg & IR_REG_SPILL_LOAD)) {
|
||||
from_reg &= ~IR_REG_SPILL_LOAD;
|
||||
ir_emit_load(ctx, type, from_reg, from);
|
||||
}
|
||||
if (to_reg != IR_REG_NONE && (to_reg & IR_REG_SPILL_STORE)) {
|
||||
if (from_reg != IR_REG_NONE) {
|
||||
/* store directly into spill slot (valid only when to_reg register is not reused) */
|
||||
to_reg = IR_REG_NONE;
|
||||
} else {
|
||||
to_reg &= ~IR_REG_SPILL_STORE;
|
||||
spill_store = 1;
|
||||
}
|
||||
}
|
||||
if (from_reg != IR_REG_NONE && to_reg != IR_REG_NONE) {
|
||||
if (from_reg != to_reg) {
|
||||
ir_emit_fp_mov(ctx, type, to_reg, from_reg);
|
||||
}
|
||||
} else if (to_reg != IR_REG_NONE) {
|
||||
ir_emit_load(ctx, type, to_reg, from);
|
||||
} else if (from_reg != IR_REG_NONE) {
|
||||
ir_emit_store(ctx, type, to, from_reg);
|
||||
} else if (IR_IS_CONST_REF(from) || !ir_is_same_mem(ctx, from, to)) {
|
||||
from_reg = ctx->regs[ref][3]; /* temporary register for fp mem->mem (see ir_fix_dessa_tmps) */
|
||||
IR_ASSERT(from_reg != IR_REG_NONE);
|
||||
ir_emit_load(ctx, type, from_reg, from);
|
||||
ir_emit_store(ctx, type, to, from_reg);
|
||||
}
|
||||
if (spill_store) {
|
||||
ir_emit_store(ctx, type, to, to_reg);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ir_emit_param_move(ir_ctx *ctx, uint8_t type, ir_reg from_reg, ir_reg to_reg, ir_ref to, int32_t offset)
|
||||
{
|
||||
ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER;
|
||||
@ -7435,11 +7335,11 @@ static int ir_fix_dessa_tmps(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to)
|
||||
if (to == 0) {
|
||||
if (IR_IS_TYPE_INT(type)) {
|
||||
if (ctx->regs[ref][0] == IR_REG_NONE) {
|
||||
ctx->regs[ref][0] = ctx->regs[ref][1] != IR_REG_RAX ? IR_REG_RAX : IR_REG_RDX;
|
||||
ctx->regs[ref][0] = IR_REG_RAX;
|
||||
}
|
||||
} else if (IR_IS_TYPE_FP(type)) {
|
||||
if (ctx->regs[ref][2] == IR_REG_NONE) {
|
||||
ctx->regs[ref][2] = ctx->regs[ref][3] != IR_REG_XMM0 ? IR_REG_XMM0 : IR_REG_XMM1;
|
||||
if (ctx->regs[ref][1] == IR_REG_NONE) {
|
||||
ctx->regs[ref][1] = IR_REG_XMM0;
|
||||
}
|
||||
} else {
|
||||
IR_ASSERT(0);
|
||||
@ -7447,12 +7347,12 @@ static int ir_fix_dessa_tmps(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to)
|
||||
}
|
||||
} else if (from != 0) {
|
||||
if (IR_IS_TYPE_INT(type)) {
|
||||
if (ctx->regs[ref][1] == IR_REG_NONE) {
|
||||
ctx->regs[ref][1] = ctx->regs[ref][0] != IR_REG_RAX ? IR_REG_RAX : IR_REG_RDX;
|
||||
if (ctx->regs[ref][0] == IR_REG_NONE) {
|
||||
ctx->regs[ref][0] = IR_REG_RAX;
|
||||
}
|
||||
} else if (IR_IS_TYPE_FP(type)) {
|
||||
if (ctx->regs[ref][3] == IR_REG_NONE) {
|
||||
ctx->regs[ref][3] = ctx->regs[ref][2] != IR_REG_XMM0 ? IR_REG_XMM0 : IR_REG_XMM1;
|
||||
if (ctx->regs[ref][1] == IR_REG_NONE) {
|
||||
ctx->regs[ref][1] = IR_REG_XMM0;
|
||||
}
|
||||
} else {
|
||||
IR_ASSERT(0);
|
||||
@ -8438,8 +8338,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
|
||||
ir_emit_osr_entry_loads(ctx, b, bb);
|
||||
}
|
||||
if (bb->flags & IR_BB_DESSA_MOVES) {
|
||||
data.dessa_from_block = b;
|
||||
ir_gen_dessa_moves(ctx, b, ir_emit_dessa_move);
|
||||
ir_emit_dessa_moves(ctx, b, bb);
|
||||
}
|
||||
do {
|
||||
ir_ref succ = ctx->cfg_edges[bb->successors];
|
||||
|
@ -59,7 +59,7 @@ aarch64
|
||||
}
|
||||
{ # LIVE-RANGES (vregs_count=2)
|
||||
TMP
|
||||
[%d0]: [2.2-2.3)/3
|
||||
[%d0]: [2.2-2.3)/1
|
||||
[%d0]: [7.0-7.2)/6.2
|
||||
R1 (d_4, d_10) [SPILL=0x0]
|
||||
[%d0]: [3.0-7.0), DEF(4.2)
|
||||
|
@ -59,7 +59,7 @@ aarch64
|
||||
}
|
||||
{ # LIVE-RANGES (vregs_count=2)
|
||||
TMP
|
||||
[%d0]: [2.2-2.3)/3
|
||||
[%d0]: [2.2-2.3)/1
|
||||
[%d0]: [7.0-7.2)/6.2
|
||||
R1 (d_4, d_10) [SPILL=0x0]
|
||||
[%d0]: [3.0-7.0), DEF(4.2)
|
||||
|
@ -54,9 +54,9 @@ aarch64
|
||||
}
|
||||
{ # LIVE-RANGES (vregs_count=3)
|
||||
TMP
|
||||
[%w0]: [2.2-2.3)/1
|
||||
[%w0]: [2.2-2.3)/0
|
||||
[%w1]: [7.0-7.2)/6.2
|
||||
[%w0]: [12.2-12.3)/1
|
||||
[%w0]: [12.2-12.3)/0
|
||||
R1 (d_4) [%w0]: [3.0-9.1), DEF(4.2), USE(9.1/2)!
|
||||
R2 (d_5) [%w18]: [3.0-13.0), DEF(5.2), USE(7.1/6.1)!, USE(9.1/1)!, USE(10.0/4, hint=%w1), PHI_USE(12.2, phi=d_4/3)
|
||||
R3 (d_9) [%w20]: [9.2-13.0), DEF(9.2)!, PHI_USE(12.2, phi=d_5/3)
|
||||
|
@ -105,8 +105,8 @@ aarch64
|
||||
{ # LIVE-RANGES (vregs_count=12)
|
||||
TMP
|
||||
[%d0]: [5.0-5.2)/2
|
||||
[%d1]: [10.2-10.3)/3
|
||||
[%w0]: [10.2-10.3)/1
|
||||
[%d1]: [10.2-10.3)/1
|
||||
[%w0]: [10.2-10.3)/0
|
||||
[%d1]: [23.0-23.2)/22.2
|
||||
R1 (d_2) [SPILL=0x0]
|
||||
[%d0]: [2.3-5.0), DEF(2.3, hint=%d0)
|
||||
|
@ -59,8 +59,8 @@ x86
|
||||
}
|
||||
{ # LIVE-RANGES (vregs_count=3)
|
||||
TMP
|
||||
[%xmm0]: [2.2-2.3)/3
|
||||
[%xmm0]: [13.2-13.3)/3
|
||||
[%xmm0]: [2.2-2.3)/1
|
||||
[%xmm0]: [13.2-13.3)/1
|
||||
R1 (d_4) [%xmm1]: [3.0-10.1), DEF(4.2), USE(9.1/2), USE(10.1/2)
|
||||
R2 (d_5, d_9) [SPILL=0x0]
|
||||
[%xmm0]: [3.0-10.0), DEF(5.2), USE(7.1/6.1)!, USE(9.0/1)!, DEF(9.0)!, USE(10.0/1, hint=R3)!
|
||||
|
@ -59,8 +59,8 @@ x86
|
||||
}
|
||||
{ # LIVE-RANGES (vregs_count=3)
|
||||
TMP
|
||||
[%xmm0]: [2.2-2.3)/3
|
||||
[%xmm0]: [15.2-15.3)/3
|
||||
[%xmm0]: [2.2-2.3)/1
|
||||
[%xmm0]: [15.2-15.3)/1
|
||||
R1 (d_4) [%xmm1]: [3.0-10.1), DEF(4.2), USE(9.1/2), USE(10.1/2)
|
||||
R2 (d_5, d_9) [SPILL=0x0]
|
||||
[%xmm0]: [3.0-10.0), DEF(5.2), USE(7.1/6.1)!, USE(9.0/1)!, DEF(9.0)!, USE(10.0/1, hint=R3)!
|
||||
|
@ -54,8 +54,8 @@ x86
|
||||
}
|
||||
{ # LIVE-RANGES (vregs_count=3)
|
||||
TMP
|
||||
[%eax]: [2.2-2.3)/1
|
||||
[%eax]: [12.2-12.3)/1
|
||||
[%eax]: [2.2-2.3)/0
|
||||
[%eax]: [12.2-12.3)/0
|
||||
R1 (d_4) [%eax]: [3.0-9.1), DEF(4.2), USE(9.1/2)!
|
||||
R2 (d_5) [%ebx]: [3.0-13.0), DEF(5.2), USE(7.1/6.1), USE(9.1/1)!, USE(10.1/4), PHI_USE(12.2, phi=d_4/3)
|
||||
R3 (d_9) [%ebp]: [9.2-13.0), DEF(9.2)!, PHI_USE(12.2, phi=d_5/3)
|
||||
|
@ -104,8 +104,8 @@ x86
|
||||
}
|
||||
{ # LIVE-RANGES (vregs_count=12)
|
||||
TMP
|
||||
[%xmm0]: [10.2-10.3)/3
|
||||
[%eax]: [10.2-10.3)/1
|
||||
[%xmm0]: [10.2-10.3)/1
|
||||
[%eax]: [10.2-10.3)/0
|
||||
R1 (d_2)
|
||||
[%xmm0]: [2.2-10.2), DEF(2.2)!
|
||||
: [10.2-24.0), [26.0-29.0), [31.0-36.0)
|
||||
|
@ -59,8 +59,8 @@ x86_64
|
||||
}
|
||||
{ # LIVE-RANGES (vregs_count=3)
|
||||
TMP
|
||||
[%xmm0]: [2.2-2.3)/3
|
||||
[%xmm0]: [13.2-13.3)/3
|
||||
[%xmm0]: [2.2-2.3)/1
|
||||
[%xmm0]: [13.2-13.3)/1
|
||||
R1 (d_4) [%xmm1]: [3.0-10.1), DEF(4.2), USE(9.1/2), USE(10.1/2)
|
||||
R2 (d_5, d_9) [SPILL=0x0]
|
||||
[%xmm0]: [3.0-10.0), DEF(5.2), USE(7.1/6.1)!, USE(9.0/1)!, DEF(9.0)!, USE(10.0/1, hint=%xmm0, hint=R3)!
|
||||
|
@ -59,8 +59,8 @@ x86_64
|
||||
}
|
||||
{ # LIVE-RANGES (vregs_count=3)
|
||||
TMP
|
||||
[%xmm0]: [2.2-2.3)/3
|
||||
[%xmm0]: [15.2-15.3)/3
|
||||
[%xmm0]: [2.2-2.3)/1
|
||||
[%xmm0]: [15.2-15.3)/1
|
||||
R1 (d_4) [%xmm1]: [3.0-10.1), DEF(4.2), USE(9.1/2), USE(10.1/2)
|
||||
R2 (d_5, d_9) [SPILL=0x0]
|
||||
[%xmm0]: [3.0-10.0), DEF(5.2), USE(7.1/6.1)!, USE(9.0/1)!, DEF(9.0)!, USE(10.0/1, hint=%xmm0, hint=R3)!
|
||||
|
@ -54,8 +54,8 @@ x86_64
|
||||
}
|
||||
{ # LIVE-RANGES (vregs_count=3)
|
||||
TMP
|
||||
[%eax]: [2.2-2.3)/1
|
||||
[%eax]: [12.2-12.3)/1
|
||||
[%eax]: [2.2-2.3)/0
|
||||
[%eax]: [12.2-12.3)/0
|
||||
R1 (d_4) [%eax]: [3.0-9.1), DEF(4.2), USE(9.1/2)!
|
||||
R2 (d_5) [%ebx]: [3.0-13.0), DEF(5.2), USE(7.1/6.1), USE(9.1/1)!, USE(10.0/4, hint=%esi), PHI_USE(12.2, phi=d_4/3)
|
||||
R3 (d_9) [%ebp]: [9.2-13.0), DEF(9.2)!, PHI_USE(12.2, phi=d_5/3)
|
||||
|
@ -104,8 +104,8 @@ x86_64
|
||||
}
|
||||
{ # LIVE-RANGES (vregs_count=12)
|
||||
TMP
|
||||
[%xmm0]: [10.2-10.3)/3
|
||||
[%eax]: [10.2-10.3)/1
|
||||
[%xmm0]: [10.2-10.3)/1
|
||||
[%eax]: [10.2-10.3)/0
|
||||
R1 (d_2) [SPILL=0x0]
|
||||
[%xmm0]: [2.3-10.2), DEF(2.3, hint=%xmm0)
|
||||
: [10.2-24.0), [26.0-29.0), [31.0-36.0)
|
||||
|
Loading…
Reference in New Issue
Block a user