[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2.1 07/21] tcg: allow globals to overlap
From: |
Kirill Batuzov |
Subject: |
[Qemu-devel] [PATCH v2.1 07/21] tcg: allow globals to overlap |
Date: |
Thu, 2 Feb 2017 17:34:45 +0300 |
Sometimes the target architecture may allow some parts of a register to be
accessed as a different register. If both of these registers are
implemented as globals in QEMU, then their content will overlap and the
change to one global will also change the value of the other. To handle
such situation properly, some fixes are needed in the register allocator
and liveness analysis.
Signed-off-by: Kirill Batuzov <address@hidden>
---
tcg/optimize.c | 19 ++++++++-
tcg/tcg.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tcg/tcg.h | 20 +++++++++
3 files changed, 166 insertions(+), 1 deletion(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 2347ce3..7a69ff0 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -55,7 +55,7 @@ static inline bool temp_is_copy(TCGArg arg)
}
/* Reset TEMP's state, possibly removing the temp for the list of copies. */
-static void reset_temp(TCGArg temp)
+static void reset_this_temp(TCGArg temp)
{
temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
@@ -66,6 +66,23 @@ static void reset_temp(TCGArg temp)
temps[temp].mask = -1;
}
+static void reset_temp(TCGArg temp)
+{
+ int i;
+ TCGTemp *ts = &tcg_ctx.temps[temp];
+ reset_this_temp(temp);
+ if (ts->sub_temps) {
+ for (i = 0; ts->sub_temps[i] != (TCGArg)-1; i++) {
+ reset_this_temp(ts->sub_temps[i]);
+ }
+ }
+ if (ts->overlap_temps) {
+ for (i = 0; ts->overlap_temps[i] != (TCGArg)-1; i++) {
+ reset_this_temp(ts->overlap_temps[i]);
+ }
+ }
+}
+
/* Reset all temporaries, given that there are NB_TEMPS of them. */
static void reset_all_temps(int nb_temps)
{
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 27e5944..a8df040 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -623,9 +623,13 @@ int tcg_global_mem_new_internal(TCGType base_type,
TCGv_ptr base,
ts2->mem_base = base_ts;
ts2->mem_offset = offset + cur_offset;
ts2->name = g_strdup_printf("%s_%d", name, i);
+ ts2->sub_temps = NULL;
+ ts2->overlap_temps = NULL;
ts1 = ts2;
}
}
+ ts->sub_temps = NULL;
+ ts->overlap_temps = NULL;
return temp_idx(s, ts);
}
@@ -1514,6 +1518,35 @@ static int tcg_temp_overlap(TCGContext *s, const TCGTemp
*tmp,
}
}
+static void tcg_temp_arr_apply(const TCGArg *arr, uint8_t *temp_state,
+ uint8_t temp_val)
+{
+ TCGArg i;
+ if (!arr) {
+ return ;
+ }
+ for (i = 0; arr[i] != (TCGArg)-1; i++) {
+ temp_state[arr[i]] = temp_val;
+ }
+}
+
+static void tcg_sub_temps_dead(TCGContext *s, TCGArg tmp, uint8_t *temp_state)
+{
+ tcg_temp_arr_apply(s->temps[tmp].sub_temps, temp_state, TS_DEAD);
+}
+
+static void tcg_sub_temps_sync(TCGContext *s, TCGArg tmp, uint8_t *temp_state)
+{
+ tcg_temp_arr_apply(s->temps[tmp].sub_temps, temp_state, TS_MEM | TS_DEAD);
+}
+
+static void tcg_overlap_temps_sync(TCGContext *s, TCGArg tmp,
+ uint8_t *temp_state)
+{
+ tcg_temp_arr_apply(s->temps[tmp].overlap_temps, temp_state,
+ TS_MEM | TS_DEAD);
+}
+
/* Liveness analysis : update the opc_arg_life array to tell if a
given input arguments is dead. Instructions updating dead
temporaries are removed. */
@@ -1568,6 +1601,11 @@ static void liveness_pass_1(TCGContext *s, uint8_t
*temp_state)
if (temp_state[arg] & TS_MEM) {
arg_life |= SYNC_ARG << i;
}
+ /* sub_temps are also dead */
+ tcg_sub_temps_dead(&tcg_ctx, arg, temp_state);
+ /* overlap_temps need to go to memory */
+ tcg_overlap_temps_sync(&tcg_ctx, arg, temp_state);
+
temp_state[arg] = TS_DEAD;
}
@@ -1595,6 +1633,11 @@ static void liveness_pass_1(TCGContext *s, uint8_t
*temp_state)
for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
arg = args[i];
if (arg != TCG_CALL_DUMMY_ARG) {
+ /* both sub_temps and overlap_temps need to go
+ to memory */
+ tcg_sub_temps_sync(&tcg_ctx, arg, temp_state);
+ tcg_overlap_temps_sync(&tcg_ctx, arg, temp_state);
+
temp_state[arg] &= ~TS_DEAD;
}
}
@@ -1713,6 +1756,11 @@ static void liveness_pass_1(TCGContext *s, uint8_t
*temp_state)
if (temp_state[arg] & TS_MEM) {
arg_life |= SYNC_ARG << i;
}
+ /* sub_temps are also dead */
+ tcg_sub_temps_dead(&tcg_ctx, arg, temp_state);
+ /* overlap_temps need to go to memory */
+ tcg_overlap_temps_sync(&tcg_ctx, arg, temp_state);
+
temp_state[arg] = TS_DEAD;
}
@@ -1753,6 +1801,9 @@ static void liveness_pass_1(TCGContext *s, uint8_t
*temp_state)
/* input arguments are live for preceding opcodes */
for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
temp_state[args[i]] &= ~TS_DEAD;
+ /* both sub_temps and overlap_temps need to go to memory */
+ tcg_sub_temps_sync(&tcg_ctx, args[i], temp_state);
+ tcg_overlap_temps_sync(&tcg_ctx, args[i], temp_state);
}
}
break;
@@ -3139,3 +3190,80 @@ void tcg_register_jit(void *buf, size_t buf_size)
{
}
#endif /* ELF_HOST_MACHINE */
+
+static int tcg_temp_is_sub_temp(const TCGTemp *t1, const TCGTemp *t2)
+{
+ if (t2->mem_offset < t1->mem_offset) {
+ return 0;
+ }
+ if (t2->mem_offset + tcg_temp_size(t2) >
+ t1->mem_offset + tcg_temp_size(t1)) {
+ return 0;
+ }
+ return 1;
+}
+
+static int tcg_temp_is_overlap_temp(const TCGTemp *t1, const TCGTemp *t2)
+{
+ if (t2->mem_offset >= t1->mem_offset + tcg_temp_size(t1)) {
+ return 0;
+ }
+ if (t2->mem_offset + tcg_temp_size(t2) <= t1->mem_offset) {
+ return 0;
+ }
+ return 1;
+}
+
+void tcg_detect_overlapping_temps(TCGContext *s)
+{
+ int i, j;
+ int overlap_count, subtemps_count;
+ TCGArg *sub_temps, *overlap_temps;
+ TCGTemp *ts;
+ for (i = 0; i < s->nb_globals; i++) {
+ ts = &s->temps[i];
+ if (ts->fixed_reg ||
+ ts->mem_base != &s->temps[GET_TCGV_PTR(s->tcg_env)]) {
+ continue;
+ }
+ overlap_count = 0;
+ subtemps_count = 0;
+ overlap_temps = NULL;
+ sub_temps = NULL;
+ for (j = 0; j < s->nb_globals; j++) {
+ if (i != j && !s->temps[j].fixed_reg &&
+ s->temps[j].mem_base == &s->temps[GET_TCGV_PTR(s->tcg_env)]) {
+ if (tcg_temp_is_sub_temp(ts, &s->temps[j])) {
+ subtemps_count++;
+ } else if (tcg_temp_is_overlap_temp(ts, &s->temps[j])) {
+ overlap_count++;
+ }
+ }
+ }
+ if (subtemps_count == 0 && overlap_count == 0) {
+ continue;
+ }
+ if (subtemps_count > 0) {
+ sub_temps = g_malloc0((subtemps_count + 1) * sizeof(TCGArg));
+ sub_temps[subtemps_count] = (TCGArg)-1;
+ tcg_temp_set_sub_temps(i, sub_temps);
+ }
+ if (overlap_count > 0) {
+ overlap_temps = g_malloc0((overlap_count + 1) * sizeof(TCGArg));
+ overlap_temps[overlap_count] = (TCGArg)-1;
+ tcg_temp_set_overlap_temps(i, overlap_temps);
+ }
+ overlap_count = 0;
+ subtemps_count = 0;
+ for (j = 0; j < s->nb_globals; j++) {
+ if (i != j && !s->temps[j].fixed_reg &&
+ s->temps[j].mem_base == &s->temps[GET_TCGV_PTR(s->tcg_env)]) {
+ if (tcg_temp_is_sub_temp(ts, &s->temps[j])) {
+ sub_temps[subtemps_count++] = (TCGArg)j;
+ } else if (tcg_temp_is_overlap_temp(ts, &s->temps[j])) {
+ overlap_temps[overlap_count++] = (TCGArg)j;
+ }
+ }
+ }
+ }
+}
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 0e1fbe9..01299cc 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -634,6 +634,14 @@ typedef struct TCGTemp {
struct TCGTemp *mem_base;
intptr_t mem_offset;
const char *name;
+
+ /* -1 terminated array of temps that are parts of this temp.
+ All bits of them are part of this temp. */
+ const TCGArg *sub_temps;
+ /* -1 terminated array of temps that overlap with this temp.
+ Some bits of them are part of this temp, but some are not. sub_temps
+ are not included here. */
+ const TCGArg *overlap_temps;
} TCGTemp;
typedef struct TCGContext TCGContext;
@@ -837,6 +845,16 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb);
void tcg_set_frame(TCGContext *s, TCGReg reg, intptr_t start, intptr_t size);
+static inline void tcg_temp_set_sub_temps(TCGArg temp, const TCGArg *arr)
+{
+ tcg_ctx.temps[temp].sub_temps = arr;
+}
+
+static inline void tcg_temp_set_overlap_temps(TCGArg temp, const TCGArg *arr)
+{
+ tcg_ctx.temps[temp].overlap_temps = arr;
+}
+
int tcg_global_mem_new_internal(TCGType, TCGv_ptr, intptr_t, const char *);
TCGv_i32 tcg_global_reg_new_i32(TCGReg reg, const char *name);
@@ -1382,4 +1400,6 @@ void helper_atomic_sto_be_mmu(CPUArchState *env,
target_ulong addr, Int128 val,
#endif /* CONFIG_ATOMIC128 */
+void tcg_detect_overlapping_temps(TCGContext *s);
+
#endif /* TCG_H */
--
2.1.4
- [Qemu-devel] [PATCH v2.1 00/20] Emulate guest vector operations with host vector operations, Kirill Batuzov, 2017/02/02
- [Qemu-devel] [PATCH v2.1 09/21] target/arm: support access to vector guest registers as globals, Kirill Batuzov, 2017/02/02
- [Qemu-devel] [PATCH v2.1 03/21] tcg: support representing vector type with smaller vector or scalar types, Kirill Batuzov, 2017/02/02
- [Qemu-devel] [PATCH v2.1 17/21] tcg: introduce qemu_ld_v128 and qemu_st_v128 opcodes, Kirill Batuzov, 2017/02/02
- [Qemu-devel] [PATCH v2.1 01/21] tcg: add support for 128bit vector type, Kirill Batuzov, 2017/02/02
- [Qemu-devel] [PATCH v2.1 16/21] tcg: introduce new TCGMemOp - MO_128, Kirill Batuzov, 2017/02/02
- [Qemu-devel] [PATCH v2.1 02/21] tcg: add support for 64bit vector type, Kirill Batuzov, 2017/02/02
- [Qemu-devel] [PATCH v2.1 18/21] softmmu: create helpers for vector loads, Kirill Batuzov, 2017/02/02
- [Qemu-devel] [PATCH v2.1 19/21] tcg/i386: add support for qemu_ld_v128/qemu_st_v128 ops, Kirill Batuzov, 2017/02/02
- [Qemu-devel] [PATCH v2.1 07/21] tcg: allow globals to overlap,
Kirill Batuzov <=
- [Qemu-devel] [PATCH v2.1 14/21] tcg: do not rely on exact values of MO_BSWAP or MO_SIGN in backend, Kirill Batuzov, 2017/02/02
- [Qemu-devel] [PATCH v2.1 04/21] tcg: add ld_v128, ld_v64, st_v128 and st_v64 opcodes, Kirill Batuzov, 2017/02/02
- [Qemu-devel] [PATCH v2.1 06/21] tcg: use results of alias analysis in liveness analysis, Kirill Batuzov, 2017/02/02
- [Qemu-devel] [PATCH v2.1 10/21] target/arm: use vector opcode to handle vadd.<size> instruction, Kirill Batuzov, 2017/02/02
- [Qemu-devel] [PATCH v2.1 13/21] tcg/i386: support remaining vector addition operations, Kirill Batuzov, 2017/02/02
[Qemu-devel] [PATCH v2.1 21/21] tcg/README: update README to include information about vector opcodes, Kirill Batuzov, 2017/02/02
[Qemu-devel] [PATCH v2.1 11/21] tcg/i386: add support for vector opcodes, Kirill Batuzov, 2017/02/02