[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC 12/14] tcg: Store pointers to temporaries directly in
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [RFC 12/14] tcg: Store pointers to temporaries directly in TCGArg |
Date: |
Wed, 16 Nov 2016 20:51:48 +0100 |
Signed-off-by: Richard Henderson <address@hidden>
---
tcg/optimize.c | 103 +++++++++++++++++++++++++++++++--------------------------
tcg/tcg.c | 28 ++++++++++------
tcg/tcg.h | 20 +++++------
3 files changed, 84 insertions(+), 67 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 0e5d9d8..06a8c13 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -33,19 +33,24 @@
glue(glue(case INDEX_op_, x), _i64)
struct tcg_temp_info {
- bool is_const;
- uint16_t prev_copy;
- uint16_t next_copy;
+ TCGTemp *prev_copy;
+ TCGTemp *next_copy;
tcg_target_ulong val;
tcg_target_ulong mask;
+ bool is_const;
};
static struct tcg_temp_info temps[TCG_MAX_TEMPS];
static TCGTempSet temps_used;
+static inline struct tcg_temp_info *ts_info(TCGTemp *ts)
+{
+ return ts->state_ptr;
+}
+
static inline struct tcg_temp_info *temp_info(TCGArg arg)
{
- return &temps[arg];
+ return ts_info(arg_temp(arg));
}
static inline bool temp_is_const(TCGArg arg)
@@ -55,20 +60,20 @@ static inline bool temp_is_const(TCGArg arg)
static inline bool temp_is_copy(TCGArg arg)
{
- return temp_info(arg)->next_copy != arg;
+ return temp_info(arg)->next_copy != arg_temp(arg);
}
/* Reset TEMP's state, possibly removing the temp for the list of copies. */
-static void reset_temp(TCGArg temp)
+static void reset_temp(TCGTemp *ts)
{
- struct tcg_temp_info *ti = temp_info(temp);
- struct tcg_temp_info *pi = temp_info(ti->prev_copy);
- struct tcg_temp_info *ni = temp_info(ti->next_copy);
+ struct tcg_temp_info *ti = ts_info(ts);
+ struct tcg_temp_info *pi = ts_info(ti->prev_copy);
+ struct tcg_temp_info *ni = ts_info(ti->next_copy);
ni->prev_copy = ti->prev_copy;
pi->next_copy = ti->next_copy;
- ti->next_copy = temp;
- ti->prev_copy = temp;
+ ti->next_copy = ts;
+ ti->prev_copy = ts;
ti->is_const = false;
ti->mask = -1;
}
@@ -82,13 +87,16 @@ static void reset_all_temps(int nb_temps)
/* Initialize and activate a temporary. */
static void init_temp_info(TCGArg temp)
{
- if (!test_bit(temp, temps_used.l)) {
- struct tcg_temp_info *ti = temp_info(temp);
- ti->next_copy = temp;
- ti->prev_copy = temp;
+ size_t idx = arg_index(temp);
+ if (!test_bit(idx, temps_used.l)) {
+ TCGTemp *ts = arg_temp(temp);
+ struct tcg_temp_info *ti = &temps[idx];
+ ts->state_ptr = ti;
+ ti->next_copy = ts;
+ ti->prev_copy = ts;
ti->is_const = false;
ti->mask = -1;
- set_bit(temp, temps_used.l);
+ set_bit(idx, temps_used.l);
}
}
@@ -128,27 +136,26 @@ static TCGOpcode op_to_movi(TCGOpcode op)
static TCGArg find_better_copy(TCGContext *s, TCGArg temp)
{
- TCGArg i;
+ TCGTemp *ts = arg_temp(temp);
+ TCGTemp *i;
/* If this is already a global, we can't do better. */
- if (temp < s->nb_globals) {
+ if (ts->temp_global) {
return temp;
}
/* Search for a global first. */
- for (i = temp_info(temp)->next_copy; i != temp;
- i = temp_info(i)->next_copy) {
- if (i < s->nb_globals) {
- return i;
+ for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
+ if (i->temp_global) {
+ return (uintptr_t)i;
}
}
/* If it is a temp, search for a temp local. */
- if (!s->temps[temp].temp_local) {
- for (i = temp_info(temp)->next_copy; i != temp;
- i = temp_info(i)->next_copy) {
- if (s->temps[i].temp_local) {
- return i;
+ if (!ts->temp_local) {
+ for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
+ if (i->temp_local) {
+ return (uintptr_t)i;
}
}
}
@@ -159,7 +166,9 @@ static TCGArg find_better_copy(TCGContext *s, TCGArg temp)
static bool temps_are_copies(TCGArg arg1, TCGArg arg2)
{
- TCGArg i;
+ TCGTemp *t1 = arg_temp(arg1);
+ TCGTemp *t2 = arg_temp(arg2);
+ TCGTemp *i;
if (arg1 == arg2) {
return true;
@@ -169,9 +178,8 @@ static bool temps_are_copies(TCGArg arg1, TCGArg arg2)
return false;
}
- for (i = temp_info(arg1)->next_copy; i != arg1;
- i = temp_info(i)->next_copy) {
- if (i == arg2) {
+ for (i = ts_info(t1)->next_copy; i != t1; i = ts_info(i)->next_copy) {
+ if (i == t2) {
return true;
}
}
@@ -184,11 +192,12 @@ static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op,
TCGArg *args,
{
TCGOpcode new_op = op_to_movi(op->opc);
tcg_target_ulong mask;
- struct tcg_temp_info *di = temp_info(dst);
+ TCGTemp *ds = arg_temp(dst);
+ struct tcg_temp_info *di = ts_info(ds);
op->opc = new_op;
- reset_temp(dst);
+ reset_temp(ds);
di->is_const = true;
di->val = val;
mask = val;
@@ -210,14 +219,16 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op,
TCGArg *args,
return;
}
- struct tcg_temp_info *di = temp_info(dst);
- struct tcg_temp_info *si = temp_info(src);
+ TCGTemp *ds = arg_temp(dst);
+ TCGTemp *ss = arg_temp(src);
+ struct tcg_temp_info *di = ts_info(ds);
+ struct tcg_temp_info *si = ts_info(ss);
TCGOpcode new_op = op_to_mov(op->opc);
tcg_target_ulong mask;
op->opc = new_op;
- reset_temp(dst);
+ reset_temp(ds);
mask = si->mask;
if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) {
/* High bits of the destination are now garbage. */
@@ -225,11 +236,11 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op,
TCGArg *args,
}
di->mask = mask;
- if (s->temps[src].type == s->temps[dst].type) {
+ if (ss->type == ds->type) {
di->next_copy = si->next_copy;
- di->prev_copy = src;
- temp_info(di->next_copy)->prev_copy = dst;
- si->next_copy = dst;
+ di->prev_copy = ss;
+ ts_info(di->next_copy)->prev_copy = ds;
+ si->next_copy = ds;
di->is_const = si->is_const;
di->val = si->val;
}
@@ -702,7 +713,7 @@ void tcg_optimize(TCGContext *s)
}
if (temp_is_const(args[1]) && temp_info(args[1])->val == 0) {
op->opc = neg_op;
- reset_temp(args[0]);
+ reset_temp(arg_temp(args[0]));
args[1] = args[2];
continue;
}
@@ -758,7 +769,7 @@ void tcg_optimize(TCGContext *s)
break;
}
op->opc = not_op;
- reset_temp(args[0]);
+ reset_temp(arg_temp(args[0]));
args[1] = args[i];
continue;
}
@@ -1270,7 +1281,7 @@ void tcg_optimize(TCGContext *s)
/* Simplify LT/GE comparisons vs zero to a single compare
vs the high word of the input. */
do_setcond_high:
- reset_temp(args[0]);
+ reset_temp(arg_temp(args[0]));
temp_info(args[0])->mask = 1;
op->opc = INDEX_op_setcond_i32;
args[1] = args[2];
@@ -1294,7 +1305,7 @@ void tcg_optimize(TCGContext *s)
goto do_default;
}
do_setcond_low:
- reset_temp(args[0]);
+ reset_temp(arg_temp(args[0]));
temp_info(args[0])->mask = 1;
op->opc = INDEX_op_setcond_i32;
args[2] = args[3];
@@ -1327,7 +1338,7 @@ void tcg_optimize(TCGContext *s)
& (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
for (i = 0; i < nb_globals; i++) {
if (test_bit(i, temps_used.l)) {
- reset_temp(i);
+ reset_temp(&s->temps[i]);
}
}
}
@@ -1345,7 +1356,7 @@ void tcg_optimize(TCGContext *s)
} else {
do_reset_output:
for (i = 0; i < nb_oargs; i++) {
- reset_temp(args[i]);
+ reset_temp(arg_temp(args[i]));
/* Save the corresponding known-zero bits mask for the
first output argument (only one supported so far). */
if (i == 0) {
diff --git a/tcg/tcg.c b/tcg/tcg.c
index c62f161..a2a0b90 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -773,11 +773,11 @@ void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret,
#else
if (TCG_TARGET_REG_BITS < 64 && (sizemask & 1)) {
#ifdef HOST_WORDS_BIGENDIAN
- s->gen_opparam_buf[pi++] = ret + 1;
+ s->gen_opparam_buf[pi++] = ret + sizeof(TCGTemp);
s->gen_opparam_buf[pi++] = ret;
#else
s->gen_opparam_buf[pi++] = ret;
- s->gen_opparam_buf[pi++] = ret + 1;
+ s->gen_opparam_buf[pi++] = ret + sizeof(TCGTemp);
#endif
nb_rets = 2;
} else {
@@ -810,11 +810,11 @@ void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret,
have to get more complicated to differentiate between
stack arguments and register arguments. */
#if defined(HOST_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
- s->gen_opparam_buf[pi++] = args[i] + 1;
+ s->gen_opparam_buf[pi++] = args[i] + sizeof(TCGTemp);
s->gen_opparam_buf[pi++] = args[i];
#else
s->gen_opparam_buf[pi++] = args[i];
- s->gen_opparam_buf[pi++] = args[i] + 1;
+ s->gen_opparam_buf[pi++] = args[i] + sizeof(TCGTemp);
#endif
real_args += 2;
continue;
@@ -1633,7 +1633,7 @@ static void liveness_pass_1(TCGContext *s)
static bool liveness_pass_2(TCGContext *s)
{
int nb_globals = s->nb_globals;
- int i, oi, oi_next;
+ int i, oi, oi_next, n;
bool changes = false;
/* Create a temporary for each indirect global. */
@@ -1644,10 +1644,16 @@ static bool liveness_pass_2(TCGContext *s)
dts->type = its->type;
dts->base_type = its->base_type;
its->state_ptr = dts;
+ } else {
+ its->state_ptr = NULL;
}
/* All globals begin dead. */
its->state = TS_DEAD;
}
+ for (n = s->nb_temps; i < n; ++i) {
+ TCGTemp *its = &s->temps[i];
+ its->state_ptr = NULL;
+ }
for (oi = s->gen_op_buf[0].next; oi != 0; oi = oi_next) {
TCGOp *op = &s->gen_op_buf[oi];
@@ -1695,8 +1701,8 @@ static bool liveness_pass_2(TCGContext *s)
TCGOp *lop = tcg_op_insert_before(s, op, lopc, 3);
TCGArg *largs = &s->gen_opparam_buf[lop->args];
- largs[0] = temp_idx(dir_ts);
- largs[1] = temp_idx(arg_ts->mem_base);
+ largs[0] = (uintptr_t)dir_ts;
+ largs[1] = (uintptr_t)arg_ts->mem_base;
largs[2] = arg_ts->mem_offset;
/* Loaded, but synced with memory. */
@@ -1713,7 +1719,7 @@ static bool liveness_pass_2(TCGContext *s)
if (arg_ts) {
dir_ts = arg_ts->state_ptr;
if (dir_ts) {
- args[i] = temp_idx(dir_ts);
+ args[i] = (uintptr_t)dir_ts;
changes = true;
if (IS_DEAD_ARG(i)) {
arg_ts->state = TS_DEAD;
@@ -1755,7 +1761,7 @@ static bool liveness_pass_2(TCGContext *s)
if (dir_ts == 0) {
continue;
}
- args[i] = temp_idx(dir_ts);
+ args[i] = (uintptr_t)dir_ts;
changes = true;
/* The output is now live and modified. */
@@ -1769,8 +1775,8 @@ static bool liveness_pass_2(TCGContext *s)
TCGOp *sop = tcg_op_insert_after(s, op, sopc, 3);
TCGArg *sargs = &s->gen_opparam_buf[sop->args];
- sargs[0] = temp_idx(dir_ts);
- sargs[1] = temp_idx(arg_ts->mem_base);
+ sargs[0] = (uintptr_t)dir_ts;
+ sargs[1] = (uintptr_t)arg_ts->mem_base;
sargs[2] = arg_ts->mem_offset;
arg_ts->state = TS_MEM;
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 2670cab..730c2d5 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -705,44 +705,44 @@ static inline uintptr_t temp_idx(TCGTemp *ts)
return n;
}
-static inline size_t arg_index(TCGArg a)
+static inline TCGTemp *arg_temp(TCGArg a)
{
- return a;
+ return (TCGTemp *)(uintptr_t)a;
}
-static inline TCGTemp *arg_temp(TCGArg a)
+static inline size_t arg_index(TCGArg a)
{
- return &tcg_ctx.temps[a];
+ return temp_idx(arg_temp(a));
}
static inline TCGv_i32 QEMU_ARTIFICIAL MAKE_TCGV_I32(uintptr_t i)
{
- return (TCGv_i32)&tcg_ctx.temps[i];
+ return (TCGv_i32)i;
}
static inline TCGv_i64 QEMU_ARTIFICIAL MAKE_TCGV_I64(uintptr_t i)
{
- return (TCGv_i64)&tcg_ctx.temps[i];
+ return (TCGv_i64)i;
}
static inline TCGv_ptr QEMU_ARTIFICIAL MAKE_TCGV_PTR(uintptr_t i)
{
- return (TCGv_ptr)&tcg_ctx.temps[i];
+ return (TCGv_ptr)i;
}
static inline uintptr_t QEMU_ARTIFICIAL GET_TCGV_I32(TCGv_i32 t)
{
- return temp_idx((TCGTemp *)t);
+ return (uintptr_t)t;
}
static inline uintptr_t QEMU_ARTIFICIAL GET_TCGV_I64(TCGv_i64 t)
{
- return temp_idx((TCGTemp *)t);
+ return (uintptr_t)t;
}
static inline uintptr_t QEMU_ARTIFICIAL GET_TCGV_PTR(TCGv_ptr t)
{
- return temp_idx((TCGTemp *)t);
+ return (uintptr_t)t;
}
static inline void tcg_set_insn_param(int op_idx, int arg, TCGArg v)
--
2.7.4
- [Qemu-devel] [RFC 02/14] tcg: Define actual structures for TCGv_*, (continued)
- [Qemu-devel] [RFC 02/14] tcg: Define actual structures for TCGv_*, Richard Henderson, 2016/11/16
- [Qemu-devel] [RFC 05/14] tcg: Avoid loops against variable bounds, Richard Henderson, 2016/11/16
- [Qemu-devel] [RFC 03/14] tcg: Use per-temp state data in liveness, Richard Henderson, 2016/11/16
- [Qemu-devel] [RFC 06/14] tcg: More use of arg_temp, Richard Henderson, 2016/11/16
- [Qemu-devel] [RFC 07/14] tcg: Change temp_allocate_frame arg to TCGTemp, Richard Henderson, 2016/11/16
- [Qemu-devel] [RFC 08/14] tcg: Remove unused TCG_CALL_DUMMY_TCGV, Richard Henderson, 2016/11/16
- [Qemu-devel] [RFC 09/14] tcg: More use of arg_index, Richard Henderson, 2016/11/16
- [Qemu-devel] [RFC 10/14] tcg: Map TCG_CALL_DUMMY_ARG to NULL, Richard Henderson, 2016/11/16
- [Qemu-devel] [RFC 13/14] tcg: Use temp number 0 again, Richard Henderson, 2016/11/16
- [Qemu-devel] [RFC 11/14] tcg: Introduce temp_info for the optimize pass, Richard Henderson, 2016/11/16
- [Qemu-devel] [RFC 12/14] tcg: Store pointers to temporaries directly in TCGArg,
Richard Henderson <=
- [Qemu-devel] [RFC 14/14] tcg/optimize: Fold movcond 0/1 into setcond, Richard Henderson, 2016/11/16