[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 07/26] tcg: rewrite tcg_reg_alloc_mov()
From: |
Aurelien Jarno |
Subject: |
[Qemu-devel] [PATCH 07/26] tcg: rewrite tcg_reg_alloc_mov() |
Date: |
Fri, 19 Oct 2012 23:38:56 +0200 |
Now that the liveness analysis provides more information, rewrite
tcg_reg_alloc_mov(). This changes the behaviour about propagating
constants and memory accesses. We now take the assumption that once
a value is loaded into a register (from memory or from a constant),
it's better to keep it there than to reload it later. This assumption
is now always almost correct given that we are now sure the
corresponding temp is going to be used later (otherwise it would have
been synchronized and marked as dead already). The assumption is wrong
if one of the op after clobbers some registers including the one
of the holding the temp (this can be avoided by allocating clobbered
registers last, which is what most TCG target do), or in case of lack
of available register.
Reviewed-by: Richard Henderson <address@hidden>
Signed-off-by: Aurelien Jarno <address@hidden>
---
tcg/tcg.c | 106 +++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 61 insertions(+), 45 deletions(-)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 6586385..b219a6d 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1714,64 +1714,80 @@ static void tcg_reg_alloc_mov(TCGContext *s, const
TCGOpDef *def,
const TCGArg *args, uint16_t dead_args,
uint8_t sync_args)
{
+ TCGRegSet allocated_regs;
TCGTemp *ts, *ots;
- int reg;
- const TCGArgConstraint *arg_ct;
+ const TCGArgConstraint *arg_ct, *oarg_ct;
+ tcg_regset_set(allocated_regs, s->reserved_regs);
ots = &s->temps[args[0]];
ts = &s->temps[args[1]];
- arg_ct = &def->args_ct[0];
+ oarg_ct = &def->args_ct[0];
+ arg_ct = &def->args_ct[1];
+
+ /* If the source value is not in a register, and we're going to be
+ forced to have it in a register in order to perform the copy,
+ then copy the SOURCE value into its own register first. That way
+ we don't have to reload SOURCE the next time it is used. */
+ if (((NEED_SYNC_ARG(0) || ots->fixed_reg) && ts->val_type != TEMP_VAL_REG)
+ || ts->val_type == TEMP_VAL_MEM) {
+ ts->reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
+ if (ts->val_type == TEMP_VAL_MEM) {
+ tcg_out_ld(s, ts->type, ts->reg, ts->mem_reg, ts->mem_offset);
+ ts->mem_coherent = 1;
+ } else if (ts->val_type == TEMP_VAL_CONST) {
+ tcg_out_movi(s, ts->type, ts->reg, ts->val);
+ }
+ s->reg_to_temp[ts->reg] = args[1];
+ ts->val_type = TEMP_VAL_REG;
+ }
- /* XXX: always mark arg dead if IS_DEAD_ARG(1) */
- if (ts->val_type == TEMP_VAL_REG) {
+ if (IS_DEAD_ARG(0) && !ots->fixed_reg) {
+ /* mov to a non-saved dead register makes no sense (even with
+ liveness analysis disabled). */
+ assert(NEED_SYNC_ARG(0));
+ /* The code above should have moved the temp to a register. */
+ assert(ts->val_type == TEMP_VAL_REG);
+ if (!ots->mem_allocated) {
+ temp_allocate_frame(s, args[0]);
+ }
+ tcg_out_st(s, ots->type, ts->reg, ots->mem_reg, ots->mem_offset);
+ if (IS_DEAD_ARG(1)) {
+ temp_dead(s, args[1]);
+ }
+ temp_dead(s, args[0]);
+ } else if (ts->val_type == TEMP_VAL_CONST) {
+ /* propagate constant */
+ if (ots->val_type == TEMP_VAL_REG) {
+ s->reg_to_temp[ots->reg] = -1;
+ }
+ ots->val_type = TEMP_VAL_CONST;
+ ots->val = ts->val;
+ } else {
+ /* The code in the first if block should have moved the
+ temp to a register. */
+ assert(ts->val_type == TEMP_VAL_REG);
if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
/* the mov can be suppressed */
- if (ots->val_type == TEMP_VAL_REG)
+ if (ots->val_type == TEMP_VAL_REG) {
s->reg_to_temp[ots->reg] = -1;
- reg = ts->reg;
+ }
+ ots->reg = ts->reg;
temp_dead(s, args[1]);
} else {
- if (ots->val_type == TEMP_VAL_REG) {
- reg = ots->reg;
- } else {
- reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
- }
- if (ts->reg != reg) {
- tcg_out_mov(s, ots->type, reg, ts->reg);
+ if (ots->val_type != TEMP_VAL_REG) {
+ /* When allocating a new register, make sure to not spill the
+ input one. */
+ tcg_regset_set_reg(allocated_regs, ts->reg);
+ ots->reg = tcg_reg_alloc(s, oarg_ct->u.regs, allocated_regs);
}
+ tcg_out_mov(s, ots->type, ots->reg, ts->reg);
}
- } else if (ts->val_type == TEMP_VAL_MEM) {
- if (ots->val_type == TEMP_VAL_REG) {
- reg = ots->reg;
- } else {
- reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
+ ots->val_type = TEMP_VAL_REG;
+ ots->mem_coherent = 0;
+ s->reg_to_temp[ots->reg] = args[0];
+ if (NEED_SYNC_ARG(0)) {
+ tcg_reg_sync(s, ots->reg);
}
- tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
- } else if (ts->val_type == TEMP_VAL_CONST) {
- if (ots->fixed_reg) {
- reg = ots->reg;
- tcg_out_movi(s, ots->type, reg, ts->val);
- } else {
- /* propagate constant */
- if (ots->val_type == TEMP_VAL_REG)
- s->reg_to_temp[ots->reg] = -1;
- ots->val_type = TEMP_VAL_CONST;
- ots->val = ts->val;
- if (NEED_SYNC_ARG(0)) {
- temp_sync(s, args[0], s->reserved_regs);
- }
- return;
- }
- } else {
- tcg_abort();
- }
- s->reg_to_temp[reg] = args[0];
- ots->reg = reg;
- ots->val_type = TEMP_VAL_REG;
- ots->mem_coherent = 0;
-
- if (NEED_SYNC_ARG(0)) {
- tcg_reg_sync(s, reg);
}
}
--
1.7.10.4
- [Qemu-devel] [PATCH v3 18/26] target-i386: rename helper flags, (continued)
- [Qemu-devel] [PATCH v3 18/26] target-i386: rename helper flags, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 05/26] tcg: rework liveness analysis, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 11/26] tcg: fix some op flags, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 25/26] target-xtensa: rename helper flags, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 09/26] tcg: start with local temps in TEMP_VAL_MEM state, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 17/26] target-cris: rename helper flags, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 21/26] target-ppc: rename helper flags, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 06/26] tcg: improve tcg_reg_alloc_movi(), Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 15/26] target-alpha: rename helper flags, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 24/26] target-sparc: rename helper flags, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH 07/26] tcg: rewrite tcg_reg_alloc_mov(),
Aurelien Jarno <=
- [Qemu-devel] [PATCH v3 20/26] target-mips: rename helper flags, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 26/26] tcg: remove compatiblity call flags, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 19/26] target-microblaze: rename helper flags, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 14/26] tcg: rework TCG helper flags, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 04/26] tcg: sync output arguments on liveness request, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 03/26] tcg: add temp_sync(), Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 08/26] tcg: always mark dead input arguments as dead, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 12/26] tcg: forbid ld/st function to modify globals, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 13/26] tcg: synchronize globals for ops with side effects, Aurelien Jarno, 2012/10/19
- [Qemu-devel] [PATCH v3 10/26] tcg: don't explicitly save globals and temps, Aurelien Jarno, 2012/10/19