From 3653771265128f5d33d12069eeb5f5d6e049ec9e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 20 Feb 2018 19:24:31 -0500 Subject: [PATCH] tcg: Allocate indirect_base temporaries in a different order Since we've not got liveness analysis for indirect bases, placing them at the end of the call-saved registers makes it more likely that it'll stay live. Backports commit 91478cefaaf2fa678e56df8635b34957f4d5d565 from qemu --- qemu/tcg/tcg.c | 41 ++++++++++++++++++++++++++++++----------- qemu/tcg/tcg.h | 3 +++ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/qemu/tcg/tcg.c b/qemu/tcg/tcg.c index 49d45d81..c9c8259f 100644 --- a/qemu/tcg/tcg.c +++ b/qemu/tcg/tcg.c @@ -352,6 +352,21 @@ void tcg_context_init(TCGContext *s) } tcg_target_init(s); + + /* Reverse the order of the saved registers, assuming they're all at + the start of tcg_target_reg_alloc_order. */ + for (n = 0; n < ARRAY_SIZE(tcg_target_reg_alloc_order); ++n) { + int r = tcg_target_reg_alloc_order[n]; + if (tcg_regset_test_reg(s->tcg_target_call_clobber_regs, r)) { + break; + } + } + for (i = 0; i < n; ++i) { + s->indirect_reg_alloc_order[i] = tcg_target_reg_alloc_order[n - 1 - i]; + } + for (; i < ARRAY_SIZE(tcg_target_reg_alloc_order); ++i) { + s->indirect_reg_alloc_order[i] = tcg_target_reg_alloc_order[i]; + } } void tcg_prologue_init(TCGContext *s) @@ -1764,24 +1779,26 @@ static void tcg_reg_free(TCGContext *s, TCGReg reg, TCGRegSet allocated_regs) /* Allocate a register belonging to reg1 & ~reg2 */ static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet desired_regs, - TCGRegSet allocated_regs) + TCGRegSet allocated_regs, bool rev) { - int i; + int i, n = ARRAY_SIZE(tcg_target_reg_alloc_order); + const int *order; TCGReg reg; TCGRegSet reg_ct; tcg_regset_andnot(reg_ct, desired_regs, allocated_regs); + order = rev ? s->indirect_reg_alloc_order : tcg_target_reg_alloc_order; /* first try free registers */ - for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) { - reg = tcg_target_reg_alloc_order[i]; + for(i = 0; i < n; i++) { + reg = order[i]; if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == NULL) return reg; } /* XXX: do better spill choice */ - for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) { - reg = tcg_target_reg_alloc_order[i]; + for(i = 0; i < n; i++) { + reg = order[i]; if (tcg_regset_test_reg(reg_ct, reg)) { tcg_reg_free(s, reg, allocated_regs); return reg; @@ -1802,12 +1819,12 @@ static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs, case TEMP_VAL_REG: return; case TEMP_VAL_CONST: - reg = tcg_reg_alloc(s, desired_regs, allocated_regs); + reg = tcg_reg_alloc(s, desired_regs, allocated_regs, ts->indirect_base); tcg_out_movi(s, ts->type, reg, ts->val); ts->mem_coherent = 0; break; case TEMP_VAL_MEM: - reg = tcg_reg_alloc(s, desired_regs, allocated_regs); + reg = tcg_reg_alloc(s, desired_regs, allocated_regs, ts->indirect_base); if (ts->indirect_reg) { tcg_regset_set_reg(allocated_regs, reg); temp_load(s, ts->mem_base, @@ -2042,7 +2059,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def, input one. */ tcg_regset_set_reg(allocated_regs, ts->reg); ots->reg = tcg_reg_alloc(s, (TCGRegSet)s->tcg_target_available_regs[otype], - allocated_regs); + allocated_regs, ots->indirect_base); } tcg_out_mov(s, otype, ots->reg, ts->reg); } @@ -2118,7 +2135,8 @@ static void tcg_reg_alloc_op(TCGContext *s, allocate_in_reg: /* allocate a new register matching the constraint and move the temporary register into it */ - reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs); + reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs, + ts->indirect_base); tcg_out_mov(s, ts->type, reg, ts->reg); } new_args[i] = reg; @@ -2167,7 +2185,8 @@ static void tcg_reg_alloc_op(TCGContext *s, tcg_regset_test_reg(arg_ct->u.regs, reg)) { goto oarg_end; } - reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs); + reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs, + ts->indirect_base); } tcg_regset_set_reg(allocated_regs, reg); /* if a fixed register is used, then a move will be done afterwards */ diff --git a/qemu/tcg/tcg.h b/qemu/tcg/tcg.h index 8f5a8b5a..eb541c7b 100644 --- a/qemu/tcg/tcg.h +++ b/qemu/tcg/tcg.h @@ -751,6 +751,9 @@ struct TCGContext { /* qemu/tcg/tcg.c */ uint64_t tcg_target_call_clobber_regs; uint64_t tcg_target_available_regs[2]; + // Unicorn: Use a large array size to get around needing a file static + // Initially was using: ARRAY_SIZE(tcg_target_reg_alloc_order) as the size + int indirect_reg_alloc_order[50]; TCGOpDef *tcg_op_defs; /* qemu/tcg/optimize.c */