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:
Dmitry Stogov 2023-05-17 22:37:45 +03:00
parent af7117a3b7
commit c9fa8dfebd
16 changed files with 237 additions and 304 deletions

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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