mirror of
https://github.com/danog/ir.git
synced 2025-01-22 05:31:32 +01:00
Fix temporary register usage for parralel arguments passing
This commit is contained in:
parent
f086da2550
commit
8496780ece
8
TODO
8
TODO
@ -36,10 +36,10 @@
|
|||||||
- kill
|
- kill
|
||||||
- restricted regset
|
- restricted regset
|
||||||
+ must be in register
|
+ must be in register
|
||||||
? temporary registers
|
+ temporary registers
|
||||||
+ switch
|
+ switch
|
||||||
- arguments loading
|
? arguments loading
|
||||||
- parameter passing
|
+ parameter passing
|
||||||
+ dessa
|
+ dessa
|
||||||
? spills
|
? spills
|
||||||
+ spill everywhere code placement
|
+ spill everywhere code placement
|
||||||
@ -63,7 +63,7 @@
|
|||||||
+ temporary register (e.g. for unsupported immediate operand in mul, div, and 64-bit constants)
|
+ temporary register (e.g. for unsupported immediate operand in mul, div, and 64-bit constants)
|
||||||
+ temporary register for swap (dessa3.ir)
|
+ temporary register for swap (dessa3.ir)
|
||||||
+ temporary register for spill loads and stores
|
+ temporary register for spill loads and stores
|
||||||
- temporary register for swap during parallel parameter pssing
|
+ temporary register for swap during parallel parameter pssing
|
||||||
+ IR_CMP_AND_BRANCH_FP invalid position of tmp variables (fib.ir)
|
+ IR_CMP_AND_BRANCH_FP invalid position of tmp variables (fib.ir)
|
||||||
- stack arguments and parameters
|
- stack arguments and parameters
|
||||||
- return merge/split
|
- return merge/split
|
||||||
|
56
ir_x86.dasc
56
ir_x86.dasc
@ -730,6 +730,31 @@ ir_reg ir_uses_fixed_reg(ir_ctx *ctx, ir_ref ref, int op_num)
|
|||||||
return IR_REG_NONE;
|
return IR_REG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ir_may_need_tmp_reg_for_int_args_swap(ir_ctx *ctx, ir_ref ref)
|
||||||
|
{
|
||||||
|
ir_insn *insn = &ctx->ir_base[ref];
|
||||||
|
int j, n;
|
||||||
|
ir_type type;
|
||||||
|
int int_param = 0;
|
||||||
|
int int_reg_params_count = IR_REG_INT_ARGS;
|
||||||
|
|
||||||
|
n = ir_input_edges_count(ctx, insn);
|
||||||
|
for (j = 3; j <= n; j++) {
|
||||||
|
type = ctx->ir_base[insn->ops[j]].type;
|
||||||
|
if (IR_IS_TYPE_INT(type)) {
|
||||||
|
if (int_param < int_reg_params_count) {
|
||||||
|
if (int_param > 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int_param++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool ir_result_reuses_op1_reg(ir_ctx *ctx, ir_ref ref)
|
bool ir_result_reuses_op1_reg(ir_ctx *ctx, ir_ref ref)
|
||||||
{
|
{
|
||||||
ir_ref rule;
|
ir_ref rule;
|
||||||
@ -983,6 +1008,16 @@ cmp_fp:
|
|||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
|
case IR_CALL:
|
||||||
|
case IR_TAILCALL:
|
||||||
|
if (ir_may_need_tmp_reg_for_int_args_swap(ctx, ref)) {
|
||||||
|
tmp_regs[0].num = 1;
|
||||||
|
tmp_regs[0].type = IR_ADDR;
|
||||||
|
tmp_regs[0].start = IR_LOAD_SUB_REF;
|
||||||
|
tmp_regs[0].end = IR_USE_SUB_REF;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case IR_SKIP:
|
case IR_SKIP:
|
||||||
insn = &ctx->ir_base[ref];
|
insn = &ctx->ir_base[ref];
|
||||||
switch (insn->op) {
|
switch (insn->op) {
|
||||||
@ -3442,7 +3477,7 @@ typedef struct _ir_copy {
|
|||||||
ir_reg to;
|
ir_reg to;
|
||||||
} ir_copy;
|
} ir_copy;
|
||||||
|
|
||||||
static int ir_parallel_copy(ir_ctx *ctx, ir_copy *copies, int count)
|
static int ir_parallel_copy(ir_ctx *ctx, ir_copy *copies, int count, ir_reg tmp_reg, ir_reg tmp_fp_reg)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int8_t *pred, *loc, *types;
|
int8_t *pred, *loc, *types;
|
||||||
@ -3499,11 +3534,16 @@ static int ir_parallel_copy(ir_ctx *ctx, ir_copy *copies, int count)
|
|||||||
if (to != loc[from_reg]) {
|
if (to != loc[from_reg]) {
|
||||||
type = types[to];
|
type = types[to];
|
||||||
if (IR_IS_TYPE_INT(type)) {
|
if (IR_IS_TYPE_INT(type)) {
|
||||||
ir_emit_mov(ctx, type, IR_REG_R0, to); // TODO: Temporary register
|
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);
|
||||||
|
loc[to] = tmp_reg;
|
||||||
} else {
|
} else {
|
||||||
ir_emit_fp_mov(ctx, type, IR_REG_XMM7, to); // TODO: Temporary register
|
IR_ASSERT(tmp_fp_reg != IR_REG_NONE);
|
||||||
|
IR_ASSERT(tmp_fp_reg >= IR_REG_FP_FIRST && tmp_fp_reg <= IR_REG_FP_LAST);
|
||||||
|
ir_emit_fp_mov(ctx, type, tmp_fp_reg, to);
|
||||||
|
loc[to] = tmp_fp_reg;
|
||||||
}
|
}
|
||||||
loc[to] = 0;
|
|
||||||
IR_REGSET_INCL(ready, to);
|
IR_REGSET_INCL(ready, to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3513,7 +3553,7 @@ static int ir_parallel_copy(ir_ctx *ctx, ir_copy *copies, int count)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
static void ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg tmp_reg)
|
||||||
{
|
{
|
||||||
int j, n;
|
int j, n;
|
||||||
ir_ref arg;
|
ir_ref arg;
|
||||||
@ -3575,7 +3615,7 @@ static void ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (count) {
|
if (count) {
|
||||||
ir_parallel_copy(ctx, copies, count);
|
ir_parallel_copy(ctx, copies, count, tmp_reg, IR_REG_FP_LAST);
|
||||||
}
|
}
|
||||||
ir_mem_free(copies);
|
ir_mem_free(copies);
|
||||||
|
|
||||||
@ -3625,7 +3665,7 @@ static void ir_emit_call(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
dasm_State **Dst = &data->dasm_state;
|
dasm_State **Dst = &data->dasm_state;
|
||||||
ir_reg def_reg;
|
ir_reg def_reg;
|
||||||
|
|
||||||
ir_emit_arguments(ctx, def, insn);
|
ir_emit_arguments(ctx, def, insn, ctx->regs[def][1]);
|
||||||
|
|
||||||
if (IR_IS_CONST_REF(insn->op2)) {
|
if (IR_IS_CONST_REF(insn->op2)) {
|
||||||
const char *name = ir_get_str(ctx, ctx->ir_base[insn->op2].val.addr);
|
const char *name = ir_get_str(ctx, ctx->ir_base[insn->op2].val.addr);
|
||||||
@ -3688,7 +3728,7 @@ static void ir_emit_tailcall(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
{
|
{
|
||||||
ir_backend_data *data = ctx->data;
|
ir_backend_data *data = ctx->data;
|
||||||
dasm_State **Dst = &data->dasm_state;
|
dasm_State **Dst = &data->dasm_state;
|
||||||
ir_emit_arguments(ctx, def, insn);
|
ir_emit_arguments(ctx, def, insn, ctx->regs[def][1]);
|
||||||
|
|
||||||
ir_emit_epilogue(ctx);
|
ir_emit_epilogue(ctx);
|
||||||
|
|
||||||
|
34
tests/debug/call3.irt
Normal file
34
tests/debug/call3.irt
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
--TEST--
|
||||||
|
CALL with parallel argument passing
|
||||||
|
--ARGS--
|
||||||
|
-S
|
||||||
|
--CODE--
|
||||||
|
{
|
||||||
|
uintptr_t c_6 = "hello %d!\n";
|
||||||
|
l_1 = START(l_4);
|
||||||
|
int32_t p_1 = PARAM(l_1, "p1", 1);
|
||||||
|
int32_t p_2 = PARAM(l_1, "p2", 2);
|
||||||
|
int32_t p_3 = PARAM(l_1, "p3", 3);
|
||||||
|
int32_t p_4 = PARAM(l_1, "p4", 4);
|
||||||
|
uintptr_t fp = PARAM(l_1, "fp", 5);
|
||||||
|
uintptr_t f, l_11 = LOAD(l_1, fp);
|
||||||
|
int32_t d_2, l_2 = CALL/4(l_11, f, c_6, p_3, p_4, p_2);
|
||||||
|
int32_t d_3 = ADD(d_2, p_1);
|
||||||
|
l_4 = RETURN(l_2, d_3);
|
||||||
|
}
|
||||||
|
--EXPECT--
|
||||||
|
test:
|
||||||
|
subq $8, %rsp
|
||||||
|
movq %rbx, (%rsp)
|
||||||
|
movl %edi, %ebx
|
||||||
|
movq (%r8), %rax
|
||||||
|
movl %ecx, %r8d
|
||||||
|
movl %esi, %ecx
|
||||||
|
movl %edx, %esi
|
||||||
|
movl %r8d, %edx
|
||||||
|
leaq 0x12(%rip), %rdi
|
||||||
|
callq *%rax
|
||||||
|
leal (%rax, %rbx), %eax
|
||||||
|
movq (%rsp), %rbx
|
||||||
|
addq $8, %rsp
|
||||||
|
retq
|
Loading…
x
Reference in New Issue
Block a user