diff options
author | Aurelien Jarno <aurelien@aurel32.net> | 2012-10-09 21:53:08 +0200 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2012-10-28 14:54:22 +0100 |
commit | 3d5c5f876d171983d614925eebe4f0edccbb75be (patch) | |
tree | b8af1e21359eb45a93a57b0b19b27412c0223084 | |
parent | b202d41ee705a7a6152d03eb362e2e2147505022 (diff) |
tcg: synchronize globals for ops with side effects
Operations with side effects (in practice qemu_ld/st ops), only need to
synchronize globals to make sure the CPU state is consistent in case of
exception.
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
-rw-r--r-- | tcg/tcg.c | 33 | ||||
-rw-r--r-- | tcg/tcg.h | 4 |
2 files changed, 26 insertions, 11 deletions
@@ -1407,9 +1407,8 @@ static void tcg_liveness_analysis(TCGContext *s) /* if end of basic block, update */ if (def->flags & TCG_OPF_BB_END) { tcg_la_bb_end(s, dead_temps, mem_temps); - } else if (def->flags & TCG_OPF_CALL_CLOBBER) { - /* globals should go back to memory */ - memset(dead_temps, 1, s->nb_globals); + } else if (def->flags & TCG_OPF_SIDE_EFFECTS) { + /* globals should be synced to memory */ memset(mem_temps, 1, s->nb_globals); } @@ -1670,6 +1669,23 @@ static void save_globals(TCGContext *s, TCGRegSet allocated_regs) } } +/* sync globals to their canonical location and assume they can be + read by the following code. 'allocated_regs' is used in case a + temporary registers needs to be allocated to store a constant. */ +static void sync_globals(TCGContext *s, TCGRegSet allocated_regs) +{ + int i; + + for (i = 0; i < s->nb_globals; i++) { +#ifdef USE_LIVENESS_ANALYSIS + assert(s->temps[i].val_type != TEMP_VAL_REG || s->temps[i].fixed_reg || + s->temps[i].mem_coherent); +#else + temp_sync(s, i, allocated_regs); +#endif + } +} + /* at the end of a basic block, we assume all temporaries are dead and all globals are stored at their canonical location. */ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs) @@ -1907,12 +1923,11 @@ static void tcg_reg_alloc_op(TCGContext *s, tcg_reg_free(s, reg); } } - /* XXX: for load/store we could do that only for the slow path - (i.e. when a memory callback is called) */ - - /* store globals and free associated registers (we assume the insn - can modify any global. */ - save_globals(s, allocated_regs); + } + if (def->flags & TCG_OPF_SIDE_EFFECTS) { + /* sync globals if the op has side effects and might trigger + an exception. */ + sync_globals(s, allocated_regs); } /* satisfy the output constraints */ @@ -530,8 +530,8 @@ enum { TCG_OPF_BB_END = 0x01, /* Instruction clobbers call registers and potentially update globals. */ TCG_OPF_CALL_CLOBBER = 0x02, - /* Instruction has side effects: it cannot be removed - if its outputs are not used. */ + /* Instruction has side effects: it cannot be removed if its outputs + are not used, and might trigger exceptions. */ TCG_OPF_SIDE_EFFECTS = 0x04, /* Instruction operands are 64-bits (otherwise 32-bits). */ TCG_OPF_64BIT = 0x08, |