qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices
@ 2016-11-16 19:51 Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 01/14] tcg: Use NULL for TCGV_UNUSED_* Richard Henderson
                   ` (13 more replies)
  0 siblings, 14 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

The comment clarification that Peter asked for in this last
cycle made me wonder if we couldn't make better use of the
data that we're already storing.

We have pointer sized integers that we're passing around.  Why
should we not simply pass the pointers themselves, to save on
looking them up later?

This does cause a few data structures to grow, so it's not a
sure fire win.  Indeed, getting measurements that aren't noise
seems to be a problem.

I'm curious if anyone thinks this is a technical improvment,
or if it's just churn.

(Oh, and the last patch is unrelated, but because of the timeline
in which is was written it is dependent on the others.  It could
be adjusted to be independent, but that would just be extra work.)


r~


Richard Henderson (13):
  tcg: Use NULL for TCGV_UNUSED_*
  tcg: Define actual structures for TCGv_*
  tcg: Use per-temp state data in liveness
  tcg: Add temp_global bit to TCGTemp
  tcg: Avoid loops against variable bounds
  tcg: More use of arg_temp
  tcg: Change temp_allocate_frame arg to TCGTemp
  tcg: Remove unused TCG_CALL_DUMMY_TCGV
  tcg: More use of arg_index
  tcg: Map TCG_CALL_DUMMY_ARG to NULL
  tcg: Introduce temp_info for the optimize pass
  tcg: Store pointers to temporaries directly in TCGArg
  tcg: Use temp number 0 again
  tcg/optimize: Fold movcond 0/1 into setcond

 tcg/optimize.c | 291 +++++++++++++++++++++++++-----------------
 tcg/tcg.c      | 392 ++++++++++++++++++++++++++-------------------------------
 tcg/tcg.h      | 259 ++++++++++++++++++++------------------
 3 files changed, 493 insertions(+), 449 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC 01/14] tcg: Use NULL for TCGV_UNUSED_*
  2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
@ 2016-11-16 19:51 ` Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 02/14] tcg: Define actual structures for TCGv_* Richard Henderson
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.c |  6 +++++-
 tcg/tcg.h | 12 ++++++------
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index aabf94f..057c1ea 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -329,7 +329,11 @@ void tcg_context_init(TCGContext *s)
     GHashTable *helper_table;
 
     memset(s, 0, sizeof(*s));
-    s->nb_globals = 0;
+
+    /* Reserve global 0 so that, when foxing these integrals
+       as pointers, NULL is unused.  */
+    s->nb_globals = 1;
+    s->nb_temps = 1;
 
     /* Count total number of arguments and allocate the corresponding
        space */
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 5fd3733..b2cdaff 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -467,13 +467,13 @@ static inline intptr_t QEMU_ARTIFICIAL GET_TCGV_PTR(TCGv_ptr t)
 #define TCGV_EQUAL_PTR(a, b) (GET_TCGV_PTR(a) == GET_TCGV_PTR(b))
 
 /* Dummy definition to avoid compiler warnings.  */
-#define TCGV_UNUSED_I32(x) x = MAKE_TCGV_I32(-1)
-#define TCGV_UNUSED_I64(x) x = MAKE_TCGV_I64(-1)
-#define TCGV_UNUSED_PTR(x) x = MAKE_TCGV_PTR(-1)
+#define TCGV_UNUSED_I32(x) x = NULL
+#define TCGV_UNUSED_I64(x) x = NULL
+#define TCGV_UNUSED_PTR(x) x = NULL
 
-#define TCGV_IS_UNUSED_I32(x) (GET_TCGV_I32(x) == -1)
-#define TCGV_IS_UNUSED_I64(x) (GET_TCGV_I64(x) == -1)
-#define TCGV_IS_UNUSED_PTR(x) (GET_TCGV_PTR(x) == -1)
+#define TCGV_IS_UNUSED_I32(x) ((x) == NULL)
+#define TCGV_IS_UNUSED_I64(x) ((x) == NULL)
+#define TCGV_IS_UNUSED_PTR(x) ((x) == NULL)
 
 /* call flags */
 /* Helper does not read globals (either directly or through an exception). It
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC 02/14] tcg: Define actual structures for TCGv_*
  2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 01/14] tcg: Use NULL for TCGV_UNUSED_* Richard Henderson
@ 2016-11-16 19:51 ` Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 03/14] tcg: Use per-temp state data in liveness Richard Henderson
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

Pointers that devolve to TCGTemp may tidy things up eventually.
At present, we still store indicies in TCGArg.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.c |  84 +++++++----------------
 tcg/tcg.h | 230 +++++++++++++++++++++++++++++++-------------------------------
 2 files changed, 138 insertions(+), 176 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 057c1ea..7118bce 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -449,13 +449,6 @@ void tcg_func_start(TCGContext *s)
     s->be = tcg_malloc(sizeof(TCGBackendData));
 }
 
-static inline int temp_idx(TCGContext *s, TCGTemp *ts)
-{
-    ptrdiff_t n = ts - s->temps;
-    tcg_debug_assert(n >= 0 && n < s->nb_temps);
-    return n;
-}
-
 static inline TCGTemp *tcg_temp_alloc(TCGContext *s)
 {
     int n = s->nb_temps++;
@@ -470,8 +463,8 @@ static inline TCGTemp *tcg_global_alloc(TCGContext *s)
     return tcg_temp_alloc(s);
 }
 
-static int tcg_global_reg_new_internal(TCGContext *s, TCGType type,
-                                       TCGReg reg, const char *name)
+static TCGTemp *tcg_global_reg_new_internal(TCGContext *s, TCGType type,
+                                            TCGReg reg, const char *name)
 {
     TCGTemp *ts;
 
@@ -487,44 +480,42 @@ static int tcg_global_reg_new_internal(TCGContext *s, TCGType type,
     ts->name = name;
     tcg_regset_set_reg(s->reserved_regs, reg);
 
-    return temp_idx(s, ts);
+    return ts;
 }
 
 void tcg_set_frame(TCGContext *s, TCGReg reg, intptr_t start, intptr_t size)
 {
-    int idx;
     s->frame_start = start;
     s->frame_end = start + size;
-    idx = tcg_global_reg_new_internal(s, TCG_TYPE_PTR, reg, "_frame");
-    s->frame_temp = &s->temps[idx];
+    s->frame_temp = tcg_global_reg_new_internal(s, TCG_TYPE_PTR, reg, "_frame");
 }
 
 TCGv_i32 tcg_global_reg_new_i32(TCGReg reg, const char *name)
 {
     TCGContext *s = &tcg_ctx;
-    int idx;
+    TCGTemp *t;
 
     if (tcg_regset_test_reg(s->reserved_regs, reg)) {
         tcg_abort();
     }
-    idx = tcg_global_reg_new_internal(s, TCG_TYPE_I32, reg, name);
-    return MAKE_TCGV_I32(idx);
+    t = tcg_global_reg_new_internal(s, TCG_TYPE_I32, reg, name);
+    return (TCGv_i32)t;
 }
 
 TCGv_i64 tcg_global_reg_new_i64(TCGReg reg, const char *name)
 {
     TCGContext *s = &tcg_ctx;
-    int idx;
+    TCGTemp *t;
 
     if (tcg_regset_test_reg(s->reserved_regs, reg)) {
         tcg_abort();
     }
-    idx = tcg_global_reg_new_internal(s, TCG_TYPE_I64, reg, name);
-    return MAKE_TCGV_I64(idx);
+    t = tcg_global_reg_new_internal(s, TCG_TYPE_I64, reg, name);
+    return (TCGv_i64)t;
 }
 
-int tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
-                                intptr_t offset, const char *name)
+TCGTemp *tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
+                                     intptr_t offset, const char *name)
 {
     TCGContext *s = &tcg_ctx;
     TCGTemp *base_ts = &s->temps[GET_TCGV_PTR(base)];
@@ -576,10 +567,10 @@ int tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
         ts->mem_offset = offset;
         ts->name = name;
     }
-    return temp_idx(s, ts);
+    return ts;
 }
 
-static int tcg_temp_new_internal(TCGType type, int temp_local)
+TCGTemp *tcg_temp_new_internal(TCGType type, bool temp_local)
 {
     TCGContext *s = &tcg_ctx;
     TCGTemp *ts;
@@ -616,36 +607,18 @@ static int tcg_temp_new_internal(TCGType type, int temp_local)
             ts->temp_allocated = 1;
             ts->temp_local = temp_local;
         }
-        idx = temp_idx(s, ts);
     }
 
 #if defined(CONFIG_DEBUG_TCG)
     s->temps_in_use++;
 #endif
-    return idx;
-}
-
-TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
-{
-    int idx;
-
-    idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
-    return MAKE_TCGV_I32(idx);
+    return ts;
 }
 
-TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
-{
-    int idx;
-
-    idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
-    return MAKE_TCGV_I64(idx);
-}
-
-static void tcg_temp_free_internal(int idx)
+void tcg_temp_free_internal(TCGTemp *ts)
 {
     TCGContext *s = &tcg_ctx;
-    TCGTemp *ts;
-    int k;
+    int k, idx = temp_idx(ts);
 
 #if defined(CONFIG_DEBUG_TCG)
     s->temps_in_use--;
@@ -655,7 +628,6 @@ static void tcg_temp_free_internal(int idx)
 #endif
 
     tcg_debug_assert(idx >= s->nb_globals && idx < s->nb_temps);
-    ts = &s->temps[idx];
     tcg_debug_assert(ts->temp_allocated != 0);
     ts->temp_allocated = 0;
 
@@ -663,16 +635,6 @@ static void tcg_temp_free_internal(int idx)
     set_bit(idx, s->free_temps[k].l);
 }
 
-void tcg_temp_free_i32(TCGv_i32 arg)
-{
-    tcg_temp_free_internal(GET_TCGV_I32(arg));
-}
-
-void tcg_temp_free_i64(TCGv_i64 arg)
-{
-    tcg_temp_free_internal(GET_TCGV_I64(arg));
-}
-
 TCGv_i32 tcg_const_i32(int32_t val)
 {
     TCGv_i32 t0;
@@ -942,7 +904,7 @@ static void tcg_reg_alloc_start(TCGContext *s)
 static char *tcg_get_arg_str_ptr(TCGContext *s, char *buf, int buf_size,
                                  TCGTemp *ts)
 {
-    int idx = temp_idx(s, ts);
+    int idx = temp_idx(ts);
 
     if (idx < s->nb_globals) {
         pstrcpy(buf, buf_size, ts->name);
@@ -1674,7 +1636,7 @@ static bool liveness_pass_2(TCGContext *s, uint8_t *temp_state)
             TCGTemp *dts = tcg_temp_alloc(s);
             dts->type = its->type;
             dts->base_type = its->base_type;
-            dir_temps[i] = temp_idx(s, dts);
+            dir_temps[i] = temp_idx(dts);
         }
     }
 
@@ -1728,7 +1690,7 @@ static bool liveness_pass_2(TCGContext *s, uint8_t *temp_state)
                     TCGArg *largs = &s->gen_opparam_buf[lop->args];
 
                     largs[0] = dir;
-                    largs[1] = temp_idx(s, its->mem_base);
+                    largs[1] = temp_idx(its->mem_base);
                     largs[2] = its->mem_offset;
 
                     /* Loaded, but synced with memory.  */
@@ -1800,7 +1762,7 @@ static bool liveness_pass_2(TCGContext *s, uint8_t *temp_state)
                 TCGArg *sargs = &s->gen_opparam_buf[sop->args];
 
                 sargs[0] = dir;
-                sargs[1] = temp_idx(s, its->mem_base);
+                sargs[1] = temp_idx(its->mem_base);
                 sargs[2] = its->mem_offset;
 
                 temp_state[arg] = TS_MEM;
@@ -1921,7 +1883,7 @@ static void temp_free_or_dead(TCGContext *s, TCGTemp *ts, int free_or_dead)
     }
     ts->val_type = (free_or_dead < 0
                     || ts->temp_local
-                    || temp_idx(s, ts) < s->nb_globals
+                    || temp_idx(ts) < s->nb_globals
                     ? TEMP_VAL_MEM : TEMP_VAL_DEAD);
 }
 
@@ -1943,7 +1905,7 @@ static void temp_sync(TCGContext *s, TCGTemp *ts,
     }
     if (!ts->mem_coherent) {
         if (!ts->mem_allocated) {
-            temp_allocate_frame(s, temp_idx(s, ts));
+            temp_allocate_frame(s, temp_idx(ts));
         }
         switch (ts->val_type) {
         case TEMP_VAL_CONST:
diff --git a/tcg/tcg.h b/tcg/tcg.h
index b2cdaff..5a65204 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -384,41 +384,52 @@ static inline unsigned get_alignment_bits(TCGMemOp memop)
 
 typedef tcg_target_ulong TCGArg;
 
-/* Define type and accessor macros for TCG variables.
-
-   TCG variables are the inputs and outputs of TCG ops, as described
-   in tcg/README. Target CPU front-end code uses these types to deal
-   with TCG variables as it emits TCG code via the tcg_gen_* functions.
-   They come in several flavours:
-    * TCGv_i32 : 32 bit integer type
-    * TCGv_i64 : 64 bit integer type
-    * TCGv_ptr : a host pointer type
-    * TCGv : an integer type the same size as target_ulong
-             (an alias for either TCGv_i32 or TCGv_i64)
-   The compiler's type checking will complain if you mix them
-   up and pass the wrong sized TCGv to a function.
-
-   Users of tcg_gen_* don't need to know about any of the internal
-   details of these, and should treat them as opaque types.
-   You won't be able to look inside them in a debugger either.
-
-   Internal implementation details follow:
-
-   Note that there is no definition of the structs TCGv_i32_d etc anywhere.
-   This is deliberate, because the values we store in variables of type
-   TCGv_i32 are not really pointers-to-structures. They're just small
-   integers, but keeping them in pointer types like this means that the
-   compiler will complain if you accidentally pass a TCGv_i32 to a
-   function which takes a TCGv_i64, and so on. Only the internals of
-   TCG need to care about the actual contents of the types, and they always
-   box and unbox via the MAKE_TCGV_* and GET_TCGV_* functions.
-   Converting to and from intptr_t rather than int reduces the number
-   of sign-extension instructions that get implied on 64-bit hosts.  */
-
-typedef struct TCGv_i32_d *TCGv_i32;
-typedef struct TCGv_i64_d *TCGv_i64;
-typedef struct TCGv_ptr_d *TCGv_ptr;
+typedef enum TCGTempVal {
+    TEMP_VAL_DEAD,
+    TEMP_VAL_REG,
+    TEMP_VAL_MEM,
+    TEMP_VAL_CONST,
+} TCGTempVal;
+
+typedef struct TCGTemp {
+    TCGReg reg:8;
+    TCGTempVal val_type:8;
+    TCGType base_type:8;
+    TCGType type:8;
+    unsigned int fixed_reg:1;
+    unsigned int indirect_reg:1;
+    unsigned int indirect_base:1;
+    unsigned int mem_coherent:1;
+    unsigned int mem_allocated:1;
+    unsigned int temp_local:1; /* If true, the temp is saved across
+                                  basic blocks. Otherwise, it is not
+                                  preserved across basic blocks. */
+    unsigned int temp_allocated:1; /* never used for code gen */
+
+    tcg_target_long val;
+    struct TCGTemp *mem_base;
+    intptr_t mem_offset;
+    const char *name;
+} TCGTemp;
+
+typedef struct TCGv_i32_d {
+    TCGTemp impl;
+} *TCGv_i32;
+
+typedef struct TCGv_i64_d {
+#if TCG_TARGET_REG_BITS == 32
+    struct TCGv_i32_d lo, hi;
+#else
+    TCGTemp impl;
+#endif
+} *TCGv_i64;
+
+typedef struct TCGv_ptr_d {
+    TCGTemp impl;
+} *TCGv_ptr;
+
 typedef TCGv_ptr TCGv_env;
+
 #if TARGET_LONG_BITS == 32
 #define TCGv TCGv_i32
 #elif TARGET_LONG_BITS == 64
@@ -427,49 +438,19 @@ typedef TCGv_ptr TCGv_env;
 #error Unhandled TARGET_LONG_BITS value
 #endif
 
-static inline TCGv_i32 QEMU_ARTIFICIAL MAKE_TCGV_I32(intptr_t i)
-{
-    return (TCGv_i32)i;
-}
-
-static inline TCGv_i64 QEMU_ARTIFICIAL MAKE_TCGV_I64(intptr_t i)
-{
-    return (TCGv_i64)i;
-}
-
-static inline TCGv_ptr QEMU_ARTIFICIAL MAKE_TCGV_PTR(intptr_t i)
-{
-    return (TCGv_ptr)i;
-}
-
-static inline intptr_t QEMU_ARTIFICIAL GET_TCGV_I32(TCGv_i32 t)
-{
-    return (intptr_t)t;
-}
-
-static inline intptr_t QEMU_ARTIFICIAL GET_TCGV_I64(TCGv_i64 t)
-{
-    return (intptr_t)t;
-}
-
-static inline intptr_t QEMU_ARTIFICIAL GET_TCGV_PTR(TCGv_ptr t)
-{
-    return (intptr_t)t;
-}
-
 #if TCG_TARGET_REG_BITS == 32
-#define TCGV_LOW(t) MAKE_TCGV_I32(GET_TCGV_I64(t))
-#define TCGV_HIGH(t) MAKE_TCGV_I32(GET_TCGV_I64(t) + 1)
+#define TCGV_LOW(t)  (&(t)->lo)
+#define TCGV_HIGH(t) (&(t)->hi)
 #endif
 
-#define TCGV_EQUAL_I32(a, b) (GET_TCGV_I32(a) == GET_TCGV_I32(b))
-#define TCGV_EQUAL_I64(a, b) (GET_TCGV_I64(a) == GET_TCGV_I64(b))
-#define TCGV_EQUAL_PTR(a, b) (GET_TCGV_PTR(a) == GET_TCGV_PTR(b))
+#define TCGV_EQUAL_I32(a, b)  ((a) == (b))
+#define TCGV_EQUAL_I64(a, b)  ((a) == (b))
+#define TCGV_EQUAL_PTR(a, b)  ((a) == (b))
 
 /* Dummy definition to avoid compiler warnings.  */
-#define TCGV_UNUSED_I32(x) x = NULL
-#define TCGV_UNUSED_I64(x) x = NULL
-#define TCGV_UNUSED_PTR(x) x = NULL
+#define TCGV_UNUSED_I32(x)    ((x) = NULL)
+#define TCGV_UNUSED_I64(x)    ((x) = NULL)
+#define TCGV_UNUSED_PTR(x)    ((x) = NULL)
 
 #define TCGV_IS_UNUSED_I32(x) ((x) == NULL)
 #define TCGV_IS_UNUSED_I64(x) ((x) == NULL)
@@ -575,34 +556,6 @@ static inline TCGCond tcg_high_cond(TCGCond c)
     }
 }
 
-typedef enum TCGTempVal {
-    TEMP_VAL_DEAD,
-    TEMP_VAL_REG,
-    TEMP_VAL_MEM,
-    TEMP_VAL_CONST,
-} TCGTempVal;
-
-typedef struct TCGTemp {
-    TCGReg reg:8;
-    TCGTempVal val_type:8;
-    TCGType base_type:8;
-    TCGType type:8;
-    unsigned int fixed_reg:1;
-    unsigned int indirect_reg:1;
-    unsigned int indirect_base:1;
-    unsigned int mem_coherent:1;
-    unsigned int mem_allocated:1;
-    unsigned int temp_local:1; /* If true, the temp is saved across
-                                  basic blocks. Otherwise, it is not
-                                  preserved across basic blocks. */
-    unsigned int temp_allocated:1; /* never used for code gen */
-
-    tcg_target_long val;
-    struct TCGTemp *mem_base;
-    intptr_t mem_offset;
-    const char *name;
-} TCGTemp;
-
 typedef struct TCGContext TCGContext;
 
 typedef struct TCGTempSet {
@@ -736,6 +689,43 @@ struct TCGContext {
 extern TCGContext tcg_ctx;
 extern bool parallel_cpus;
 
+static inline uintptr_t temp_idx(TCGTemp *ts)
+{
+    ptrdiff_t n = ts - tcg_ctx.temps;
+    tcg_debug_assert(n >= 0 && n < tcg_ctx.nb_temps);
+    return n;
+}
+
+static inline TCGv_i32 QEMU_ARTIFICIAL MAKE_TCGV_I32(uintptr_t i)
+{
+    return (TCGv_i32)&tcg_ctx.temps[i];
+}
+
+static inline TCGv_i64 QEMU_ARTIFICIAL MAKE_TCGV_I64(uintptr_t i)
+{
+    return (TCGv_i64)&tcg_ctx.temps[i];
+}
+
+static inline TCGv_ptr QEMU_ARTIFICIAL MAKE_TCGV_PTR(uintptr_t i)
+{
+    return (TCGv_ptr)&tcg_ctx.temps[i];
+}
+
+static inline uintptr_t QEMU_ARTIFICIAL GET_TCGV_I32(TCGv_i32 t)
+{
+    return temp_idx((TCGTemp *)t);
+}
+
+static inline uintptr_t QEMU_ARTIFICIAL GET_TCGV_I64(TCGv_i64 t)
+{
+    return temp_idx((TCGTemp *)t);
+}
+
+static inline uintptr_t QEMU_ARTIFICIAL GET_TCGV_PTR(TCGv_ptr t)
+{
+    return temp_idx((TCGTemp *)t);
+}
+
 static inline void tcg_set_insn_param(int op_idx, int arg, TCGArg v)
 {
     int op_argi = tcg_ctx.gen_op_buf[op_idx].args;
@@ -788,49 +778,59 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb);
 
 void tcg_set_frame(TCGContext *s, TCGReg reg, intptr_t start, intptr_t size);
 
-int tcg_global_mem_new_internal(TCGType, TCGv_ptr, intptr_t, const char *);
+TCGTemp *tcg_global_mem_new_internal(TCGType, TCGv_ptr, intptr_t, const char *);
+TCGTemp *tcg_temp_new_internal(TCGType type, bool temp_local);
+void tcg_temp_free_internal(TCGTemp *ts);
 
 TCGv_i32 tcg_global_reg_new_i32(TCGReg reg, const char *name);
 TCGv_i64 tcg_global_reg_new_i64(TCGReg reg, const char *name);
 
-TCGv_i32 tcg_temp_new_internal_i32(int temp_local);
-TCGv_i64 tcg_temp_new_internal_i64(int temp_local);
-
-void tcg_temp_free_i32(TCGv_i32 arg);
-void tcg_temp_free_i64(TCGv_i64 arg);
-
 static inline TCGv_i32 tcg_global_mem_new_i32(TCGv_ptr reg, intptr_t offset,
                                               const char *name)
 {
-    int idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
-    return MAKE_TCGV_I32(idx);
+    TCGTemp *t = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
+    return (TCGv_i32)t;
 }
 
 static inline TCGv_i32 tcg_temp_new_i32(void)
 {
-    return tcg_temp_new_internal_i32(0);
+    TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_I32, false);
+    return (TCGv_i32)t;
 }
 
 static inline TCGv_i32 tcg_temp_local_new_i32(void)
 {
-    return tcg_temp_new_internal_i32(1);
+    TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_I32, true);
+    return (TCGv_i32)t;
 }
 
 static inline TCGv_i64 tcg_global_mem_new_i64(TCGv_ptr reg, intptr_t offset,
                                               const char *name)
 {
-    int idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
-    return MAKE_TCGV_I64(idx);
+    TCGTemp *t = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
+    return (TCGv_i64)t;
 }
 
 static inline TCGv_i64 tcg_temp_new_i64(void)
 {
-    return tcg_temp_new_internal_i64(0);
+    TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_I64, false);
+    return (TCGv_i64)t;
 }
 
 static inline TCGv_i64 tcg_temp_local_new_i64(void)
 {
-    return tcg_temp_new_internal_i64(1);
+    TCGTemp *t = tcg_temp_new_internal(TCG_TYPE_I64, true);
+    return (TCGv_i64)t;
+}
+
+static inline void tcg_temp_free_i32(TCGv_i32 arg)
+{
+    tcg_temp_free_internal((TCGTemp *)arg);
+}
+
+static inline void tcg_temp_free_i64(TCGv_i64 arg)
+{
+    tcg_temp_free_internal((TCGTemp *)arg);
 }
 
 #if defined(CONFIG_DEBUG_TCG)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC 03/14] tcg: Use per-temp state data in liveness
  2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 01/14] tcg: Use NULL for TCGV_UNUSED_* Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 02/14] tcg: Define actual structures for TCGv_* Richard Henderson
@ 2016-11-16 19:51 ` Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 04/14] tcg: Add temp_global bit to TCGTemp Richard Henderson
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.c | 219 +++++++++++++++++++++++++++++++++-----------------------------
 tcg/tcg.h |  16 +++++
 2 files changed, 132 insertions(+), 103 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 7118bce..8ae41a6 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1368,42 +1368,55 @@ TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *old_op,
 
 /* liveness analysis: end of function: all temps are dead, and globals
    should be in memory. */
-static inline void tcg_la_func_end(TCGContext *s, uint8_t *temp_state)
+static void tcg_la_func_end(TCGContext *s)
 {
-    memset(temp_state, TS_DEAD | TS_MEM, s->nb_globals);
-    memset(temp_state + s->nb_globals, TS_DEAD, s->nb_temps - s->nb_globals);
+    int ng = s->nb_globals;
+    int nt = s->nb_temps;
+    int i;
+
+    for (i = 0; i < ng; ++i) {
+        s->temps[i].state = TS_DEAD | TS_MEM;
+    }
+    for (i = ng; i < nt; ++i) {
+        s->temps[i].state = TS_DEAD;
+    }
 }
 
 /* liveness analysis: end of basic block: all temps are dead, globals
    and local temps should be in memory. */
-static inline void tcg_la_bb_end(TCGContext *s, uint8_t *temp_state)
+static void tcg_la_bb_end(TCGContext *s)
 {
-    int i, n;
+    int ng = s->nb_globals;
+    int nt = s->nb_temps;
+    int i;
 
-    tcg_la_func_end(s, temp_state);
-    for (i = s->nb_globals, n = s->nb_temps; i < n; i++) {
-        if (s->temps[i].temp_local) {
-            temp_state[i] |= TS_MEM;
-        }
+    for (i = 0; i < ng; ++i) {
+        s->temps[i].state = TS_DEAD | TS_MEM;
+    }
+    for (i = ng; i < nt; ++i) {
+        s->temps[i].state = (s->temps[i].temp_local
+                             ? TS_DEAD | 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. */
-static void liveness_pass_1(TCGContext *s, uint8_t *temp_state)
+static void liveness_pass_1(TCGContext *s)
 {
     int nb_globals = s->nb_globals;
     int oi, oi_prev;
 
-    tcg_la_func_end(s, temp_state);
+    tcg_la_func_end(s);
 
     for (oi = s->gen_op_buf[0].prev; oi != 0; oi = oi_prev) {
         int i, nb_iargs, nb_oargs;
         TCGOpcode opc_new, opc_new2;
         bool have_opc_new2;
         TCGLifeData arg_life = 0;
-        TCGArg arg;
+        TCGTemp *arg_ts;
+        TCGArg arg_idx;
 
         TCGOp * const op = &s->gen_op_buf[oi];
         TCGArg * const args = &s->gen_opparam_buf[op->args];
@@ -1424,8 +1437,8 @@ static void liveness_pass_1(TCGContext *s, uint8_t *temp_state)
                 /* pure functions can be removed if their result is unused */
                 if (call_flags & TCG_CALL_NO_SIDE_EFFECTS) {
                     for (i = 0; i < nb_oargs; i++) {
-                        arg = args[i];
-                        if (temp_state[arg] != TS_DEAD) {
+                        arg_ts = arg_temp(args[i]);
+                        if (arg_ts->state != TS_DEAD) {
                             goto do_not_remove_call;
                         }
                     }
@@ -1435,41 +1448,45 @@ static void liveness_pass_1(TCGContext *s, uint8_t *temp_state)
 
                     /* output args are dead */
                     for (i = 0; i < nb_oargs; i++) {
-                        arg = args[i];
-                        if (temp_state[arg] & TS_DEAD) {
+                        arg_ts = arg_temp(args[i]);
+                        if (arg_ts->state & TS_DEAD) {
                             arg_life |= DEAD_ARG << i;
                         }
-                        if (temp_state[arg] & TS_MEM) {
+                        if (arg_ts->state & TS_MEM) {
                             arg_life |= SYNC_ARG << i;
                         }
-                        temp_state[arg] = TS_DEAD;
+                        arg_ts->state = TS_DEAD;
                     }
 
                     if (!(call_flags & (TCG_CALL_NO_WRITE_GLOBALS |
                                         TCG_CALL_NO_READ_GLOBALS))) {
                         /* globals should go back to memory */
-                        memset(temp_state, TS_DEAD | TS_MEM, nb_globals);
+                        for (i = 0; i < nb_globals; i++) {
+                            s->temps[i].state = TS_DEAD | TS_MEM;
+                        }
                     } else if (!(call_flags & TCG_CALL_NO_READ_GLOBALS)) {
                         /* globals should be synced to memory */
                         for (i = 0; i < nb_globals; i++) {
-                            temp_state[i] |= TS_MEM;
+                            s->temps[i].state |= TS_MEM;
                         }
                     }
 
                     /* record arguments that die in this helper */
                     for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
-                        arg = args[i];
-                        if (arg != TCG_CALL_DUMMY_ARG) {
-                            if (temp_state[arg] & TS_DEAD) {
+                        arg_idx = arg_index(args[i]);
+                        if (arg_idx != TCG_CALL_DUMMY_ARG) {
+                            arg_ts = arg_temp(args[i]);
+                            if (arg_ts->state & TS_DEAD) {
                                 arg_life |= DEAD_ARG << i;
                             }
                         }
                     }
                     /* input arguments are live for preceding opcodes */
                     for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
-                        arg = args[i];
-                        if (arg != TCG_CALL_DUMMY_ARG) {
-                            temp_state[arg] &= ~TS_DEAD;
+                        arg_idx = arg_index(args[i]);
+                        if (arg_idx != TCG_CALL_DUMMY_ARG) {
+                            arg_ts = arg_temp(args[i]);
+                            arg_ts->state &= ~TS_DEAD;
                         }
                     }
                 }
@@ -1479,7 +1496,7 @@ static void liveness_pass_1(TCGContext *s, uint8_t *temp_state)
             break;
         case INDEX_op_discard:
             /* mark the temporary as dead */
-            temp_state[args[0]] = TS_DEAD;
+            arg_temp(args[0])->state = TS_DEAD;
             break;
 
         case INDEX_op_add2_i32:
@@ -1500,8 +1517,8 @@ static void liveness_pass_1(TCGContext *s, uint8_t *temp_state)
                the low part.  The result can be optimized to a simple
                add or sub.  This happens often for x86_64 guest when the
                cpu mode is set to 32 bit.  */
-            if (temp_state[args[1]] == TS_DEAD) {
-                if (temp_state[args[0]] == TS_DEAD) {
+            if (arg_temp(args[1])->state == TS_DEAD) {
+                if (arg_temp(args[0])->state == TS_DEAD) {
                     goto do_remove;
                 }
                 /* Replace the opcode and adjust the args in place,
@@ -1538,8 +1555,8 @@ static void liveness_pass_1(TCGContext *s, uint8_t *temp_state)
         do_mul2:
             nb_iargs = 2;
             nb_oargs = 2;
-            if (temp_state[args[1]] == TS_DEAD) {
-                if (temp_state[args[0]] == TS_DEAD) {
+            if (arg_temp(args[1])->state == TS_DEAD) {
+                if (arg_temp(args[0])->state == TS_DEAD) {
                     /* Both parts of the operation are dead.  */
                     goto do_remove;
                 }
@@ -1547,7 +1564,7 @@ static void liveness_pass_1(TCGContext *s, uint8_t *temp_state)
                 op->opc = opc = opc_new;
                 args[1] = args[2];
                 args[2] = args[3];
-            } else if (temp_state[args[0]] == TS_DEAD && have_opc_new2) {
+            } else if (arg_temp(args[0])->state == TS_DEAD && have_opc_new2) {
                 /* The low part of the operation is dead; generate the high. */
                 op->opc = opc = opc_new2;
                 args[0] = args[1];
@@ -1570,7 +1587,7 @@ static void liveness_pass_1(TCGContext *s, uint8_t *temp_state)
                implies side effects */
             if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
                 for (i = 0; i < nb_oargs; i++) {
-                    if (temp_state[args[i]] != TS_DEAD) {
+                    if (arg_temp(args[i])->state != TS_DEAD) {
                         goto do_not_remove;
                     }
                 }
@@ -1580,36 +1597,36 @@ static void liveness_pass_1(TCGContext *s, uint8_t *temp_state)
             do_not_remove:
                 /* output args are dead */
                 for (i = 0; i < nb_oargs; i++) {
-                    arg = args[i];
-                    if (temp_state[arg] & TS_DEAD) {
+                    arg_ts = arg_temp(args[i]);
+                    if (arg_ts->state & TS_DEAD) {
                         arg_life |= DEAD_ARG << i;
                     }
-                    if (temp_state[arg] & TS_MEM) {
+                    if (arg_ts->state & TS_MEM) {
                         arg_life |= SYNC_ARG << i;
                     }
-                    temp_state[arg] = TS_DEAD;
+                    arg_ts->state = TS_DEAD;
                 }
 
                 /* if end of basic block, update */
                 if (def->flags & TCG_OPF_BB_END) {
-                    tcg_la_bb_end(s, temp_state);
+                    tcg_la_bb_end(s);
                 } else if (def->flags & TCG_OPF_SIDE_EFFECTS) {
                     /* globals should be synced to memory */
                     for (i = 0; i < nb_globals; i++) {
-                        temp_state[i] |= TS_MEM;
+                        s->temps[i].state |= TS_MEM;
                     }
                 }
 
                 /* record arguments that die in this opcode */
                 for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
-                    arg = args[i];
-                    if (temp_state[arg] & TS_DEAD) {
+                    arg_ts = arg_temp(args[i]);
+                    if (arg_ts->state & TS_DEAD) {
                         arg_life |= DEAD_ARG << i;
                     }
                 }
                 /* input arguments are live for preceding opcodes */
                 for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
-                    temp_state[args[i]] &= ~TS_DEAD;
+                    arg_temp(args[i])->state &= ~TS_DEAD;
                 }
             }
             break;
@@ -1619,16 +1636,12 @@ static void liveness_pass_1(TCGContext *s, uint8_t *temp_state)
 }
 
 /* Liveness analysis: Convert indirect regs to direct temporaries.  */
-static bool liveness_pass_2(TCGContext *s, uint8_t *temp_state)
+static bool liveness_pass_2(TCGContext *s)
 {
     int nb_globals = s->nb_globals;
-    int16_t *dir_temps;
     int i, oi, oi_next;
     bool changes = false;
 
-    dir_temps = tcg_malloc(nb_globals * sizeof(int16_t));
-    memset(dir_temps, 0, nb_globals * sizeof(int16_t));
-
     /* Create a temporary for each indirect global.  */
     for (i = 0; i < nb_globals; ++i) {
         TCGTemp *its = &s->temps[i];
@@ -1636,12 +1649,12 @@ static bool liveness_pass_2(TCGContext *s, uint8_t *temp_state)
             TCGTemp *dts = tcg_temp_alloc(s);
             dts->type = its->type;
             dts->base_type = its->base_type;
-            dir_temps[i] = temp_idx(dts);
+            its->state_ptr = dts;
         }
+        /* All globals begin dead.  */
+        its->state = TS_DEAD;
     }
 
-    memset(temp_state, TS_DEAD, nb_globals);
-
     for (oi = s->gen_op_buf[0].next; oi != 0; oi = oi_next) {
         TCGOp *op = &s->gen_op_buf[oi];
         TCGArg *args = &s->gen_opparam_buf[op->args];
@@ -1649,7 +1662,8 @@ static bool liveness_pass_2(TCGContext *s, uint8_t *temp_state)
         const TCGOpDef *def = &tcg_op_defs[opc];
         TCGLifeData arg_life = op->life;
         int nb_iargs, nb_oargs, call_flags;
-        TCGArg arg, dir;
+        TCGTemp *arg_ts, *dir_ts;
+        size_t arg_idx;
 
         oi_next = op->next;
 
@@ -1677,24 +1691,24 @@ static bool liveness_pass_2(TCGContext *s, uint8_t *temp_state)
 
         /* Make sure that input arguments are available.  */
         for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
-            arg = args[i];
+            arg_idx = arg_index(args[i]);
             /* Note this unsigned test catches TCG_CALL_ARG_DUMMY too.  */
-            if (arg < nb_globals) {
-                dir = dir_temps[arg];
-                if (dir != 0 && temp_state[arg] == TS_DEAD) {
-                    TCGTemp *its = &s->temps[arg];
-                    TCGOpcode lopc = (its->type == TCG_TYPE_I32
+            if (arg_idx < nb_globals) {
+                arg_ts = arg_temp(args[i]);
+                dir_ts = arg_ts->state_ptr;
+                if (dir_ts != 0 && arg_ts->state == TS_DEAD) {
+                    TCGOpcode lopc = (arg_ts->type == TCG_TYPE_I32
                                       ? INDEX_op_ld_i32
                                       : INDEX_op_ld_i64);
                     TCGOp *lop = tcg_op_insert_before(s, op, lopc, 3);
                     TCGArg *largs = &s->gen_opparam_buf[lop->args];
 
-                    largs[0] = dir;
-                    largs[1] = temp_idx(its->mem_base);
-                    largs[2] = its->mem_offset;
+                    largs[0] = temp_idx(dir_ts);
+                    largs[1] = temp_idx(arg_ts->mem_base);
+                    largs[2] = arg_ts->mem_offset;
 
                     /* Loaded, but synced with memory.  */
-                    temp_state[arg] = TS_MEM;
+                    arg_ts->state = TS_MEM;
                 }
             }
         }
@@ -1703,14 +1717,15 @@ static bool liveness_pass_2(TCGContext *s, uint8_t *temp_state)
            No action is required except keeping temp_state up to date
            so that we reload when needed.  */
         for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
-            arg = args[i];
-            if (arg < nb_globals) {
-                dir = dir_temps[arg];
-                if (dir != 0) {
-                    args[i] = dir;
+            arg_idx = arg_index(args[i]);
+            if (arg_idx < nb_globals) {
+                arg_ts = arg_temp(args[i]);
+                dir_ts = arg_ts->state_ptr;
+                if (dir_ts != 0) {
+                    args[i] = temp_idx(dir_ts);
                     changes = true;
                     if (IS_DEAD_ARG(i)) {
-                        temp_state[arg] = TS_DEAD;
+                        arg_ts->state = TS_DEAD;
                     }
                 }
             }
@@ -1724,52 +1739,54 @@ static bool liveness_pass_2(TCGContext *s, uint8_t *temp_state)
             for (i = 0; i < nb_globals; ++i) {
                 /* Liveness should see that globals are synced back,
                    that is, either TS_DEAD or TS_MEM.  */
-                tcg_debug_assert(dir_temps[i] == 0
-                                 || temp_state[i] != 0);
+                arg_ts = &s->temps[i];
+                tcg_debug_assert(arg_ts->state_ptr == 0
+                                 || arg_ts->state != 0);
             }
         } else {
             for (i = 0; i < nb_globals; ++i) {
                 /* Liveness should see that globals are saved back,
                    that is, TS_DEAD, waiting to be reloaded.  */
-                tcg_debug_assert(dir_temps[i] == 0
-                                 || temp_state[i] == TS_DEAD);
+                arg_ts = &s->temps[i];
+                tcg_debug_assert(arg_ts->state_ptr == 0
+                                 || arg_ts->state == TS_DEAD);
             }
         }
 
         /* Outputs become available.  */
         for (i = 0; i < nb_oargs; i++) {
-            arg = args[i];
-            if (arg >= nb_globals) {
+            arg_idx = arg_index(args[i]);
+            if (arg_idx >= nb_globals) {
                 continue;
             }
-            dir = dir_temps[arg];
-            if (dir == 0) {
+            arg_ts = arg_temp(args[i]);
+            dir_ts = arg_ts->state_ptr;
+            if (dir_ts == 0) {
                 continue;
             }
-            args[i] = dir;
+            args[i] = temp_idx(dir_ts);
             changes = true;
 
             /* The output is now live and modified.  */
-            temp_state[arg] = 0;
+            arg_ts->state = 0;
 
             /* Sync outputs upon their last write.  */
             if (NEED_SYNC_ARG(i)) {
-                TCGTemp *its = &s->temps[arg];
-                TCGOpcode sopc = (its->type == TCG_TYPE_I32
+                TCGOpcode sopc = (arg_ts->type == TCG_TYPE_I32
                                   ? INDEX_op_st_i32
                                   : INDEX_op_st_i64);
                 TCGOp *sop = tcg_op_insert_after(s, op, sopc, 3);
                 TCGArg *sargs = &s->gen_opparam_buf[sop->args];
 
-                sargs[0] = dir;
-                sargs[1] = temp_idx(its->mem_base);
-                sargs[2] = its->mem_offset;
+                sargs[0] = temp_idx(dir_ts);
+                sargs[1] = temp_idx(arg_ts->mem_base);
+                sargs[2] = arg_ts->mem_offset;
 
-                temp_state[arg] = TS_MEM;
+                arg_ts->state = TS_MEM;
             }
             /* Drop outputs that are dead.  */
             if (IS_DEAD_ARG(i)) {
-                temp_state[arg] = TS_DEAD;
+                arg_ts->state = TS_DEAD;
             }
         }
     }
@@ -2531,27 +2548,23 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
     s->la_time -= profile_getclock();
 #endif
 
-    {
-        uint8_t *temp_state = tcg_malloc(s->nb_temps + s->nb_indirects);
-
-        liveness_pass_1(s, temp_state);
+    liveness_pass_1(s);
 
-        if (s->nb_indirects > 0) {
+    if (s->nb_indirects > 0) {
 #ifdef DEBUG_DISAS
-            if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_IND)
-                         && qemu_log_in_addr_range(tb->pc))) {
-                qemu_log_lock();
-                qemu_log("OP before indirect lowering:\n");
-                tcg_dump_ops(s);
-                qemu_log("\n");
-                qemu_log_unlock();
-            }
+        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_IND)
+                     && qemu_log_in_addr_range(tb->pc))) {
+            qemu_log_lock();
+            qemu_log("OP before indirect lowering:\n");
+            tcg_dump_ops(s);
+            qemu_log("\n");
+            qemu_log_unlock();
+        }
 #endif
-            /* Replace indirect temps with direct temps.  */
-            if (liveness_pass_2(s, temp_state)) {
-                /* If changes were made, re-run liveness.  */
-                liveness_pass_1(s, temp_state);
-            }
+        /* Replace indirect temps with direct temps.  */
+        if (liveness_pass_2(s)) {
+            /* If changes were made, re-run liveness.  */
+            liveness_pass_1(s);
         }
     }
 
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 5a65204..723e06f 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -410,6 +410,12 @@ typedef struct TCGTemp {
     struct TCGTemp *mem_base;
     intptr_t mem_offset;
     const char *name;
+
+    /* Pass-specific information that can be stored for a temporary.
+       One word worth of integer data, and one pointer to data
+       allocated separately.  */
+    uintptr_t state;
+    void *state_ptr;
 } TCGTemp;
 
 typedef struct TCGv_i32_d {
@@ -696,6 +702,16 @@ static inline uintptr_t temp_idx(TCGTemp *ts)
     return n;
 }
 
+static inline size_t arg_index(TCGArg a)
+{
+    return a;
+}
+
+static inline TCGTemp *arg_temp(TCGArg a)
+{
+    return &tcg_ctx.temps[a];
+}
+
 static inline TCGv_i32 QEMU_ARTIFICIAL MAKE_TCGV_I32(uintptr_t i)
 {
     return (TCGv_i32)&tcg_ctx.temps[i];
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC 04/14] tcg: Add temp_global bit to TCGTemp
  2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
                   ` (2 preceding siblings ...)
  2016-11-16 19:51 ` [Qemu-devel] [RFC 03/14] tcg: Use per-temp state data in liveness Richard Henderson
@ 2016-11-16 19:51 ` Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 05/14] tcg: Avoid loops against variable bounds Richard Henderson
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

This avoids needing to test the index of a temp against nb_globals.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.c | 12 +++++++++---
 tcg/tcg.h | 12 ++++++++----
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 8ae41a6..b186b38 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -458,9 +458,14 @@ static inline TCGTemp *tcg_temp_alloc(TCGContext *s)
 
 static inline TCGTemp *tcg_global_alloc(TCGContext *s)
 {
+    TCGTemp *ts;
+
     tcg_debug_assert(s->nb_globals == s->nb_temps);
     s->nb_globals++;
-    return tcg_temp_alloc(s);
+    ts = tcg_temp_alloc(s);
+    ts->temp_global = 1;
+
+    return ts;
 }
 
 static TCGTemp *tcg_global_reg_new_internal(TCGContext *s, TCGType type,
@@ -906,7 +911,7 @@ static char *tcg_get_arg_str_ptr(TCGContext *s, char *buf, int buf_size,
 {
     int idx = temp_idx(ts);
 
-    if (idx < s->nb_globals) {
+    if (ts->temp_global) {
         pstrcpy(buf, buf_size, ts->name);
     } else if (ts->temp_local) {
         snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
@@ -1718,6 +1723,7 @@ static bool liveness_pass_2(TCGContext *s)
            so that we reload when needed.  */
         for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
             arg_idx = arg_index(args[i]);
+            /* Note this unsigned test catches TCG_CALL_ARG_DUMMY too.  */
             if (arg_idx < nb_globals) {
                 arg_ts = arg_temp(args[i]);
                 dir_ts = arg_ts->state_ptr;
@@ -1900,7 +1906,7 @@ static void temp_free_or_dead(TCGContext *s, TCGTemp *ts, int free_or_dead)
     }
     ts->val_type = (free_or_dead < 0
                     || ts->temp_local
-                    || temp_idx(ts) < s->nb_globals
+                    || ts->temp_global
                     ? TEMP_VAL_MEM : TEMP_VAL_DEAD);
 }
 
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 723e06f..dbd6308 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -401,10 +401,14 @@ typedef struct TCGTemp {
     unsigned int indirect_base:1;
     unsigned int mem_coherent:1;
     unsigned int mem_allocated:1;
-    unsigned int temp_local:1; /* If true, the temp is saved across
-                                  basic blocks. Otherwise, it is not
-                                  preserved across basic blocks. */
-    unsigned int temp_allocated:1; /* never used for code gen */
+    /* If true, the temp is saved across both basic blocks and
+       translation blocks.  */
+    unsigned int temp_global:1;
+    /* If true, the temp is saved across basic blocks but dead
+       at the end of translation blocks.  If false, the temp is
+       dead at the end of basic blocks.  */
+    unsigned int temp_local:1;
+    unsigned int temp_allocated:1;
 
     tcg_target_long val;
     struct TCGTemp *mem_base;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC 05/14] tcg: Avoid loops against variable bounds
  2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
                   ` (3 preceding siblings ...)
  2016-11-16 19:51 ` [Qemu-devel] [RFC 04/14] tcg: Add temp_global bit to TCGTemp Richard Henderson
@ 2016-11-16 19:51 ` Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 06/14] tcg: More use of arg_temp Richard Henderson
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

Copy s->nb_globals or s->nb_temps to a local variable for the purposes
of iteration.  This should allow the compiler to use low-overhead
looping constructs on some hosts.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.c | 27 ++++++++++-----------------
 1 file changed, 10 insertions(+), 17 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index b186b38..840c8b5 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -882,23 +882,16 @@ void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret,
 
 static void tcg_reg_alloc_start(TCGContext *s)
 {
-    int i;
+    int i, n;
     TCGTemp *ts;
-    for(i = 0; i < s->nb_globals; i++) {
+
+    for (i = 0, n = s->nb_globals; i < n; i++) {
         ts = &s->temps[i];
-        if (ts->fixed_reg) {
-            ts->val_type = TEMP_VAL_REG;
-        } else {
-            ts->val_type = TEMP_VAL_MEM;
-        }
+        ts->val_type = (ts->fixed_reg ? TEMP_VAL_REG : TEMP_VAL_MEM);
     }
-    for(i = s->nb_globals; i < s->nb_temps; i++) {
+    for (n = s->nb_temps; i < n; i++) {
         ts = &s->temps[i];
-        if (ts->temp_local) {
-            ts->val_type = TEMP_VAL_MEM;
-        } else {
-            ts->val_type = TEMP_VAL_DEAD;
-        }
+        ts->val_type = (ts->temp_local ? TEMP_VAL_MEM : TEMP_VAL_DEAD);
         ts->mem_allocated = 0;
         ts->fixed_reg = 0;
     }
@@ -2046,9 +2039,9 @@ static void temp_save(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs)
    temporary registers needs to be allocated to store a constant. */
 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
 {
-    int i;
+    int i, n;
 
-    for (i = 0; i < s->nb_globals; i++) {
+    for (i = 0, n = s->nb_globals; i < n; i++) {
         temp_save(s, &s->temps[i], allocated_regs);
     }
 }
@@ -2058,9 +2051,9 @@ static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
    temporary registers needs to be allocated to store a constant. */
 static void sync_globals(TCGContext *s, TCGRegSet allocated_regs)
 {
-    int i;
+    int i, n;
 
-    for (i = 0; i < s->nb_globals; i++) {
+    for (i = 0, n = s->nb_globals; i < n; i++) {
         TCGTemp *ts = &s->temps[i];
         tcg_debug_assert(ts->val_type != TEMP_VAL_REG
                          || ts->fixed_reg
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC 06/14] tcg: More use of arg_temp
  2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
                   ` (4 preceding siblings ...)
  2016-11-16 19:51 ` [Qemu-devel] [RFC 05/14] tcg: Avoid loops against variable bounds Richard Henderson
@ 2016-11-16 19:51 ` Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 07/14] tcg: Change temp_allocate_frame arg to TCGTemp Richard Henderson
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 840c8b5..4bcdb1e 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -523,7 +523,7 @@ TCGTemp *tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
                                      intptr_t offset, const char *name)
 {
     TCGContext *s = &tcg_ctx;
-    TCGTemp *base_ts = &s->temps[GET_TCGV_PTR(base)];
+    TCGTemp *base_ts = &base->impl;
     TCGTemp *ts = tcg_global_alloc(s);
     int indirect_reg = 0, bigendian = 0;
 #ifdef HOST_WORDS_BIGENDIAN
@@ -2107,7 +2107,7 @@ static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp *ots,
 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
                                TCGLifeData arg_life)
 {
-    TCGTemp *ots = &s->temps[args[0]];
+    TCGTemp *ots = arg_temp(args[0]);
     tcg_target_ulong val = args[1];
 
     tcg_reg_alloc_do_movi(s, ots, val, arg_life);
@@ -2121,8 +2121,8 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
     TCGType otype, itype;
 
     tcg_regset_set(allocated_regs, s->reserved_regs);
-    ots = &s->temps[args[0]];
-    ts = &s->temps[args[1]];
+    ots = arg_temp(args[0]);
+    ts = arg_temp(args[1]);
 
     /* Note that otype != itype for no-op truncation.  */
     otype = ots->type;
@@ -2213,7 +2213,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
         i = def->sorted_args[nb_oargs + k];
         arg = args[i];
         arg_ct = &def->args_ct[i];
-        ts = &s->temps[arg];
+        ts = arg_temp(arg);
 
         if (ts->val_type == TEMP_VAL_CONST
             && tcg_target_const_match(ts->val, ts->type, arg_ct)) {
@@ -2270,7 +2270,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
     /* mark dead temporaries and free the associated registers */
     for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
         if (IS_DEAD_ARG(i)) {
-            temp_dead(s, &s->temps[args[i]]);
+            temp_dead(s, arg_temp(args[i]));
         }
     }
 
@@ -2297,7 +2297,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
             i = def->sorted_args[k];
             arg = args[i];
             arg_ct = &def->args_ct[i];
-            ts = &s->temps[arg];
+            ts = arg_temp(arg);
             if (arg_ct->ct & TCG_CT_ALIAS) {
                 reg = new_args[arg_ct->alias_index];
             } else {
@@ -2333,7 +2333,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
     
     /* move the outputs in the correct register if needed */
     for(i = 0; i < nb_oargs; i++) {
-        ts = &s->temps[args[i]];
+        ts = arg_temp(args[i]);
         reg = new_args[i];
         if (ts->fixed_reg && ts->reg != reg) {
             tcg_out_mov(s, ts->type, ts->reg, reg);
@@ -2391,7 +2391,7 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
         stack_offset -= sizeof(tcg_target_long);
 #endif
         if (arg != TCG_CALL_DUMMY_ARG) {
-            ts = &s->temps[arg];
+            ts = arg_temp(arg);
             temp_load(s, ts, tcg_target_available_regs[ts->type],
                       s->reserved_regs);
             tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
@@ -2406,7 +2406,7 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
     for(i = 0; i < nb_regs; i++) {
         arg = args[nb_oargs + i];
         if (arg != TCG_CALL_DUMMY_ARG) {
-            ts = &s->temps[arg];
+            ts = arg_temp(arg);
             reg = tcg_target_call_iarg_regs[i];
             tcg_reg_free(s, reg, allocated_regs);
 
@@ -2429,7 +2429,7 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
     /* mark dead temporaries and free the associated registers */
     for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
         if (IS_DEAD_ARG(i)) {
-            temp_dead(s, &s->temps[args[i]]);
+            temp_dead(s, arg_temp(args[i]));
         }
     }
     
@@ -2455,7 +2455,7 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
     /* assign output registers and emit moves if needed */
     for(i = 0; i < nb_oargs; i++) {
         arg = args[i];
-        ts = &s->temps[arg];
+        ts = arg_temp(arg);
         reg = tcg_target_call_oarg_regs[i];
         tcg_debug_assert(s->reg_to_temp[reg] == NULL);
 
@@ -2627,7 +2627,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
             }
             break;
         case INDEX_op_discard:
-            temp_dead(s, &s->temps[args[0]]);
+            temp_dead(s, arg_temp(args[0]));
             break;
         case INDEX_op_set_label:
             tcg_reg_alloc_bb_end(s, s->reserved_regs);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC 07/14] tcg: Change temp_allocate_frame arg to TCGTemp
  2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
                   ` (5 preceding siblings ...)
  2016-11-16 19:51 ` [Qemu-devel] [RFC 06/14] tcg: More use of arg_temp Richard Henderson
@ 2016-11-16 19:51 ` Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 08/14] tcg: Remove unused TCG_CALL_DUMMY_TCGV Richard Henderson
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 4bcdb1e..c9e0da5 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1865,10 +1865,8 @@ static void check_regs(TCGContext *s)
 }
 #endif
 
-static void temp_allocate_frame(TCGContext *s, int temp)
+static void temp_allocate_frame(TCGContext *s, TCGTemp *ts)
 {
-    TCGTemp *ts;
-    ts = &s->temps[temp];
 #if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64)
     /* Sparc64 stack is accessed with offset of 2047 */
     s->current_frame_offset = (s->current_frame_offset +
@@ -1921,7 +1919,7 @@ static void temp_sync(TCGContext *s, TCGTemp *ts,
     }
     if (!ts->mem_coherent) {
         if (!ts->mem_allocated) {
-            temp_allocate_frame(s, temp_idx(ts));
+            temp_allocate_frame(s, ts);
         }
         switch (ts->val_type) {
         case TEMP_VAL_CONST:
@@ -2152,7 +2150,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
            liveness analysis disabled). */
         tcg_debug_assert(NEED_SYNC_ARG(0));
         if (!ots->mem_allocated) {
-            temp_allocate_frame(s, args[0]);
+            temp_allocate_frame(s, ots);
         }
         tcg_out_st(s, otype, ts->reg, ots->mem_base->reg, ots->mem_offset);
         if (IS_DEAD_ARG(1)) {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC 08/14] tcg: Remove unused TCG_CALL_DUMMY_TCGV
  2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
                   ` (6 preceding siblings ...)
  2016-11-16 19:51 ` [Qemu-devel] [RFC 07/14] tcg: Change temp_allocate_frame arg to TCGTemp Richard Henderson
@ 2016-11-16 19:51 ` Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 09/14] tcg: More use of arg_index Richard Henderson
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tcg/tcg.h b/tcg/tcg.h
index dbd6308..acc0cfb 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -483,7 +483,6 @@ typedef TCGv_ptr TCGv_env;
 #define TCG_CALL_NO_WG_SE       (TCG_CALL_NO_WG | TCG_CALL_NO_SE)
 
 /* used to align parameters */
-#define TCG_CALL_DUMMY_TCGV     MAKE_TCGV_I32(-1)
 #define TCG_CALL_DUMMY_ARG      ((TCGArg)(-1))
 
 typedef enum {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC 09/14] tcg: More use of arg_index
  2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
                   ` (7 preceding siblings ...)
  2016-11-16 19:51 ` [Qemu-devel] [RFC 08/14] tcg: Remove unused TCG_CALL_DUMMY_TCGV Richard Henderson
@ 2016-11-16 19:51 ` Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 10/14] tcg: Map TCG_CALL_DUMMY_ARG to NULL Richard Henderson
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index c9e0da5..e8b3fbb 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1024,13 +1024,14 @@ void tcg_dump_ops(TCGContext *s)
                             args[nb_oargs + nb_iargs + 1], nb_oargs);
             for (i = 0; i < nb_oargs; i++) {
                 col += qemu_log(",%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
-                                                           args[i]));
+                                                           arg_index(args[i])));
             }
             for (i = 0; i < nb_iargs; i++) {
                 TCGArg arg = args[nb_oargs + i];
                 const char *t = "<dummy>";
                 if (arg != TCG_CALL_DUMMY_ARG) {
-                    t = tcg_get_arg_str_idx(s, buf, sizeof(buf), arg);
+                    t = tcg_get_arg_str_idx(s, buf, sizeof(buf),
+                                            arg_index(arg));
                 }
                 col += qemu_log(",%s", t);
             }
@@ -1047,14 +1048,14 @@ void tcg_dump_ops(TCGContext *s)
                     col += qemu_log(",");
                 }
                 col += qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
-                                                          args[k++]));
+                                                          arg_index(args[k++])));
             }
             for (i = 0; i < nb_iargs; i++) {
                 if (k != 0) {
                     col += qemu_log(",");
                 }
                 col += qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
-                                                          args[k++]));
+                                                          arg_index(args[k++])));
             }
             switch (c) {
             case INDEX_op_brcond_i32:
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC 10/14] tcg: Map TCG_CALL_DUMMY_ARG to NULL
  2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
                   ` (8 preceding siblings ...)
  2016-11-16 19:51 ` [Qemu-devel] [RFC 09/14] tcg: More use of arg_index Richard Henderson
@ 2016-11-16 19:51 ` Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 11/14] tcg: Introduce temp_info for the optimize pass Richard Henderson
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.c | 36 +++++++++++++-----------------------
 tcg/tcg.h |  2 +-
 2 files changed, 14 insertions(+), 24 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index e8b3fbb..c62f161 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1415,7 +1415,6 @@ static void liveness_pass_1(TCGContext *s)
         bool have_opc_new2;
         TCGLifeData arg_life = 0;
         TCGTemp *arg_ts;
-        TCGArg arg_idx;
 
         TCGOp * const op = &s->gen_op_buf[oi];
         TCGArg * const args = &s->gen_opparam_buf[op->args];
@@ -1472,19 +1471,15 @@ static void liveness_pass_1(TCGContext *s)
 
                     /* record arguments that die in this helper */
                     for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
-                        arg_idx = arg_index(args[i]);
-                        if (arg_idx != TCG_CALL_DUMMY_ARG) {
-                            arg_ts = arg_temp(args[i]);
-                            if (arg_ts->state & TS_DEAD) {
-                                arg_life |= DEAD_ARG << i;
-                            }
+                        arg_ts = arg_temp(args[i]);
+                        if (arg_ts && (arg_ts->state & TS_DEAD)) {
+                            arg_life |= DEAD_ARG << i;
                         }
                     }
                     /* input arguments are live for preceding opcodes */
                     for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
-                        arg_idx = arg_index(args[i]);
-                        if (arg_idx != TCG_CALL_DUMMY_ARG) {
-                            arg_ts = arg_temp(args[i]);
+                        arg_ts = arg_temp(args[i]);
+                        if (arg_ts) {
                             arg_ts->state &= ~TS_DEAD;
                         }
                     }
@@ -1690,12 +1685,10 @@ static bool liveness_pass_2(TCGContext *s)
 
         /* Make sure that input arguments are available.  */
         for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
-            arg_idx = arg_index(args[i]);
-            /* Note this unsigned test catches TCG_CALL_ARG_DUMMY too.  */
-            if (arg_idx < nb_globals) {
-                arg_ts = arg_temp(args[i]);
+            arg_ts = arg_temp(args[i]);
+            if (arg_ts) {
                 dir_ts = arg_ts->state_ptr;
-                if (dir_ts != 0 && arg_ts->state == TS_DEAD) {
+                if (dir_ts && arg_ts->state == TS_DEAD) {
                     TCGOpcode lopc = (arg_ts->type == TCG_TYPE_I32
                                       ? INDEX_op_ld_i32
                                       : INDEX_op_ld_i64);
@@ -1716,12 +1709,10 @@ static bool liveness_pass_2(TCGContext *s)
            No action is required except keeping temp_state up to date
            so that we reload when needed.  */
         for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
-            arg_idx = arg_index(args[i]);
-            /* Note this unsigned test catches TCG_CALL_ARG_DUMMY too.  */
-            if (arg_idx < nb_globals) {
-                arg_ts = arg_temp(args[i]);
+            arg_ts = arg_temp(args[i]);
+            if (arg_ts) {
                 dir_ts = arg_ts->state_ptr;
-                if (dir_ts != 0) {
+                if (dir_ts) {
                     args[i] = temp_idx(dir_ts);
                     changes = true;
                     if (IS_DEAD_ARG(i)) {
@@ -2403,9 +2394,8 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
     /* assign input registers */
     tcg_regset_set(allocated_regs, s->reserved_regs);
     for(i = 0; i < nb_regs; i++) {
-        arg = args[nb_oargs + i];
-        if (arg != TCG_CALL_DUMMY_ARG) {
-            ts = arg_temp(arg);
+        ts = arg_temp(args[nb_oargs + i]);
+        if (ts) {
             reg = tcg_target_call_iarg_regs[i];
             tcg_reg_free(s, reg, allocated_regs);
 
diff --git a/tcg/tcg.h b/tcg/tcg.h
index acc0cfb..2670cab 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -483,7 +483,7 @@ typedef TCGv_ptr TCGv_env;
 #define TCG_CALL_NO_WG_SE       (TCG_CALL_NO_WG | TCG_CALL_NO_SE)
 
 /* used to align parameters */
-#define TCG_CALL_DUMMY_ARG      ((TCGArg)(-1))
+#define TCG_CALL_DUMMY_ARG      0
 
 typedef enum {
     /* Used to indicate the type of accesses on which ordering
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC 11/14] tcg: Introduce temp_info for the optimize pass
  2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
                   ` (9 preceding siblings ...)
  2016-11-16 19:51 ` [Qemu-devel] [RFC 10/14] tcg: Map TCG_CALL_DUMMY_ARG to NULL Richard Henderson
@ 2016-11-16 19:51 ` Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 12/14] tcg: Store pointers to temporaries directly in TCGArg Richard Henderson
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/optimize.c | 215 +++++++++++++++++++++++++++++++++------------------------
 1 file changed, 123 insertions(+), 92 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index f41ed2c..0e5d9d8 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -43,25 +43,34 @@ struct tcg_temp_info {
 static struct tcg_temp_info temps[TCG_MAX_TEMPS];
 static TCGTempSet temps_used;
 
+static inline struct tcg_temp_info *temp_info(TCGArg arg)
+{
+    return &temps[arg];
+}
+
 static inline bool temp_is_const(TCGArg arg)
 {
-    return temps[arg].is_const;
+    return temp_info(arg)->is_const;
 }
 
 static inline bool temp_is_copy(TCGArg arg)
 {
-    return temps[arg].next_copy != arg;
+    return temp_info(arg)->next_copy != arg;
 }
 
 /* Reset TEMP's state, possibly removing the temp for the list of copies.  */
 static void reset_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;
-    temps[temp].next_copy = temp;
-    temps[temp].prev_copy = temp;
-    temps[temp].is_const = false;
-    temps[temp].mask = -1;
+    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);
+
+    ni->prev_copy = ti->prev_copy;
+    pi->next_copy = ti->next_copy;
+    ti->next_copy = temp;
+    ti->prev_copy = temp;
+    ti->is_const = false;
+    ti->mask = -1;
 }
 
 /* Reset all temporaries, given that there are NB_TEMPS of them.  */
@@ -74,10 +83,11 @@ static void reset_all_temps(int nb_temps)
 static void init_temp_info(TCGArg temp)
 {
     if (!test_bit(temp, temps_used.l)) {
-        temps[temp].next_copy = temp;
-        temps[temp].prev_copy = temp;
-        temps[temp].is_const = false;
-        temps[temp].mask = -1;
+        struct tcg_temp_info *ti = temp_info(temp);
+        ti->next_copy = temp;
+        ti->prev_copy = temp;
+        ti->is_const = false;
+        ti->mask = -1;
         set_bit(temp, temps_used.l);
     }
 }
@@ -126,7 +136,8 @@ static TCGArg find_better_copy(TCGContext *s, TCGArg temp)
     }
 
     /* Search for a global first. */
-    for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
+    for (i = temp_info(temp)->next_copy; i != temp;
+         i = temp_info(i)->next_copy) {
         if (i < s->nb_globals) {
             return i;
         }
@@ -134,7 +145,8 @@ static TCGArg find_better_copy(TCGContext *s, TCGArg temp)
 
     /* If it is a temp, search for a temp local. */
     if (!s->temps[temp].temp_local) {
-        for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
+        for (i = temp_info(temp)->next_copy; i != temp;
+             i = temp_info(i)->next_copy) {
             if (s->temps[i].temp_local) {
                 return i;
             }
@@ -157,7 +169,8 @@ static bool temps_are_copies(TCGArg arg1, TCGArg arg2)
         return false;
     }
 
-    for (i = temps[arg1].next_copy ; i != arg1 ; i = temps[i].next_copy) {
+    for (i = temp_info(arg1)->next_copy; i != arg1;
+         i = temp_info(i)->next_copy) {
         if (i == arg2) {
             return true;
         }
@@ -171,18 +184,19 @@ 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);
 
     op->opc = new_op;
 
     reset_temp(dst);
-    temps[dst].is_const = true;
-    temps[dst].val = val;
+    di->is_const = true;
+    di->val = val;
     mask = val;
     if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_movi_i32) {
         /* High bits of the destination are now garbage.  */
         mask |= ~0xffffffffull;
     }
-    temps[dst].mask = mask;
+    di->mask = mask;
 
     args[0] = dst;
     args[1] = val;
@@ -196,26 +210,28 @@ 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);
     TCGOpcode new_op = op_to_mov(op->opc);
     tcg_target_ulong mask;
 
     op->opc = new_op;
 
     reset_temp(dst);
-    mask = temps[src].mask;
+    mask = si->mask;
     if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) {
         /* High bits of the destination are now garbage.  */
         mask |= ~0xffffffffull;
     }
-    temps[dst].mask = mask;
+    di->mask = mask;
 
     if (s->temps[src].type == s->temps[dst].type) {
-        temps[dst].next_copy = temps[src].next_copy;
-        temps[dst].prev_copy = src;
-        temps[temps[dst].next_copy].prev_copy = dst;
-        temps[src].next_copy = dst;
-        temps[dst].is_const = temps[src].is_const;
-        temps[dst].val = temps[src].val;
+        di->next_copy = si->next_copy;
+        di->prev_copy = src;
+        temp_info(di->next_copy)->prev_copy = dst;
+        si->next_copy = dst;
+        di->is_const = si->is_const;
+        di->val = si->val;
     }
 
     args[0] = dst;
@@ -448,18 +464,20 @@ static bool do_constant_folding_cond_eq(TCGCond c)
 static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
                                        TCGArg y, TCGCond c)
 {
+    tcg_target_ulong xv = temp_info(x)->val;
+    tcg_target_ulong yv = temp_info(y)->val;
     if (temp_is_const(x) && temp_is_const(y)) {
         switch (op_bits(op)) {
         case 32:
-            return do_constant_folding_cond_32(temps[x].val, temps[y].val, c);
+            return do_constant_folding_cond_32(xv, yv, c);
         case 64:
-            return do_constant_folding_cond_64(temps[x].val, temps[y].val, c);
+            return do_constant_folding_cond_64(xv, yv, c);
         default:
             tcg_abort();
         }
     } else if (temps_are_copies(x, y)) {
         return do_constant_folding_cond_eq(c);
-    } else if (temp_is_const(y) && temps[y].val == 0) {
+    } else if (temp_is_const(y) && yv == 0) {
         switch (c) {
         case TCG_COND_LTU:
             return 0;
@@ -480,11 +498,14 @@ static TCGArg do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c)
     TCGArg bl = p2[0], bh = p2[1];
 
     if (temp_is_const(bl) && temp_is_const(bh)) {
-        uint64_t b = ((uint64_t)temps[bh].val << 32) | (uint32_t)temps[bl].val;
+        tcg_target_ulong blv = temp_info(bl)->val;
+        tcg_target_ulong bhv = temp_info(bh)->val;
+        uint64_t b = deposit64(blv, 32, 32, bhv);
 
         if (temp_is_const(al) && temp_is_const(ah)) {
-            uint64_t a;
-            a = ((uint64_t)temps[ah].val << 32) | (uint32_t)temps[al].val;
+            tcg_target_ulong alv = temp_info(al)->val;
+            tcg_target_ulong ahv = temp_info(ah)->val;
+            uint64_t a = deposit64(alv, 32, 32, ahv);
             return do_constant_folding_cond_64(a, b, c);
         }
         if (b == 0) {
@@ -655,7 +676,7 @@ void tcg_optimize(TCGContext *s)
         CASE_OP_32_64(sar):
         CASE_OP_32_64(rotl):
         CASE_OP_32_64(rotr):
-            if (temp_is_const(args[1]) && temps[args[1]].val == 0) {
+            if (temp_is_const(args[1]) && temp_info(args[1])->val == 0) {
                 tcg_opt_gen_movi(s, op, args, args[0], 0);
                 continue;
             }
@@ -679,7 +700,7 @@ void tcg_optimize(TCGContext *s)
                 if (!have_neg) {
                     break;
                 }
-                if (temp_is_const(args[1]) && temps[args[1]].val == 0) {
+                if (temp_is_const(args[1]) && temp_info(args[1])->val == 0) {
                     op->opc = neg_op;
                     reset_temp(args[0]);
                     args[1] = args[2];
@@ -690,21 +711,24 @@ void tcg_optimize(TCGContext *s)
         CASE_OP_32_64(xor):
         CASE_OP_32_64(nand):
             if (!temp_is_const(args[1])
-                && temp_is_const(args[2]) && temps[args[2]].val == -1) {
+                && temp_is_const(args[2])
+                && temp_info(args[2])->val == -1) {
                 i = 1;
                 goto try_not;
             }
             break;
         CASE_OP_32_64(nor):
             if (!temp_is_const(args[1])
-                && temp_is_const(args[2]) && temps[args[2]].val == 0) {
+                && temp_is_const(args[2])
+                && temp_info(args[2])->val == 0) {
                 i = 1;
                 goto try_not;
             }
             break;
         CASE_OP_32_64(andc):
             if (!temp_is_const(args[2])
-                && temp_is_const(args[1]) && temps[args[1]].val == -1) {
+                && temp_is_const(args[1])
+                && temp_info(args[1])->val == -1) {
                 i = 2;
                 goto try_not;
             }
@@ -712,7 +736,8 @@ void tcg_optimize(TCGContext *s)
         CASE_OP_32_64(orc):
         CASE_OP_32_64(eqv):
             if (!temp_is_const(args[2])
-                && temp_is_const(args[1]) && temps[args[1]].val == 0) {
+                && temp_is_const(args[1])
+                && temp_info(args[1])->val == 0) {
                 i = 2;
                 goto try_not;
             }
@@ -754,7 +779,8 @@ void tcg_optimize(TCGContext *s)
         CASE_OP_32_64(xor):
         CASE_OP_32_64(andc):
             if (!temp_is_const(args[1])
-                && temp_is_const(args[2]) && temps[args[2]].val == 0) {
+                && temp_is_const(args[2])
+                && temp_info(args[2])->val == 0) {
                 tcg_opt_gen_mov(s, op, args, args[0], args[1]);
                 continue;
             }
@@ -763,7 +789,8 @@ void tcg_optimize(TCGContext *s)
         CASE_OP_32_64(orc):
         CASE_OP_32_64(eqv):
             if (!temp_is_const(args[1])
-                && temp_is_const(args[2]) && temps[args[2]].val == -1) {
+                && temp_is_const(args[2])
+                && temp_info(args[2])->val == -1) {
                 tcg_opt_gen_mov(s, op, args, args[0], args[1]);
                 continue;
             }
@@ -778,21 +805,21 @@ void tcg_optimize(TCGContext *s)
         affected = -1;
         switch (opc) {
         CASE_OP_32_64(ext8s):
-            if ((temps[args[1]].mask & 0x80) != 0) {
+            if ((temp_info(args[1])->mask & 0x80) != 0) {
                 break;
             }
         CASE_OP_32_64(ext8u):
             mask = 0xff;
             goto and_const;
         CASE_OP_32_64(ext16s):
-            if ((temps[args[1]].mask & 0x8000) != 0) {
+            if ((temp_info(args[1])->mask & 0x8000) != 0) {
                 break;
             }
         CASE_OP_32_64(ext16u):
             mask = 0xffff;
             goto and_const;
         case INDEX_op_ext32s_i64:
-            if ((temps[args[1]].mask & 0x80000000) != 0) {
+            if ((temp_info(args[1])->mask & 0x80000000) != 0) {
                 break;
             }
         case INDEX_op_ext32u_i64:
@@ -800,100 +827,100 @@ void tcg_optimize(TCGContext *s)
             goto and_const;
 
         CASE_OP_32_64(and):
-            mask = temps[args[2]].mask;
+            mask = temp_info(args[2])->mask;
             if (temp_is_const(args[2])) {
         and_const:
-                affected = temps[args[1]].mask & ~mask;
+                affected = temp_info(args[1])->mask & ~mask;
             }
-            mask = temps[args[1]].mask & mask;
+            mask = temp_info(args[1])->mask & mask;
             break;
 
         case INDEX_op_ext_i32_i64:
-            if ((temps[args[1]].mask & 0x80000000) != 0) {
+            if ((temp_info(args[1])->mask & 0x80000000) != 0) {
                 break;
             }
         case INDEX_op_extu_i32_i64:
             /* We do not compute affected as it is a size changing op.  */
-            mask = (uint32_t)temps[args[1]].mask;
+            mask = (uint32_t)temp_info(args[1])->mask;
             break;
 
         CASE_OP_32_64(andc):
             /* Known-zeros does not imply known-ones.  Therefore unless
                args[2] is constant, we can't infer anything from it.  */
             if (temp_is_const(args[2])) {
-                mask = ~temps[args[2]].mask;
+                mask = ~temp_info(args[2])->mask;
                 goto and_const;
             }
             /* But we certainly know nothing outside args[1] may be set. */
-            mask = temps[args[1]].mask;
+            mask = temp_info(args[1])->mask;
             break;
 
         case INDEX_op_sar_i32:
             if (temp_is_const(args[2])) {
-                tmp = temps[args[2]].val & 31;
-                mask = (int32_t)temps[args[1]].mask >> tmp;
+                tmp = temp_info(args[2])->val & 31;
+                mask = (int32_t)temp_info(args[1])->mask >> tmp;
             }
             break;
         case INDEX_op_sar_i64:
             if (temp_is_const(args[2])) {
-                tmp = temps[args[2]].val & 63;
-                mask = (int64_t)temps[args[1]].mask >> tmp;
+                tmp = temp_info(args[2])->val & 63;
+                mask = (int64_t)temp_info(args[1])->mask >> tmp;
             }
             break;
 
         case INDEX_op_shr_i32:
             if (temp_is_const(args[2])) {
-                tmp = temps[args[2]].val & 31;
-                mask = (uint32_t)temps[args[1]].mask >> tmp;
+                tmp = temp_info(args[2])->val & 31;
+                mask = (uint32_t)temp_info(args[1])->mask >> tmp;
             }
             break;
         case INDEX_op_shr_i64:
             if (temp_is_const(args[2])) {
-                tmp = temps[args[2]].val & 63;
-                mask = (uint64_t)temps[args[1]].mask >> tmp;
+                tmp = temp_info(args[2])->val & 63;
+                mask = (uint64_t)temp_info(args[1])->mask >> tmp;
             }
             break;
 
         case INDEX_op_extrl_i64_i32:
-            mask = (uint32_t)temps[args[1]].mask;
+            mask = (uint32_t)temp_info(args[1])->mask;
             break;
         case INDEX_op_extrh_i64_i32:
-            mask = (uint64_t)temps[args[1]].mask >> 32;
+            mask = (uint64_t)temp_info(args[1])->mask >> 32;
             break;
 
         CASE_OP_32_64(shl):
             if (temp_is_const(args[2])) {
-                tmp = temps[args[2]].val & (TCG_TARGET_REG_BITS - 1);
-                mask = temps[args[1]].mask << tmp;
+                tmp = temp_info(args[2])->val & (TCG_TARGET_REG_BITS - 1);
+                mask = temp_info(args[1])->mask << tmp;
             }
             break;
 
         CASE_OP_32_64(neg):
             /* Set to 1 all bits to the left of the rightmost.  */
-            mask = -(temps[args[1]].mask & -temps[args[1]].mask);
+            mask = -(temp_info(args[1])->mask & -temp_info(args[1])->mask);
             break;
 
         CASE_OP_32_64(deposit):
-            mask = deposit64(temps[args[1]].mask, args[3], args[4],
-                             temps[args[2]].mask);
+            mask = deposit64(temp_info(args[1])->mask, args[3], args[4],
+                             temp_info(args[2])->mask);
             break;
 
         CASE_OP_32_64(extract):
-            mask = extract64(temps[args[1]].mask, args[2], args[3]);
+            mask = extract64(temp_info(args[1])->mask, args[2], args[3]);
             if (args[2] == 0) {
-                affected = temps[args[1]].mask & ~mask;
+                affected = temp_info(args[1])->mask & ~mask;
             }
             break;
         CASE_OP_32_64(sextract):
-            mask = sextract64(temps[args[1]].mask, args[2], args[3]);
+            mask = sextract64(temp_info(args[1])->mask, args[2], args[3]);
             if (args[2] == 0 && (tcg_target_long)mask >= 0) {
-                affected = temps[args[1]].mask & ~mask;
+                affected = temp_info(args[1])->mask & ~mask;
             }
             break;
 
         CASE_OP_32_64(or):
         CASE_OP_32_64(xor):
-            mask = temps[args[1]].mask | temps[args[2]].mask;
+            mask = temp_info(args[1])->mask | temp_info(args[2])->mask;
             break;
 
         CASE_OP_32_64(setcond):
@@ -902,7 +929,7 @@ void tcg_optimize(TCGContext *s)
             break;
 
         CASE_OP_32_64(movcond):
-            mask = temps[args[3]].mask | temps[args[4]].mask;
+            mask = temp_info(args[3])->mask | temp_info(args[4])->mask;
             break;
 
         CASE_OP_32_64(ld8u):
@@ -956,7 +983,7 @@ void tcg_optimize(TCGContext *s)
         CASE_OP_32_64(mul):
         CASE_OP_32_64(muluh):
         CASE_OP_32_64(mulsh):
-            if ((temp_is_const(args[2]) && temps[args[2]].val == 0)) {
+            if ((temp_is_const(args[2]) && temp_info(args[2])->val == 0)) {
                 tcg_opt_gen_movi(s, op, args, args[0], 0);
                 continue;
             }
@@ -1016,7 +1043,7 @@ void tcg_optimize(TCGContext *s)
         case INDEX_op_extrl_i64_i32:
         case INDEX_op_extrh_i64_i32:
             if (temp_is_const(args[1])) {
-                tmp = do_constant_folding(opc, temps[args[1]].val, 0);
+                tmp = do_constant_folding(opc, temp_info(args[1])->val, 0);
                 tcg_opt_gen_movi(s, op, args, args[0], tmp);
                 break;
             }
@@ -1045,8 +1072,8 @@ void tcg_optimize(TCGContext *s)
         CASE_OP_32_64(rem):
         CASE_OP_32_64(remu):
             if (temp_is_const(args[1]) && temp_is_const(args[2])) {
-                tmp = do_constant_folding(opc, temps[args[1]].val,
-                                          temps[args[2]].val);
+                tmp = do_constant_folding(opc, temp_info(args[1])->val,
+                                          temp_info(args[2])->val);
                 tcg_opt_gen_movi(s, op, args, args[0], tmp);
                 break;
             }
@@ -1054,8 +1081,8 @@ void tcg_optimize(TCGContext *s)
 
         CASE_OP_32_64(deposit):
             if (temp_is_const(args[1]) && temp_is_const(args[2])) {
-                tmp = deposit64(temps[args[1]].val, args[3], args[4],
-                                temps[args[2]].val);
+                tmp = deposit64(temp_info(args[1])->val, args[3], args[4],
+                                temp_info(args[2])->val);
                 tcg_opt_gen_movi(s, op, args, args[0], tmp);
                 break;
             }
@@ -1063,7 +1090,7 @@ void tcg_optimize(TCGContext *s)
 
         CASE_OP_32_64(extract):
             if (temp_is_const(args[1])) {
-                tmp = extract64(temps[args[1]].val, args[2], args[3]);
+                tmp = extract64(temp_info(args[1])->val, args[2], args[3]);
                 tcg_opt_gen_movi(s, op, args, args[0], tmp);
                 break;
             }
@@ -1071,7 +1098,7 @@ void tcg_optimize(TCGContext *s)
 
         CASE_OP_32_64(sextract):
             if (temp_is_const(args[1])) {
-                tmp = sextract64(temps[args[1]].val, args[2], args[3]);
+                tmp = sextract64(temp_info(args[1])->val, args[2], args[3]);
                 tcg_opt_gen_movi(s, op, args, args[0], tmp);
                 break;
             }
@@ -1111,10 +1138,10 @@ void tcg_optimize(TCGContext *s)
         case INDEX_op_sub2_i32:
             if (temp_is_const(args[2]) && temp_is_const(args[3])
                 && temp_is_const(args[4]) && temp_is_const(args[5])) {
-                uint32_t al = temps[args[2]].val;
-                uint32_t ah = temps[args[3]].val;
-                uint32_t bl = temps[args[4]].val;
-                uint32_t bh = temps[args[5]].val;
+                uint32_t al = temp_info(args[2])->val;
+                uint32_t ah = temp_info(args[3])->val;
+                uint32_t bl = temp_info(args[4])->val;
+                uint32_t bh = temp_info(args[5])->val;
                 uint64_t a = ((uint64_t)ah << 32) | al;
                 uint64_t b = ((uint64_t)bh << 32) | bl;
                 TCGArg rl, rh;
@@ -1140,8 +1167,8 @@ void tcg_optimize(TCGContext *s)
 
         case INDEX_op_mulu2_i32:
             if (temp_is_const(args[2]) && temp_is_const(args[3])) {
-                uint32_t a = temps[args[2]].val;
-                uint32_t b = temps[args[3]].val;
+                uint32_t a = temp_info(args[2])->val;
+                uint32_t b = temp_info(args[3])->val;
                 uint64_t r = (uint64_t)a * b;
                 TCGArg rl, rh;
                 TCGOp *op2 = tcg_op_insert_before(s, op, INDEX_op_movi_i32, 2);
@@ -1171,8 +1198,10 @@ void tcg_optimize(TCGContext *s)
                     tcg_op_remove(s, op);
                 }
             } else if ((args[4] == TCG_COND_LT || args[4] == TCG_COND_GE)
-                       && temp_is_const(args[2]) && temps[args[2]].val == 0
-                       && temp_is_const(args[3]) && temps[args[3]].val == 0) {
+                       && temp_is_const(args[2])
+                       && temp_info(args[2])->val == 0
+                       && temp_is_const(args[3])
+                       && temp_info(args[3])->val == 0) {
                 /* Simplify LT/GE comparisons vs zero to a single compare
                    vs the high word of the input.  */
             do_brcond_high:
@@ -1234,13 +1263,15 @@ void tcg_optimize(TCGContext *s)
             do_setcond_const:
                 tcg_opt_gen_movi(s, op, args, args[0], tmp);
             } else if ((args[5] == TCG_COND_LT || args[5] == TCG_COND_GE)
-                       && temp_is_const(args[3]) && temps[args[3]].val == 0
-                       && temp_is_const(args[4]) && temps[args[4]].val == 0) {
+                       && temp_is_const(args[3])
+                       && temp_info(args[3])->val == 0
+                       && temp_is_const(args[4])
+                       && temp_info(args[4])->val == 0) {
                 /* Simplify LT/GE comparisons vs zero to a single compare
                    vs the high word of the input.  */
             do_setcond_high:
                 reset_temp(args[0]);
-                temps[args[0]].mask = 1;
+                temp_info(args[0])->mask = 1;
                 op->opc = INDEX_op_setcond_i32;
                 args[1] = args[2];
                 args[2] = args[4];
@@ -1264,7 +1295,7 @@ void tcg_optimize(TCGContext *s)
                 }
             do_setcond_low:
                 reset_temp(args[0]);
-                temps[args[0]].mask = 1;
+                temp_info(args[0])->mask = 1;
                 op->opc = INDEX_op_setcond_i32;
                 args[2] = args[3];
                 args[3] = args[5];
@@ -1318,7 +1349,7 @@ void tcg_optimize(TCGContext *s)
                     /* Save the corresponding known-zero bits mask for the
                        first output argument (only one supported so far). */
                     if (i == 0) {
-                        temps[args[i]].mask = mask;
+                        temp_info(args[i])->mask = mask;
                     }
                 }
             }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC 12/14] tcg: Store pointers to temporaries directly in TCGArg
  2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
                   ` (10 preceding siblings ...)
  2016-11-16 19:51 ` [Qemu-devel] [RFC 11/14] tcg: Introduce temp_info for the optimize pass Richard Henderson
@ 2016-11-16 19:51 ` Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 13/14] tcg: Use temp number 0 again Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 14/14] tcg/optimize: Fold movcond 0/1 into setcond Richard Henderson
  13 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 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

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC 13/14] tcg: Use temp number 0 again
  2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
                   ` (11 preceding siblings ...)
  2016-11-16 19:51 ` [Qemu-devel] [RFC 12/14] tcg: Store pointers to temporaries directly in TCGArg Richard Henderson
@ 2016-11-16 19:51 ` Richard Henderson
  2016-11-16 19:51 ` [Qemu-devel] [RFC 14/14] tcg/optimize: Fold movcond 0/1 into setcond Richard Henderson
  13 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

Now that we're storing pointers, we don't have to reserve
index 0 to avoid the apperance of a NULL pointer.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index a2a0b90..d4409ad 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -330,11 +330,6 @@ void tcg_context_init(TCGContext *s)
 
     memset(s, 0, sizeof(*s));
 
-    /* Reserve global 0 so that, when foxing these integrals
-       as pointers, NULL is unused.  */
-    s->nb_globals = 1;
-    s->nb_temps = 1;
-
     /* Count total number of arguments and allocate the corresponding
        space */
     total_args = 0;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Qemu-devel] [RFC 14/14] tcg/optimize: Fold movcond 0/1 into setcond
  2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
                   ` (12 preceding siblings ...)
  2016-11-16 19:51 ` [Qemu-devel] [RFC 13/14] tcg: Use temp number 0 again Richard Henderson
@ 2016-11-16 19:51 ` Richard Henderson
  13 siblings, 0 replies; 15+ messages in thread
From: Richard Henderson @ 2016-11-16 19:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: aurelien, peter.maydell

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/optimize.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index 06a8c13..28ce624 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -1143,6 +1143,21 @@ void tcg_optimize(TCGContext *s)
                 tcg_opt_gen_mov(s, op, args, args[0], args[4-tmp]);
                 break;
             }
+            if (temp_is_const(args[3]) && temp_is_const(args[4])) {
+                tcg_target_ulong tv = temp_info(args[3])->val;
+                tcg_target_ulong fv = temp_info(args[4])->val;
+                TCGCond cond = args[5];
+                if (fv == 1 && tv == 0) {
+                    cond = tcg_invert_cond(cond);
+                } else if (!(tv == 1 && fv == 0)) {
+                    goto do_default;
+                }
+                args[3] = cond;
+                op->opc = opc = (opc == INDEX_op_movcond_i32
+                                 ? INDEX_op_setcond_i32
+                                 : INDEX_op_setcond_i64);
+                nb_iargs = 2;
+            }
             goto do_default;
 
         case INDEX_op_add2_i32:
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2016-11-16 19:52 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-11-16 19:51 [Qemu-devel] [RFC 00/14] tcg: Use TCGTemp pointers instead of indices Richard Henderson
2016-11-16 19:51 ` [Qemu-devel] [RFC 01/14] tcg: Use NULL for TCGV_UNUSED_* Richard Henderson
2016-11-16 19:51 ` [Qemu-devel] [RFC 02/14] tcg: Define actual structures for TCGv_* Richard Henderson
2016-11-16 19:51 ` [Qemu-devel] [RFC 03/14] tcg: Use per-temp state data in liveness Richard Henderson
2016-11-16 19:51 ` [Qemu-devel] [RFC 04/14] tcg: Add temp_global bit to TCGTemp Richard Henderson
2016-11-16 19:51 ` [Qemu-devel] [RFC 05/14] tcg: Avoid loops against variable bounds Richard Henderson
2016-11-16 19:51 ` [Qemu-devel] [RFC 06/14] tcg: More use of arg_temp Richard Henderson
2016-11-16 19:51 ` [Qemu-devel] [RFC 07/14] tcg: Change temp_allocate_frame arg to TCGTemp Richard Henderson
2016-11-16 19:51 ` [Qemu-devel] [RFC 08/14] tcg: Remove unused TCG_CALL_DUMMY_TCGV Richard Henderson
2016-11-16 19:51 ` [Qemu-devel] [RFC 09/14] tcg: More use of arg_index Richard Henderson
2016-11-16 19:51 ` [Qemu-devel] [RFC 10/14] tcg: Map TCG_CALL_DUMMY_ARG to NULL Richard Henderson
2016-11-16 19:51 ` [Qemu-devel] [RFC 11/14] tcg: Introduce temp_info for the optimize pass Richard Henderson
2016-11-16 19:51 ` [Qemu-devel] [RFC 12/14] tcg: Store pointers to temporaries directly in TCGArg Richard Henderson
2016-11-16 19:51 ` [Qemu-devel] [RFC 13/14] tcg: Use temp number 0 again Richard Henderson
2016-11-16 19:51 ` [Qemu-devel] [RFC 14/14] tcg/optimize: Fold movcond 0/1 into setcond Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).