From c9fa8dfebd66981b2c0b4fbca185d2ebc7f2bb00 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 17 May 2023 22:37:45 +0300 Subject: [PATCH] Fixed SSA deconstruction Previously we performed parallel copy for virtual registers, now we do the same for the target CPU registers. --- ir_aarch64.dasc | 124 ++--------------------- ir_emit.c | 125 +++++++++++++++++++++++ ir_ra.c | 99 ++++++++++-------- ir_x86.dasc | 149 +++++----------------------- tests/debug.aarch64/regset-fib.irt | 2 +- tests/debug.aarch64/regset-fib2.irt | 2 +- tests/debug.aarch64/regset-fibi.irt | 4 +- tests/debug.aarch64/regset-test.irt | 4 +- tests/debug.x86/regset-fib.irt | 4 +- tests/debug.x86/regset-fib2.irt | 4 +- tests/debug.x86/regset-fibi.irt | 4 +- tests/debug.x86/regset-test.irt | 4 +- tests/debug/regset-fib.irt | 4 +- tests/debug/regset-fib2.irt | 4 +- tests/debug/regset-fibi.irt | 4 +- tests/debug/regset-test.irt | 4 +- 16 files changed, 237 insertions(+), 304 deletions(-) diff --git a/ir_aarch64.dasc b/ir_aarch64.dasc index 95261e3..4730e08 100644 --- a/ir_aarch64.dasc +++ b/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]; diff --git a/ir_emit.c b/ir_emit.c index da663b1..83ce0c0 100644 --- a/ir_emit.c +++ b/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; diff --git a/ir_ra.c b/ir_ra.c index 51e730b..b4c5eeb 100644 --- a/ir_ra.c +++ b/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; diff --git a/ir_x86.dasc b/ir_x86.dasc index d40deaf..35b712f 100644 --- a/ir_x86.dasc +++ b/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]; diff --git a/tests/debug.aarch64/regset-fib.irt b/tests/debug.aarch64/regset-fib.irt index 2823cc7..3f722f9 100644 --- a/tests/debug.aarch64/regset-fib.irt +++ b/tests/debug.aarch64/regset-fib.irt @@ -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) diff --git a/tests/debug.aarch64/regset-fib2.irt b/tests/debug.aarch64/regset-fib2.irt index 6cb465a..5dc2b55 100644 --- a/tests/debug.aarch64/regset-fib2.irt +++ b/tests/debug.aarch64/regset-fib2.irt @@ -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) diff --git a/tests/debug.aarch64/regset-fibi.irt b/tests/debug.aarch64/regset-fibi.irt index 3917e45..5f5816f 100644 --- a/tests/debug.aarch64/regset-fibi.irt +++ b/tests/debug.aarch64/regset-fibi.irt @@ -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) diff --git a/tests/debug.aarch64/regset-test.irt b/tests/debug.aarch64/regset-test.irt index 6094498..75f8d62 100644 --- a/tests/debug.aarch64/regset-test.irt +++ b/tests/debug.aarch64/regset-test.irt @@ -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) diff --git a/tests/debug.x86/regset-fib.irt b/tests/debug.x86/regset-fib.irt index c5d13ab..da15c78 100644 --- a/tests/debug.x86/regset-fib.irt +++ b/tests/debug.x86/regset-fib.irt @@ -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)! diff --git a/tests/debug.x86/regset-fib2.irt b/tests/debug.x86/regset-fib2.irt index c579dc7..950850f 100644 --- a/tests/debug.x86/regset-fib2.irt +++ b/tests/debug.x86/regset-fib2.irt @@ -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)! diff --git a/tests/debug.x86/regset-fibi.irt b/tests/debug.x86/regset-fibi.irt index abb8d66..48ffb89 100644 --- a/tests/debug.x86/regset-fibi.irt +++ b/tests/debug.x86/regset-fibi.irt @@ -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) diff --git a/tests/debug.x86/regset-test.irt b/tests/debug.x86/regset-test.irt index 5b33ab9..5396798 100644 --- a/tests/debug.x86/regset-test.irt +++ b/tests/debug.x86/regset-test.irt @@ -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) diff --git a/tests/debug/regset-fib.irt b/tests/debug/regset-fib.irt index b99b95f..5abfda2 100644 --- a/tests/debug/regset-fib.irt +++ b/tests/debug/regset-fib.irt @@ -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)! diff --git a/tests/debug/regset-fib2.irt b/tests/debug/regset-fib2.irt index 07e09ba..609c5c4 100644 --- a/tests/debug/regset-fib2.irt +++ b/tests/debug/regset-fib2.irt @@ -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)! diff --git a/tests/debug/regset-fibi.irt b/tests/debug/regset-fibi.irt index 3d3005d..1f83b04 100644 --- a/tests/debug/regset-fibi.irt +++ b/tests/debug/regset-fibi.irt @@ -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) diff --git a/tests/debug/regset-test.irt b/tests/debug/regset-test.irt index d10e5b0..45b90b3 100644 --- a/tests/debug/regset-test.irt +++ b/tests/debug/regset-test.irt @@ -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)