All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows
@ 2015-12-17 19:58 Richard Henderson
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 02/14] tcg: Change ts->mem_reg to ts->mem_base Richard Henderson
                   ` (12 more replies)
  0 siblings, 13 replies; 26+ messages in thread
From: Richard Henderson @ 2015-12-17 19:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien

This is a two year old patch set that I revived just before the 2.5 cutoff;
I decided against re-posting it then, but now that 2.6 development is open,
I think it's time to try again.

The Idea is to let TCG know that the 24 windowed registers are accessed
via a different base register than TCG_AREG0.  Moreover, the base register
by which they are accessed is itself loaded via TCG_AREG0.  A simple bit
of recursion in the tcg register allocation functions that allows this
to happen.

We were able to do some benchmarking with this patch set during the
summer and fall; it's somewhere on the mailing list if you want to go
looking.


r~


Richard Henderson (14):
  tcg: Change tcg_global_mem_new_* to take a TCGv_ptr
  tcg: Change ts->mem_reg to ts->mem_base
  tcg: Tidy temporary allocation
  tcg: More use of TCGReg where appropriate
  tcg: Remove tcg_get_arg_str_i32/64
  tcg: Change reg_to_temp to TCGTemp pointer
  tcg: Change temp_dead argument to TCGTemp
  tcg: Change temp_sync argument to TCGTemp
  tcg: Change temp_save argument to TCGTemp
  tcg: Introduce temp_load
  tcg: Implement indirect memory registers
  tcg: Allocate indirect_base temporaries in a different order
  target-sparc: Tidy global register initialization
  target-sparc: Use global registers for the register window

 target-alpha/translate.c      |   8 +-
 target-arm/translate-a64.c    |   6 +-
 target-arm/translate.c        |  18 +-
 target-cris/translate.c       |  24 +-
 target-cris/translate_v10.c   |  82 +++---
 target-i386/translate.c       |  10 +-
 target-lm32/translate.c       |  24 +-
 target-m68k/translate.c       |  30 +-
 target-microblaze/translate.c |  18 +-
 target-mips/translate.c       |  25 +-
 target-moxie/translate.c      |   8 +-
 target-openrisc/translate.c   |  26 +-
 target-ppc/translate.c        |  44 +--
 target-s390x/translate.c      |  18 +-
 target-sh4/translate.c        |  48 ++--
 target-sparc/translate.c      | 192 ++++++-------
 target-tilegx/translate.c     |   4 +-
 target-tricore/translate.c    |  22 +-
 target-unicore32/translate.c  |   2 +-
 target-xtensa/translate.c     |  10 +-
 tcg/tcg.c                     | 639 +++++++++++++++++++++---------------------
 tcg/tcg.h                     |  51 ++--
 22 files changed, 670 insertions(+), 639 deletions(-)

-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 02/14] tcg: Change ts->mem_reg to ts->mem_base
  2015-12-17 19:58 [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows Richard Henderson
@ 2015-12-17 20:00 ` Richard Henderson
  2015-12-31 10:52   ` Aurelien Jarno
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 03/14] tcg: Tidy temporary allocation Richard Henderson
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 2015-12-17 20:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien

Chain the temporaries together via pointers intstead of indices.
The mem_reg value is now mem_base->reg.  This will be important later.

This does require that the frame pointer have a global temporary
allocated for it.  This is simple bar the existing reserved_regs check.

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

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 3dbcb84..b1864d3 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -406,13 +406,6 @@ void tcg_prologue_init(TCGContext *s)
 #endif
 }
 
-void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size)
-{
-    s->frame_start = start;
-    s->frame_end = start + size;
-    s->frame_reg = reg;
-}
-
 void tcg_func_start(TCGContext *s)
 {
     tcg_pool_reset(s);
@@ -442,19 +435,15 @@ static inline void tcg_temp_alloc(TCGContext *s, int n)
         tcg_abort();
 }
 
-static inline int tcg_global_reg_new_internal(TCGType type, int reg,
-                                              const char *name)
+static int tcg_global_reg_new_internal(TCGContext *s, TCGType type,
+                                       int reg, const char *name)
 {
-    TCGContext *s = &tcg_ctx;
     TCGTemp *ts;
     int idx;
 
-#if TCG_TARGET_REG_BITS == 32
-    if (type != TCG_TYPE_I32)
-        tcg_abort();
-#endif
-    if (tcg_regset_test_reg(s->reserved_regs, reg))
+    if (TCG_TARGET_REG_BITS == 32 && type != TCG_TYPE_I32) {
         tcg_abort();
+    }
     idx = s->nb_globals;
     tcg_temp_alloc(s, s->nb_globals + 1);
     ts = &s->temps[s->nb_globals];
@@ -468,19 +457,36 @@ static inline int tcg_global_reg_new_internal(TCGType type, int reg,
     return idx;
 }
 
+void tcg_set_frame(TCGContext *s, int 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];
+}
+
 TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
 {
+    TCGContext *s = &tcg_ctx;
     int idx;
 
-    idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
+    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);
 }
 
 TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
 {
+    TCGContext *s = &tcg_ctx;
     int idx;
 
-    idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
+    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);
 }
 
@@ -489,7 +495,7 @@ int tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
 {
     TCGContext *s = &tcg_ctx;
     TCGTemp *ts, *base_ts = &s->temps[GET_TCGV_PTR(base)];
-    int idx, reg = base_ts->reg;
+    int idx;
 
     idx = s->nb_globals;
 #if TCG_TARGET_REG_BITS == 32
@@ -501,7 +507,7 @@ int tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
         ts->type = TCG_TYPE_I32;
         ts->fixed_reg = 0;
         ts->mem_allocated = 1;
-        ts->mem_reg = reg;
+        ts->mem_base = base_ts;
 #ifdef HOST_WORDS_BIGENDIAN
         ts->mem_offset = offset + 4;
 #else
@@ -516,7 +522,7 @@ int tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
         ts->type = TCG_TYPE_I32;
         ts->fixed_reg = 0;
         ts->mem_allocated = 1;
-        ts->mem_reg = reg;
+        ts->mem_base = base_ts;
 #ifdef HOST_WORDS_BIGENDIAN
         ts->mem_offset = offset;
 #else
@@ -536,7 +542,7 @@ int tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
         ts->type = type;
         ts->fixed_reg = 0;
         ts->mem_allocated = 1;
-        ts->mem_reg = reg;
+        ts->mem_base = base_ts;
         ts->mem_offset = offset;
         ts->name = name;
         s->nb_globals++;
@@ -1591,7 +1597,8 @@ static void dump_regs(TCGContext *s)
             printf("%s", tcg_target_reg_names[ts->reg]);
             break;
         case TEMP_VAL_MEM:
-            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
+            printf("%d(%s)", (int)ts->mem_offset,
+                   tcg_target_reg_names[ts->mem_base->reg]);
             break;
         case TEMP_VAL_CONST:
             printf("$0x%" TCG_PRIlx, ts->val);
@@ -1664,7 +1671,7 @@ static void temp_allocate_frame(TCGContext *s, int temp)
         tcg_abort();
     }
     ts->mem_offset = s->current_frame_offset;
-    ts->mem_reg = s->frame_reg;
+    ts->mem_base = s->frame_temp;
     ts->mem_allocated = 1;
     s->current_frame_offset += sizeof(tcg_target_long);
 }
@@ -1682,7 +1689,7 @@ static inline void tcg_reg_sync(TCGContext *s, int reg)
         if (!ts->mem_allocated) {
             temp_allocate_frame(s, temp);
         }
-        tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
+        tcg_out_st(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
     }
     ts->mem_coherent = 1;
 }
@@ -1898,7 +1905,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
         ts->reg = tcg_reg_alloc(s, tcg_target_available_regs[itype],
                                 allocated_regs);
         if (ts->val_type == TEMP_VAL_MEM) {
-            tcg_out_ld(s, itype, ts->reg, ts->mem_reg, ts->mem_offset);
+            tcg_out_ld(s, itype, ts->reg, ts->mem_base->reg, ts->mem_offset);
             ts->mem_coherent = 1;
         } else if (ts->val_type == TEMP_VAL_CONST) {
             tcg_out_movi(s, itype, ts->reg, ts->val);
@@ -1917,7 +1924,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
         if (!ots->mem_allocated) {
             temp_allocate_frame(s, args[0]);
         }
-        tcg_out_st(s, otype, ts->reg, ots->mem_reg, ots->mem_offset);
+        tcg_out_st(s, otype, ts->reg, ots->mem_base->reg, ots->mem_offset);
         if (IS_DEAD_ARG(1)) {
             temp_dead(s, args[1]);
         }
@@ -1992,7 +1999,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
         ts = &s->temps[arg];
         if (ts->val_type == TEMP_VAL_MEM) {
             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
-            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
+            tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
             ts->val_type = TEMP_VAL_REG;
             ts->reg = reg;
             ts->mem_coherent = 1;
@@ -2186,7 +2193,7 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
                 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
                                     s->reserved_regs);
                 /* XXX: not correct if reading values from the stack */
-                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
+                tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
                 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
             } else if (ts->val_type == TEMP_VAL_CONST) {
                 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
@@ -2216,7 +2223,7 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
                     tcg_out_mov(s, ts->type, reg, ts->reg);
                 }
             } else if (ts->val_type == TEMP_VAL_MEM) {
-                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
+                tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
             } else if (ts->val_type == TEMP_VAL_CONST) {
                 /* XXX: sign extend ? */
                 tcg_out_movi(s, ts->type, reg, ts->val);
diff --git a/tcg/tcg.h b/tcg/tcg.h
index e528b07..8b7efed 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -449,7 +449,6 @@ typedef enum TCGTempVal {
 
 typedef struct TCGTemp {
     unsigned int reg:8;
-    unsigned int mem_reg:8;
     TCGTempVal val_type:8;
     TCGType base_type:8;
     TCGType type:8;
@@ -462,6 +461,7 @@ typedef struct TCGTemp {
     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;
@@ -515,7 +515,7 @@ struct TCGContext {
     intptr_t current_frame_offset;
     intptr_t frame_start;
     intptr_t frame_end;
-    int frame_reg;
+    TCGTemp *frame_temp;
 
     tcg_insn_unit *code_ptr;
 
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 03/14] tcg: Tidy temporary allocation
  2015-12-17 19:58 [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows Richard Henderson
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 02/14] tcg: Change ts->mem_reg to ts->mem_base Richard Henderson
@ 2015-12-17 20:00 ` Richard Henderson
  2015-12-31 11:13   ` Aurelien Jarno
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 04/14] tcg: More use of TCGReg where appropriate Richard Henderson
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 2015-12-17 20:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien

In particular, make sure the memory is memset before use.
Continues the increased use of TCGTemp pointers instead of
integer indices where appropriate.

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

diff --git a/tcg/tcg.c b/tcg/tcg.c
index b1864d3..0a6edfb 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -429,32 +429,45 @@ void tcg_func_start(TCGContext *s)
     s->be = tcg_malloc(sizeof(TCGBackendData));
 }
 
-static inline void tcg_temp_alloc(TCGContext *s, int n)
+static inline int temp_idx(TCGContext *s, TCGTemp *ts)
 {
-    if (n > TCG_MAX_TEMPS)
-        tcg_abort();
+    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++;
+    tcg_debug_assert(n < TCG_MAX_TEMPS);
+    return memset(&s->temps[n], 0, sizeof(TCGTemp));
+}
+
+static inline TCGTemp *tcg_global_alloc(TCGContext *s)
+{
+    tcg_debug_assert(s->nb_globals == s->nb_temps);
+    s->nb_globals++;
+    return tcg_temp_alloc(s);
 }
 
 static int tcg_global_reg_new_internal(TCGContext *s, TCGType type,
                                        int reg, const char *name)
 {
     TCGTemp *ts;
-    int idx;
 
     if (TCG_TARGET_REG_BITS == 32 && type != TCG_TYPE_I32) {
         tcg_abort();
     }
-    idx = s->nb_globals;
-    tcg_temp_alloc(s, s->nb_globals + 1);
-    ts = &s->temps[s->nb_globals];
+
+    ts = tcg_global_alloc(s);
     ts->base_type = type;
     ts->type = type;
     ts->fixed_reg = 1;
     ts->reg = reg;
     ts->name = name;
-    s->nb_globals++;
     tcg_regset_set_reg(s->reserved_regs, reg);
-    return idx;
+
+    return temp_idx(s, ts);
 }
 
 void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size)
@@ -494,63 +507,47 @@ int tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
                                 intptr_t offset, const char *name)
 {
     TCGContext *s = &tcg_ctx;
-    TCGTemp *ts, *base_ts = &s->temps[GET_TCGV_PTR(base)];
-    int idx;
+    TCGTemp *base_ts = &s->temps[GET_TCGV_PTR(base)];
+    TCGTemp *ts = tcg_global_alloc(s);
+    int bigendian = 0;
+#ifdef HOST_WORDS_BIGENDIAN
+    bigendian = 1;
+#endif
 
-    idx = s->nb_globals;
-#if TCG_TARGET_REG_BITS == 32
-    if (type == TCG_TYPE_I64) {
+    if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
+        TCGTemp *ts2 = tcg_global_alloc(s);
         char buf[64];
-        tcg_temp_alloc(s, s->nb_globals + 2);
-        ts = &s->temps[s->nb_globals];
-        ts->base_type = type;
+
+        ts->base_type = TCG_TYPE_I64;
         ts->type = TCG_TYPE_I32;
-        ts->fixed_reg = 0;
         ts->mem_allocated = 1;
         ts->mem_base = base_ts;
-#ifdef HOST_WORDS_BIGENDIAN
-        ts->mem_offset = offset + 4;
-#else
-        ts->mem_offset = offset;
-#endif
+        ts->mem_offset = offset + bigendian * 4;
         pstrcpy(buf, sizeof(buf), name);
         pstrcat(buf, sizeof(buf), "_0");
         ts->name = strdup(buf);
-        ts++;
 
-        ts->base_type = type;
-        ts->type = TCG_TYPE_I32;
-        ts->fixed_reg = 0;
-        ts->mem_allocated = 1;
-        ts->mem_base = base_ts;
-#ifdef HOST_WORDS_BIGENDIAN
-        ts->mem_offset = offset;
-#else
-        ts->mem_offset = offset + 4;
-#endif
+        tcg_debug_assert(ts2 == ts + 1);
+        ts2->base_type = TCG_TYPE_I64;
+        ts2->type = TCG_TYPE_I32;
+        ts2->mem_allocated = 1;
+        ts2->mem_base = base_ts;
+        ts2->mem_offset = offset + (1 - bigendian) * 4;
         pstrcpy(buf, sizeof(buf), name);
         pstrcat(buf, sizeof(buf), "_1");
         ts->name = strdup(buf);
-
-        s->nb_globals += 2;
-    } else
-#endif
-    {
-        tcg_temp_alloc(s, s->nb_globals + 1);
-        ts = &s->temps[s->nb_globals];
+    } else {
         ts->base_type = type;
         ts->type = type;
-        ts->fixed_reg = 0;
         ts->mem_allocated = 1;
         ts->mem_base = base_ts;
         ts->mem_offset = offset;
         ts->name = name;
-        s->nb_globals++;
     }
-    return idx;
+    return temp_idx(s, ts);
 }
 
-static inline int tcg_temp_new_internal(TCGType type, int temp_local)
+static int tcg_temp_new_internal(TCGType type, int temp_local)
 {
     TCGContext *s = &tcg_ctx;
     TCGTemp *ts;
@@ -564,38 +561,30 @@ static inline int tcg_temp_new_internal(TCGType type, int temp_local)
 
         ts = &s->temps[idx];
         ts->temp_allocated = 1;
-        assert(ts->base_type == type);
-        assert(ts->temp_local == temp_local);
+        tcg_debug_assert(ts->base_type == type);
+        tcg_debug_assert(ts->temp_local == temp_local);
     } else {
-        idx = s->nb_temps;
-#if TCG_TARGET_REG_BITS == 32
-        if (type == TCG_TYPE_I64) {
-            tcg_temp_alloc(s, s->nb_temps + 2);
-            ts = &s->temps[s->nb_temps];
-            ts->base_type = type;
-            ts->type = TCG_TYPE_I32;
-            ts->temp_allocated = 1;
-            ts->temp_local = temp_local;
-            ts->name = NULL;
-            ts++;
+        ts = tcg_temp_alloc(s);
+        if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
+            TCGTemp *ts2 = tcg_temp_alloc(s);
+
             ts->base_type = type;
             ts->type = TCG_TYPE_I32;
             ts->temp_allocated = 1;
             ts->temp_local = temp_local;
-            ts->name = NULL;
-            s->nb_temps += 2;
-        } else
-#endif
-        {
-            tcg_temp_alloc(s, s->nb_temps + 1);
-            ts = &s->temps[s->nb_temps];
+
+            tcg_debug_assert(ts2 == ts + 1);
+            ts2->base_type = TCG_TYPE_I64;
+            ts2->type = TCG_TYPE_I32;
+            ts2->temp_allocated = 1;
+            ts2->temp_local = temp_local;
+        } else {
             ts->base_type = type;
             ts->type = type;
             ts->temp_allocated = 1;
             ts->temp_local = temp_local;
-            ts->name = NULL;
-            s->nb_temps++;
         }
+        idx = temp_idx(s, ts);
     }
 
 #if defined(CONFIG_DEBUG_TCG)
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 04/14] tcg: More use of TCGReg where appropriate
  2015-12-17 19:58 [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows Richard Henderson
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 02/14] tcg: Change ts->mem_reg to ts->mem_base Richard Henderson
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 03/14] tcg: Tidy temporary allocation Richard Henderson
@ 2015-12-17 20:00 ` Richard Henderson
  2015-12-31 11:14   ` Aurelien Jarno
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 05/14] tcg: Remove tcg_get_arg_str_i32/64 Richard Henderson
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 2015-12-17 20:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien

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

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 0a6edfb..06d71d7 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -451,7 +451,7 @@ static inline TCGTemp *tcg_global_alloc(TCGContext *s)
 }
 
 static int tcg_global_reg_new_internal(TCGContext *s, TCGType type,
-                                       int reg, const char *name)
+                                       TCGReg reg, const char *name)
 {
     TCGTemp *ts;
 
@@ -470,7 +470,7 @@ static int tcg_global_reg_new_internal(TCGContext *s, TCGType type,
     return temp_idx(s, ts);
 }
 
-void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size)
+void tcg_set_frame(TCGContext *s, TCGReg reg, intptr_t start, intptr_t size)
 {
     int idx;
     s->frame_start = start;
@@ -479,7 +479,7 @@ void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size)
     s->frame_temp = &s->temps[idx];
 }
 
-TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
+TCGv_i32 tcg_global_reg_new_i32(TCGReg reg, const char *name)
 {
     TCGContext *s = &tcg_ctx;
     int idx;
@@ -491,7 +491,7 @@ TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
     return MAKE_TCGV_I32(idx);
 }
 
-TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
+TCGv_i64 tcg_global_reg_new_i64(TCGReg reg, const char *name)
 {
     TCGContext *s = &tcg_ctx;
     int idx;
@@ -1613,7 +1613,8 @@ static void dump_regs(TCGContext *s)
 
 static void check_regs(TCGContext *s)
 {
-    int reg, k;
+    TCGReg reg;
+    int k;
     TCGTemp *ts;
     char buf[64];
 
@@ -1666,7 +1667,7 @@ static void temp_allocate_frame(TCGContext *s, int temp)
 }
 
 /* sync register 'reg' by saving it to the corresponding temporary */
-static inline void tcg_reg_sync(TCGContext *s, int reg)
+static inline void tcg_reg_sync(TCGContext *s, TCGReg reg)
 {
     TCGTemp *ts;
     int temp;
@@ -1684,7 +1685,7 @@ static inline void tcg_reg_sync(TCGContext *s, int reg)
 }
 
 /* free register 'reg' by spilling the corresponding temporary if necessary */
-static void tcg_reg_free(TCGContext *s, int reg)
+static void tcg_reg_free(TCGContext *s, TCGReg reg)
 {
     int temp;
 
@@ -1697,9 +1698,10 @@ static void tcg_reg_free(TCGContext *s, int reg)
 }
 
 /* Allocate a register belonging to reg1 & ~reg2 */
-static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
+static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
 {
-    int i, reg;
+    int i;
+    TCGReg reg;
     TCGRegSet reg_ct;
 
     tcg_regset_andnot(reg_ct, reg1, reg2);
@@ -1964,7 +1966,8 @@ static void tcg_reg_alloc_op(TCGContext *s,
                              uint8_t sync_args)
 {
     TCGRegSet allocated_regs;
-    int i, k, nb_iargs, nb_oargs, reg;
+    int i, k, nb_iargs, nb_oargs;
+    TCGReg reg;
     TCGArg arg;
     const TCGArgConstraint *arg_ct;
     TCGTemp *ts;
@@ -2140,7 +2143,8 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
                                const TCGArg * const args, uint16_t dead_args,
                                uint8_t sync_args)
 {
-    int flags, nb_regs, i, reg;
+    int flags, nb_regs, i;
+    TCGReg reg;
     TCGArg arg;
     TCGTemp *ts;
     intptr_t stack_offset;
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 8b7efed..3674739 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -448,7 +448,7 @@ typedef enum TCGTempVal {
 } TCGTempVal;
 
 typedef struct TCGTemp {
-    unsigned int reg:8;
+    TCGReg reg:8;
     TCGTempVal val_type:8;
     TCGType base_type:8;
     TCGType type:8;
@@ -628,12 +628,12 @@ void tcg_func_start(TCGContext *s);
 
 int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf);
 
-void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size);
+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 *);
 
-TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name);
-TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name);
+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);
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 05/14] tcg: Remove tcg_get_arg_str_i32/64
  2015-12-17 19:58 [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows Richard Henderson
                   ` (2 preceding siblings ...)
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 04/14] tcg: More use of TCGReg where appropriate Richard Henderson
@ 2015-12-17 20:00 ` Richard Henderson
  2015-12-31 11:15   ` Aurelien Jarno
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 06/14] tcg: Change reg_to_temp to TCGTemp pointer Richard Henderson
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 2015-12-17 20:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.c | 10 ----------
 tcg/tcg.h |  5 -----
 2 files changed, 15 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 06d71d7..b6cd85c 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -926,16 +926,6 @@ static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
     return buf;
 }
 
-char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
-{
-    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
-}
-
-char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
-{
-    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
-}
-
 /* Find helper name.  */
 static inline const char *tcg_find_helper(TCGContext *s, uintptr_t val)
 {
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 3674739..223d9c6 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -641,11 +641,6 @@ 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);
 
-char *tcg_get_arg_str_i32(TCGContext *s, char *buf,
-                          int buf_size, TCGv_i32 arg);
-char *tcg_get_arg_str_i64(TCGContext *s, char *buf,
-                          int buf_size, TCGv_i64 arg);
-
 static inline TCGv_i32 tcg_global_mem_new_i32(TCGv_ptr reg, intptr_t offset,
                                               const char *name)
 {
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 06/14] tcg: Change reg_to_temp to TCGTemp pointer
  2015-12-17 19:58 [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows Richard Henderson
                   ` (3 preceding siblings ...)
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 05/14] tcg: Remove tcg_get_arg_str_i32/64 Richard Henderson
@ 2015-12-17 20:00 ` Richard Henderson
  2015-12-31 11:19   ` Aurelien Jarno
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 07/14] tcg: Change temp_dead argument to TCGTemp Richard Henderson
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 2015-12-17 20:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien

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

diff --git a/tcg/tcg.c b/tcg/tcg.c
index b6cd85c..d91950d 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -903,29 +903,32 @@ static void tcg_reg_alloc_start(TCGContext *s)
         ts->mem_allocated = 0;
         ts->fixed_reg = 0;
     }
-    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
-        s->reg_to_temp[i] = -1;
-    }
+
+    memset(s->reg_to_temp, 0, sizeof(s->reg_to_temp));
 }
 
-static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
-                                 int idx)
+static char *tcg_get_arg_str_ptr(TCGContext *s, char *buf, int buf_size,
+                                 TCGTemp *ts)
 {
-    TCGTemp *ts;
+    int idx = temp_idx(s, ts);
 
-    assert(idx >= 0 && idx < s->nb_temps);
-    ts = &s->temps[idx];
     if (idx < s->nb_globals) {
         pstrcpy(buf, buf_size, ts->name);
+    } else if (ts->temp_local) {
+        snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
     } else {
-        if (ts->temp_local) 
-            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
-        else
-            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
+        snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
     }
     return buf;
 }
 
+static char *tcg_get_arg_str_idx(TCGContext *s, char *buf,
+                                 int buf_size, int idx)
+{
+    assert(idx >= 0 && idx < s->nb_temps);
+    return tcg_get_arg_str_ptr(s, buf, buf_size, &s->temps[idx]);
+}
+
 /* Find helper name.  */
 static inline const char *tcg_find_helper(TCGContext *s, uintptr_t val)
 {
@@ -1593,10 +1596,10 @@ static void dump_regs(TCGContext *s)
     }
 
     for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
-        if (s->reg_to_temp[i] >= 0) {
+        if (s->reg_to_temp[i] != NULL) {
             printf("%s: %s\n", 
                    tcg_target_reg_names[i], 
-                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
+                   tcg_get_arg_str_ptr(s, buf, sizeof(buf), s->reg_to_temp[i]));
         }
     }
 }
@@ -1608,29 +1611,26 @@ static void check_regs(TCGContext *s)
     TCGTemp *ts;
     char buf[64];
 
-    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
-        k = s->reg_to_temp[reg];
-        if (k >= 0) {
-            ts = &s->temps[k];
-            if (ts->val_type != TEMP_VAL_REG ||
-                ts->reg != reg) {
+    for (reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
+        ts = s->reg_to_temp[reg];
+        if (ts != NULL) {
+            if (ts->val_type != TEMP_VAL_REG || ts->reg != reg) {
                 printf("Inconsistency for register %s:\n", 
                        tcg_target_reg_names[reg]);
                 goto fail;
             }
         }
     }
-    for(k = 0; k < s->nb_temps; k++) {
+    for (k = 0; k < s->nb_temps; k++) {
         ts = &s->temps[k];
-        if (ts->val_type == TEMP_VAL_REG &&
-            !ts->fixed_reg &&
-            s->reg_to_temp[ts->reg] != k) {
-                printf("Inconsistency for temp %s:\n", 
-                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
+        if (ts->val_type == TEMP_VAL_REG && !ts->fixed_reg
+            && s->reg_to_temp[ts->reg] != ts) {
+            printf("Inconsistency for temp %s:\n",
+                   tcg_get_arg_str_ptr(s, buf, sizeof(buf), ts));
         fail:
-                printf("reg state:\n");
-                dump_regs(s);
-                tcg_abort();
+            printf("reg state:\n");
+            dump_regs(s);
+            tcg_abort();
         }
     }
 }
@@ -1659,15 +1659,12 @@ static void temp_allocate_frame(TCGContext *s, int temp)
 /* sync register 'reg' by saving it to the corresponding temporary */
 static inline void tcg_reg_sync(TCGContext *s, TCGReg reg)
 {
-    TCGTemp *ts;
-    int temp;
+    TCGTemp *ts = s->reg_to_temp[reg];
 
-    temp = s->reg_to_temp[reg];
-    ts = &s->temps[temp];
     assert(ts->val_type == TEMP_VAL_REG);
     if (!ts->mem_coherent && !ts->fixed_reg) {
         if (!ts->mem_allocated) {
-            temp_allocate_frame(s, temp);
+            temp_allocate_frame(s, temp_idx(s, ts));
         }
         tcg_out_st(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
     }
@@ -1677,13 +1674,12 @@ static inline void tcg_reg_sync(TCGContext *s, TCGReg reg)
 /* free register 'reg' by spilling the corresponding temporary if necessary */
 static void tcg_reg_free(TCGContext *s, TCGReg reg)
 {
-    int temp;
+    TCGTemp *ts = s->reg_to_temp[reg];
 
-    temp = s->reg_to_temp[reg];
-    if (temp != -1) {
+    if (ts != NULL) {
         tcg_reg_sync(s, reg);
-        s->temps[temp].val_type = TEMP_VAL_MEM;
-        s->reg_to_temp[reg] = -1;
+        ts->val_type = TEMP_VAL_MEM;
+        s->reg_to_temp[reg] = NULL;
     }
 }
 
@@ -1699,7 +1695,7 @@ static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
     /* first try free registers */
     for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
         reg = tcg_target_reg_alloc_order[i];
-        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
+        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == NULL)
             return reg;
     }
 
@@ -1718,12 +1714,11 @@ static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
 /* mark a temporary as dead. */
 static inline void temp_dead(TCGContext *s, int temp)
 {
-    TCGTemp *ts;
+    TCGTemp *ts = &s->temps[temp];
 
-    ts = &s->temps[temp];
     if (!ts->fixed_reg) {
         if (ts->val_type == TEMP_VAL_REG) {
-            s->reg_to_temp[ts->reg] = -1;
+            s->reg_to_temp[ts->reg] = NULL;
         }
         if (temp < s->nb_globals || ts->temp_local) {
             ts->val_type = TEMP_VAL_MEM;
@@ -1737,16 +1732,15 @@ static inline void temp_dead(TCGContext *s, int temp)
    temporary registers needs to be allocated to store a constant. */
 static inline void temp_sync(TCGContext *s, int temp, TCGRegSet allocated_regs)
 {
-    TCGTemp *ts;
+    TCGTemp *ts = &s->temps[temp];
 
-    ts = &s->temps[temp];
     if (!ts->fixed_reg) {
         switch(ts->val_type) {
         case TEMP_VAL_CONST:
             ts->reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
                                     allocated_regs);
             ts->val_type = TEMP_VAL_REG;
-            s->reg_to_temp[ts->reg] = temp;
+            s->reg_to_temp[ts->reg] = ts;
             ts->mem_coherent = 0;
             tcg_out_movi(s, ts->type, ts->reg, ts->val);
             /* fallthrough*/
@@ -1848,8 +1842,9 @@ static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
         tcg_out_movi(s, ots->type, ots->reg, val);
     } else {
         /* The movi is not explicitly generated here */
-        if (ots->val_type == TEMP_VAL_REG)
-            s->reg_to_temp[ots->reg] = -1;
+        if (ots->val_type == TEMP_VAL_REG) {
+            s->reg_to_temp[ots->reg] = NULL;
+        }
         ots->val_type = TEMP_VAL_CONST;
         ots->val = val;
     }
@@ -1892,7 +1887,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
             tcg_out_movi(s, itype, ts->reg, ts->val);
             ts->mem_coherent = 0;
         }
-        s->reg_to_temp[ts->reg] = args[1];
+        s->reg_to_temp[ts->reg] = ts;
         ts->val_type = TEMP_VAL_REG;
     }
 
@@ -1913,7 +1908,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
     } else if (ts->val_type == TEMP_VAL_CONST) {
         /* propagate constant */
         if (ots->val_type == TEMP_VAL_REG) {
-            s->reg_to_temp[ots->reg] = -1;
+            s->reg_to_temp[ots->reg] = NULL;
         }
         ots->val_type = TEMP_VAL_CONST;
         ots->val = ts->val;
@@ -1927,7 +1922,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
         if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
             /* the mov can be suppressed */
             if (ots->val_type == TEMP_VAL_REG) {
-                s->reg_to_temp[ots->reg] = -1;
+                s->reg_to_temp[ots->reg] = NULL;
             }
             ots->reg = ts->reg;
             temp_dead(s, args[1]);
@@ -1943,7 +1938,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
         }
         ots->val_type = TEMP_VAL_REG;
         ots->mem_coherent = 0;
-        s->reg_to_temp[ots->reg] = args[0];
+        s->reg_to_temp[ots->reg] = ots;
         if (NEED_SYNC_ARG(0)) {
             tcg_reg_sync(s, ots->reg);
         }
@@ -1985,7 +1980,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
             ts->val_type = TEMP_VAL_REG;
             ts->reg = reg;
             ts->mem_coherent = 1;
-            s->reg_to_temp[reg] = arg;
+            s->reg_to_temp[reg] = ts;
         } else if (ts->val_type == TEMP_VAL_CONST) {
             if (tcg_target_const_match(ts->val, ts->type, arg_ct)) {
                 /* constant is OK for instruction */
@@ -1999,7 +1994,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
                 ts->val_type = TEMP_VAL_REG;
                 ts->reg = reg;
                 ts->mem_coherent = 0;
-                s->reg_to_temp[reg] = arg;
+                s->reg_to_temp[reg] = ts;
             }
         }
         assert(ts->val_type == TEMP_VAL_REG);
@@ -2090,14 +2085,14 @@ static void tcg_reg_alloc_op(TCGContext *s,
             /* if a fixed register is used, then a move will be done afterwards */
             if (!ts->fixed_reg) {
                 if (ts->val_type == TEMP_VAL_REG) {
-                    s->reg_to_temp[ts->reg] = -1;
+                    s->reg_to_temp[ts->reg] = NULL;
                 }
                 ts->val_type = TEMP_VAL_REG;
                 ts->reg = reg;
                 /* temp value is modified, so the value kept in memory is
                    potentially not the same */
                 ts->mem_coherent = 0;
-                s->reg_to_temp[reg] = arg;
+                s->reg_to_temp[reg] = ts;
             }
         oarg_end:
             new_args[i] = reg;
@@ -2248,7 +2243,7 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
         arg = args[i];
         ts = &s->temps[arg];
         reg = tcg_target_call_oarg_regs[i];
-        assert(s->reg_to_temp[reg] == -1);
+        assert(s->reg_to_temp[reg] == NULL);
 
         if (ts->fixed_reg) {
             if (ts->reg != reg) {
@@ -2256,12 +2251,12 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
             }
         } else {
             if (ts->val_type == TEMP_VAL_REG) {
-                s->reg_to_temp[ts->reg] = -1;
+                s->reg_to_temp[ts->reg] = NULL;
             }
             ts->val_type = TEMP_VAL_REG;
             ts->reg = reg;
             ts->mem_coherent = 0;
-            s->reg_to_temp[reg] = arg;
+            s->reg_to_temp[reg] = ts;
             if (NEED_SYNC_ARG(i)) {
                 tcg_reg_sync(s, reg);
             }
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 223d9c6..83da5fb 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -572,9 +572,9 @@ struct TCGContext {
     TCGTempSet free_temps[TCG_TYPE_COUNT * 2];
     TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */
 
-    /* tells in which temporary a given register is. It does not take
-       into account fixed registers */
-    int reg_to_temp[TCG_TARGET_NB_REGS];
+    /* Tells which temporary holds a given register.
+       It does not take into account fixed registers */
+    TCGTemp *reg_to_temp[TCG_TARGET_NB_REGS];
 
     TCGOp gen_op_buf[OPC_BUF_SIZE];
     TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE];
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 07/14] tcg: Change temp_dead argument to TCGTemp
  2015-12-17 19:58 [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows Richard Henderson
                   ` (4 preceding siblings ...)
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 06/14] tcg: Change reg_to_temp to TCGTemp pointer Richard Henderson
@ 2015-12-17 20:00 ` Richard Henderson
  2015-12-31 11:24   ` Aurelien Jarno
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 08/14] tcg: Change temp_sync " Richard Henderson
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 2015-12-17 20:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien

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

diff --git a/tcg/tcg.c b/tcg/tcg.c
index d91950d..d19bb45 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1712,20 +1712,16 @@ static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
 }
 
 /* mark a temporary as dead. */
-static inline void temp_dead(TCGContext *s, int temp)
+static inline void temp_dead(TCGContext *s, TCGTemp *ts)
 {
-    TCGTemp *ts = &s->temps[temp];
-
-    if (!ts->fixed_reg) {
-        if (ts->val_type == TEMP_VAL_REG) {
-            s->reg_to_temp[ts->reg] = NULL;
-        }
-        if (temp < s->nb_globals || ts->temp_local) {
-            ts->val_type = TEMP_VAL_MEM;
-        } else {
-            ts->val_type = TEMP_VAL_DEAD;
-        }
+    if (ts->fixed_reg) {
+        return;
     }
+    if (ts->val_type == TEMP_VAL_REG) {
+        s->reg_to_temp[ts->reg] = NULL;
+    }
+    ts->val_type = (temp_idx(s, ts) < s->nb_globals || ts->temp_local
+                    ? TEMP_VAL_MEM : TEMP_VAL_DEAD);
 }
 
 /* sync a temporary to memory. 'allocated_regs' is used in case a
@@ -1760,13 +1756,15 @@ static inline void temp_sync(TCGContext *s, int temp, TCGRegSet allocated_regs)
    temporary registers needs to be allocated to store a constant. */
 static inline void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
 {
+    TCGTemp *ts = &s->temps[temp];
+
 #ifdef USE_LIVENESS_ANALYSIS
     /* The liveness analysis already ensures that globals are back
        in memory. Keep an assert for safety. */
-    assert(s->temps[temp].val_type == TEMP_VAL_MEM || s->temps[temp].fixed_reg);
+    tcg_debug_assert(ts->val_type == TEMP_VAL_MEM || ts->fixed_reg);
 #else
     temp_sync(s, temp, allocated_regs);
-    temp_dead(s, temp);
+    temp_dead(s, ts);
 #endif
 }
 
@@ -1816,7 +1814,7 @@ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
                Keep an assert for safety. */
             assert(ts->val_type == TEMP_VAL_DEAD);
 #else
-            temp_dead(s, i);
+            temp_dead(s, ts);
 #endif
         }
     }
@@ -1852,7 +1850,7 @@ static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
         temp_sync(s, args[0], s->reserved_regs);
     }
     if (IS_DEAD_ARG(0)) {
-        temp_dead(s, args[0]);
+        temp_dead(s, ots);
     }
 }
 
@@ -1902,9 +1900,9 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
         }
         tcg_out_st(s, otype, ts->reg, ots->mem_base->reg, ots->mem_offset);
         if (IS_DEAD_ARG(1)) {
-            temp_dead(s, args[1]);
+            temp_dead(s, ts);
         }
-        temp_dead(s, args[0]);
+        temp_dead(s, ots);
     } else if (ts->val_type == TEMP_VAL_CONST) {
         /* propagate constant */
         if (ots->val_type == TEMP_VAL_REG) {
@@ -1913,7 +1911,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
         ots->val_type = TEMP_VAL_CONST;
         ots->val = ts->val;
         if (IS_DEAD_ARG(1)) {
-            temp_dead(s, args[1]);
+            temp_dead(s, ts);
         }
     } else {
         /* The code in the first if block should have moved the
@@ -1925,7 +1923,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
                 s->reg_to_temp[ots->reg] = NULL;
             }
             ots->reg = ts->reg;
-            temp_dead(s, args[1]);
+            temp_dead(s, ts);
         } else {
             if (ots->val_type != TEMP_VAL_REG) {
                 /* When allocating a new register, make sure to not spill the
@@ -2042,7 +2040,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, args[i]);
+            temp_dead(s, &s->temps[args[i]]);
         }
     }
 
@@ -2113,7 +2111,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
             tcg_reg_sync(s, reg);
         }
         if (IS_DEAD_ARG(i)) {
-            temp_dead(s, args[i]);
+            temp_dead(s, ts);
         }
     }
 }
@@ -2215,7 +2213,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, args[i]);
+            temp_dead(s, &s->temps[args[i]]);
         }
     }
     
@@ -2261,7 +2259,7 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
                 tcg_reg_sync(s, reg);
             }
             if (IS_DEAD_ARG(i)) {
-                temp_dead(s, args[i]);
+                temp_dead(s, ts);
             }
         }
     }
@@ -2391,7 +2389,7 @@ int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf)
             }
             break;
         case INDEX_op_discard:
-            temp_dead(s, args[0]);
+            temp_dead(s, &s->temps[args[0]]);
             break;
         case INDEX_op_set_label:
             tcg_reg_alloc_bb_end(s, s->reserved_regs);
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 08/14] tcg: Change temp_sync argument to TCGTemp
  2015-12-17 19:58 [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows Richard Henderson
                   ` (5 preceding siblings ...)
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 07/14] tcg: Change temp_dead argument to TCGTemp Richard Henderson
@ 2015-12-17 20:00 ` Richard Henderson
  2015-12-31 11:24   ` Aurelien Jarno
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 09/14] tcg: Change temp_save " Richard Henderson
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 2015-12-17 20:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien

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

diff --git a/tcg/tcg.c b/tcg/tcg.c
index d19bb45..8edf582 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1726,29 +1726,28 @@ static inline void temp_dead(TCGContext *s, TCGTemp *ts)
 
 /* sync a temporary to memory. 'allocated_regs' is used in case a
    temporary registers needs to be allocated to store a constant. */
-static inline void temp_sync(TCGContext *s, int temp, TCGRegSet allocated_regs)
+static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs)
 {
-    TCGTemp *ts = &s->temps[temp];
-
-    if (!ts->fixed_reg) {
-        switch(ts->val_type) {
-        case TEMP_VAL_CONST:
-            ts->reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
-                                    allocated_regs);
-            ts->val_type = TEMP_VAL_REG;
-            s->reg_to_temp[ts->reg] = ts;
-            ts->mem_coherent = 0;
-            tcg_out_movi(s, ts->type, ts->reg, ts->val);
-            /* fallthrough*/
-        case TEMP_VAL_REG:
-            tcg_reg_sync(s, ts->reg);
-            break;
-        case TEMP_VAL_DEAD:
-        case TEMP_VAL_MEM:
-            break;
-        default:
-            tcg_abort();
-        }
+    if (ts->fixed_reg) {
+        return;
+    }
+    switch (ts->val_type) {
+    case TEMP_VAL_CONST:
+        ts->reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
+                                allocated_regs);
+        ts->val_type = TEMP_VAL_REG;
+        s->reg_to_temp[ts->reg] = ts;
+        ts->mem_coherent = 0;
+        tcg_out_movi(s, ts->type, ts->reg, ts->val);
+        /* fallthrough*/
+    case TEMP_VAL_REG:
+        tcg_reg_sync(s, ts->reg);
+        break;
+    case TEMP_VAL_DEAD:
+    case TEMP_VAL_MEM:
+        break;
+    default:
+        tcg_abort();
     }
 }
 
@@ -1763,7 +1762,7 @@ static inline void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
        in memory. Keep an assert for safety. */
     tcg_debug_assert(ts->val_type == TEMP_VAL_MEM || ts->fixed_reg);
 #else
-    temp_sync(s, temp, allocated_regs);
+    temp_sync(s, ts, allocated_regs);
     temp_dead(s, ts);
 #endif
 }
@@ -1788,11 +1787,13 @@ static void sync_globals(TCGContext *s, TCGRegSet allocated_regs)
     int i;
 
     for (i = 0; i < s->nb_globals; i++) {
+        TCGTemp *ts = &s->temps[i];
 #ifdef USE_LIVENESS_ANALYSIS
-        assert(s->temps[i].val_type != TEMP_VAL_REG || s->temps[i].fixed_reg ||
-               s->temps[i].mem_coherent);
+        tcg_debug_assert(ts->val_type != TEMP_VAL_REG
+                         || ts->fixed_reg
+                         || ts->mem_coherent);
 #else
-        temp_sync(s, i, allocated_regs);
+        temp_sync(s, ts, allocated_regs);
 #endif
     }
 }
@@ -1847,7 +1848,7 @@ static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
         ots->val = val;
     }
     if (NEED_SYNC_ARG(0)) {
-        temp_sync(s, args[0], s->reserved_regs);
+        temp_sync(s, ots, s->reserved_regs);
     }
     if (IS_DEAD_ARG(0)) {
         temp_dead(s, ots);
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 09/14] tcg: Change temp_save argument to TCGTemp
  2015-12-17 19:58 [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows Richard Henderson
                   ` (6 preceding siblings ...)
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 08/14] tcg: Change temp_sync " Richard Henderson
@ 2015-12-17 20:00 ` Richard Henderson
  2015-12-31 11:24   ` Aurelien Jarno
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 10/14] tcg: Introduce temp_load Richard Henderson
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 2015-12-17 20:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien

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

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 8edf582..6f40bf3 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1753,10 +1753,9 @@ static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs)
 
 /* save a temporary to memory. 'allocated_regs' is used in case a
    temporary registers needs to be allocated to store a constant. */
-static inline void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
+static inline void temp_save(TCGContext *s, TCGTemp *ts,
+                             TCGRegSet allocated_regs)
 {
-    TCGTemp *ts = &s->temps[temp];
-
 #ifdef USE_LIVENESS_ANALYSIS
     /* The liveness analysis already ensures that globals are back
        in memory. Keep an assert for safety. */
@@ -1774,8 +1773,8 @@ static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
 {
     int i;
 
-    for(i = 0; i < s->nb_globals; i++) {
-        temp_save(s, i, allocated_regs);
+    for (i = 0; i < s->nb_globals; i++) {
+        temp_save(s, &s->temps[i], allocated_regs);
     }
 }
 
@@ -1802,13 +1801,12 @@ static void sync_globals(TCGContext *s, TCGRegSet allocated_regs)
    all globals are stored at their canonical location. */
 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
 {
-    TCGTemp *ts;
     int i;
 
-    for(i = s->nb_globals; i < s->nb_temps; i++) {
-        ts = &s->temps[i];
+    for (i = s->nb_globals; i < s->nb_temps; i++) {
+        TCGTemp *ts = &s->temps[i];
         if (ts->temp_local) {
-            temp_save(s, i, allocated_regs);
+            temp_save(s, ts, allocated_regs);
         } else {
 #ifdef USE_LIVENESS_ANALYSIS
             /* The liveness analysis already ensures that temps are dead.
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 10/14] tcg: Introduce temp_load
  2015-12-17 19:58 [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows Richard Henderson
                   ` (7 preceding siblings ...)
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 09/14] tcg: Change temp_save " Richard Henderson
@ 2015-12-17 20:00 ` Richard Henderson
  2015-12-31 11:33   ` Aurelien Jarno
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 11/14] tcg: Implement indirect memory registers Richard Henderson
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 2015-12-17 20:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien

Unify all of the places that realize a temporary into a register.

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

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 6f40bf3..c51e0ec 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1711,6 +1711,35 @@ static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
     tcg_abort();
 }
 
+/* Make sure the temporary is in a register.  If needed, allocate the register
+   from DESIRED while avoiding ALLOCATED.  */
+static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs,
+                      TCGRegSet allocated_regs)
+{
+    TCGReg reg;
+
+    switch (ts->val_type) {
+    case TEMP_VAL_REG:
+        return;
+    case TEMP_VAL_CONST:
+        reg = tcg_reg_alloc(s, desired_regs, allocated_regs);
+        tcg_out_movi(s, ts->type, reg, ts->val);
+        ts->mem_coherent = 0;
+        break;
+    case TEMP_VAL_MEM:
+        reg = tcg_reg_alloc(s, desired_regs, allocated_regs);
+        tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
+        ts->mem_coherent = 1;
+        break;
+    case TEMP_VAL_DEAD:
+    default:
+        tcg_abort();
+    }
+    ts->reg = reg;
+    ts->val_type = TEMP_VAL_REG;
+    s->reg_to_temp[reg] = ts;
+}
+
 /* mark a temporary as dead. */
 static inline void temp_dead(TCGContext *s, TCGTemp *ts)
 {
@@ -1733,13 +1762,8 @@ static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs)
     }
     switch (ts->val_type) {
     case TEMP_VAL_CONST:
-        ts->reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
-                                allocated_regs);
-        ts->val_type = TEMP_VAL_REG;
-        s->reg_to_temp[ts->reg] = ts;
-        ts->mem_coherent = 0;
-        tcg_out_movi(s, ts->type, ts->reg, ts->val);
-        /* fallthrough*/
+        temp_load(s, ts, tcg_target_available_regs[ts->type], allocated_regs);
+        /* fallthrough */
     case TEMP_VAL_REG:
         tcg_reg_sync(s, ts->reg);
         break;
@@ -1875,17 +1899,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
        we don't have to reload SOURCE the next time it is used. */
     if (((NEED_SYNC_ARG(0) || ots->fixed_reg) && ts->val_type != TEMP_VAL_REG)
         || ts->val_type == TEMP_VAL_MEM) {
-        ts->reg = tcg_reg_alloc(s, tcg_target_available_regs[itype],
-                                allocated_regs);
-        if (ts->val_type == TEMP_VAL_MEM) {
-            tcg_out_ld(s, itype, ts->reg, ts->mem_base->reg, ts->mem_offset);
-            ts->mem_coherent = 1;
-        } else if (ts->val_type == TEMP_VAL_CONST) {
-            tcg_out_movi(s, itype, ts->reg, ts->val);
-            ts->mem_coherent = 0;
-        }
-        s->reg_to_temp[ts->reg] = ts;
-        ts->val_type = TEMP_VAL_REG;
+        temp_load(s, ts, tcg_target_available_regs[itype], allocated_regs);
     }
 
     if (IS_DEAD_ARG(0) && !ots->fixed_reg) {
@@ -1971,30 +1985,17 @@ static void tcg_reg_alloc_op(TCGContext *s,
         arg = args[i];
         arg_ct = &def->args_ct[i];
         ts = &s->temps[arg];
-        if (ts->val_type == TEMP_VAL_MEM) {
-            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
-            tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
-            ts->val_type = TEMP_VAL_REG;
-            ts->reg = reg;
-            ts->mem_coherent = 1;
-            s->reg_to_temp[reg] = ts;
-        } else if (ts->val_type == TEMP_VAL_CONST) {
-            if (tcg_target_const_match(ts->val, ts->type, arg_ct)) {
-                /* constant is OK for instruction */
-                const_args[i] = 1;
-                new_args[i] = ts->val;
-                goto iarg_end;
-            } else {
-                /* need to move to a register */
-                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
-                tcg_out_movi(s, ts->type, reg, ts->val);
-                ts->val_type = TEMP_VAL_REG;
-                ts->reg = reg;
-                ts->mem_coherent = 0;
-                s->reg_to_temp[reg] = ts;
-            }
+
+        if (ts->val_type == TEMP_VAL_CONST
+            && tcg_target_const_match(ts->val, ts->type, arg_ct)) {
+            /* constant is OK for instruction */
+            const_args[i] = 1;
+            new_args[i] = ts->val;
+            goto iarg_end;
         }
-        assert(ts->val_type == TEMP_VAL_REG);
+
+        temp_load(s, ts, arg_ct->u.regs, allocated_regs);
+
         if (arg_ct->ct & TCG_CT_IALIAS) {
             if (ts->fixed_reg) {
                 /* if fixed register, we must allocate a new register
@@ -2162,23 +2163,9 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
 #endif
         if (arg != TCG_CALL_DUMMY_ARG) {
             ts = &s->temps[arg];
-            if (ts->val_type == TEMP_VAL_REG) {
-                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
-            } else if (ts->val_type == TEMP_VAL_MEM) {
-                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
-                                    s->reserved_regs);
-                /* XXX: not correct if reading values from the stack */
-                tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
-                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
-            } else if (ts->val_type == TEMP_VAL_CONST) {
-                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
-                                    s->reserved_regs);
-                /* XXX: sign extend may be needed on some targets */
-                tcg_out_movi(s, ts->type, reg, ts->val);
-                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
-            } else {
-                tcg_abort();
-            }
+            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);
         }
 #ifndef TCG_TARGET_STACK_GROWSUP
         stack_offset += sizeof(tcg_target_long);
@@ -2193,18 +2180,19 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
             ts = &s->temps[arg];
             reg = tcg_target_call_iarg_regs[i];
             tcg_reg_free(s, reg);
+
             if (ts->val_type == TEMP_VAL_REG) {
                 if (ts->reg != reg) {
                     tcg_out_mov(s, ts->type, reg, ts->reg);
                 }
-            } else if (ts->val_type == TEMP_VAL_MEM) {
-                tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
-            } else if (ts->val_type == TEMP_VAL_CONST) {
-                /* XXX: sign extend ? */
-                tcg_out_movi(s, ts->type, reg, ts->val);
             } else {
-                tcg_abort();
+                TCGRegSet arg_set;
+
+                tcg_regset_clear(arg_set);
+                tcg_regset_set_reg(arg_set, reg);
+                temp_load(s, ts, arg_set, allocated_regs);
             }
+
             tcg_regset_set_reg(allocated_regs, reg);
         }
     }
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 11/14] tcg: Implement indirect memory registers
  2015-12-17 19:58 [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows Richard Henderson
                   ` (8 preceding siblings ...)
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 10/14] tcg: Introduce temp_load Richard Henderson
@ 2015-12-17 20:00 ` Richard Henderson
  2015-12-31 11:54   ` Aurelien Jarno
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 12/14] tcg: Allocate indirect_base temporaries in a different order Richard Henderson
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 26+ messages in thread
From: Richard Henderson @ 2015-12-17 20:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien

That is, global_mem registers whose base is another global_mem
register, rather than a fixed register.

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

diff --git a/tcg/tcg.c b/tcg/tcg.c
index c51e0ec..7150a3f 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -509,17 +509,23 @@ int tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
     TCGContext *s = &tcg_ctx;
     TCGTemp *base_ts = &s->temps[GET_TCGV_PTR(base)];
     TCGTemp *ts = tcg_global_alloc(s);
-    int bigendian = 0;
+    int indirect_reg = 0, bigendian = 0;
 #ifdef HOST_WORDS_BIGENDIAN
     bigendian = 1;
 #endif
 
+    if (!base_ts->fixed_reg) {
+        indirect_reg = 1;
+        base_ts->indirect_base = 1;
+    }
+
     if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
         TCGTemp *ts2 = tcg_global_alloc(s);
         char buf[64];
 
         ts->base_type = TCG_TYPE_I64;
         ts->type = TCG_TYPE_I32;
+        ts->indirect_reg = indirect_reg;
         ts->mem_allocated = 1;
         ts->mem_base = base_ts;
         ts->mem_offset = offset + bigendian * 4;
@@ -530,6 +536,7 @@ int tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
         tcg_debug_assert(ts2 == ts + 1);
         ts2->base_type = TCG_TYPE_I64;
         ts2->type = TCG_TYPE_I32;
+        ts2->indirect_reg = indirect_reg;
         ts2->mem_allocated = 1;
         ts2->mem_base = base_ts;
         ts2->mem_offset = offset + (1 - bigendian) * 4;
@@ -539,6 +546,7 @@ int tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
     } else {
         ts->base_type = type;
         ts->type = type;
+        ts->indirect_reg = indirect_reg;
         ts->mem_allocated = 1;
         ts->mem_base = base_ts;
         ts->mem_offset = offset;
@@ -1656,8 +1664,10 @@ static void temp_allocate_frame(TCGContext *s, int temp)
     s->current_frame_offset += sizeof(tcg_target_long);
 }
 
+static void temp_load(TCGContext *, TCGTemp *, TCGRegSet, TCGRegSet);
+
 /* sync register 'reg' by saving it to the corresponding temporary */
-static inline void tcg_reg_sync(TCGContext *s, TCGReg reg)
+static void tcg_reg_sync(TCGContext *s, TCGReg reg, TCGRegSet allocated_regs)
 {
     TCGTemp *ts = s->reg_to_temp[reg];
 
@@ -1665,6 +1675,11 @@ static inline void tcg_reg_sync(TCGContext *s, TCGReg reg)
     if (!ts->mem_coherent && !ts->fixed_reg) {
         if (!ts->mem_allocated) {
             temp_allocate_frame(s, temp_idx(s, ts));
+        } else if (ts->indirect_reg) {
+            tcg_regset_set_reg(allocated_regs, ts->reg);
+            temp_load(s, ts->mem_base,
+                      tcg_target_available_regs[TCG_TYPE_PTR],
+                      allocated_regs);
         }
         tcg_out_st(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
     }
@@ -1672,25 +1687,26 @@ static inline void tcg_reg_sync(TCGContext *s, TCGReg reg)
 }
 
 /* free register 'reg' by spilling the corresponding temporary if necessary */
-static void tcg_reg_free(TCGContext *s, TCGReg reg)
+static void tcg_reg_free(TCGContext *s, TCGReg reg, TCGRegSet allocated_regs)
 {
     TCGTemp *ts = s->reg_to_temp[reg];
 
     if (ts != NULL) {
-        tcg_reg_sync(s, reg);
+        tcg_reg_sync(s, reg, allocated_regs);
         ts->val_type = TEMP_VAL_MEM;
         s->reg_to_temp[reg] = NULL;
     }
 }
 
 /* Allocate a register belonging to reg1 & ~reg2 */
-static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
+static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet desired_regs,
+                            TCGRegSet allocated_regs)
 {
     int i;
     TCGReg reg;
     TCGRegSet reg_ct;
 
-    tcg_regset_andnot(reg_ct, reg1, reg2);
+    tcg_regset_andnot(reg_ct, desired_regs, allocated_regs);
 
     /* first try free registers */
     for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
@@ -1703,7 +1719,7 @@ static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
     for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
         reg = tcg_target_reg_alloc_order[i];
         if (tcg_regset_test_reg(reg_ct, reg)) {
-            tcg_reg_free(s, reg);
+            tcg_reg_free(s, reg, allocated_regs);
             return reg;
         }
     }
@@ -1728,6 +1744,12 @@ static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs,
         break;
     case TEMP_VAL_MEM:
         reg = tcg_reg_alloc(s, desired_regs, allocated_regs);
+        if (ts->indirect_reg) {
+            tcg_regset_set_reg(allocated_regs, reg);
+            temp_load(s, ts->mem_base,
+                      tcg_target_available_regs[TCG_TYPE_PTR],
+                      allocated_regs);
+        }
         tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
         ts->mem_coherent = 1;
         break;
@@ -1765,7 +1787,7 @@ static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs)
         temp_load(s, ts, tcg_target_available_regs[ts->type], allocated_regs);
         /* fallthrough */
     case TEMP_VAL_REG:
-        tcg_reg_sync(s, ts->reg);
+        tcg_reg_sync(s, ts->reg, allocated_regs);
         break;
     case TEMP_VAL_DEAD:
     case TEMP_VAL_MEM:
@@ -1781,13 +1803,16 @@ static inline void temp_save(TCGContext *s, TCGTemp *ts,
                              TCGRegSet allocated_regs)
 {
 #ifdef USE_LIVENESS_ANALYSIS
-    /* The liveness analysis already ensures that globals are back
-       in memory. Keep an assert for safety. */
-    tcg_debug_assert(ts->val_type == TEMP_VAL_MEM || ts->fixed_reg);
-#else
+    /* ??? Liveness does not yet incorporate indirect bases.  */
+    if (!ts->indirect_base) {
+        /* The liveness analysis already ensures that globals are back
+           in memory. Keep an assert for safety. */
+        tcg_debug_assert(ts->val_type == TEMP_VAL_MEM || ts->fixed_reg);
+        return;
+    }
+#endif
     temp_sync(s, ts, allocated_regs);
     temp_dead(s, ts);
-#endif
 }
 
 /* save globals to their canonical location and assume they can be
@@ -1812,12 +1837,15 @@ static void sync_globals(TCGContext *s, TCGRegSet allocated_regs)
     for (i = 0; i < s->nb_globals; i++) {
         TCGTemp *ts = &s->temps[i];
 #ifdef USE_LIVENESS_ANALYSIS
-        tcg_debug_assert(ts->val_type != TEMP_VAL_REG
-                         || ts->fixed_reg
-                         || ts->mem_coherent);
-#else
-        temp_sync(s, ts, allocated_regs);
+        /* ??? Liveness does not yet incorporate indirect bases.  */
+        if (!ts->indirect_base) {
+            tcg_debug_assert(ts->val_type != TEMP_VAL_REG
+                             || ts->fixed_reg
+                             || ts->mem_coherent);
+            continue;
+        }
 #endif
+        temp_sync(s, ts, allocated_regs);
     }
 }
 
@@ -1833,12 +1861,15 @@ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
             temp_save(s, ts, allocated_regs);
         } else {
 #ifdef USE_LIVENESS_ANALYSIS
-            /* The liveness analysis already ensures that temps are dead.
-               Keep an assert for safety. */
-            assert(ts->val_type == TEMP_VAL_DEAD);
-#else
-            temp_dead(s, ts);
+            /* ??? Liveness does not yet incorporate indirect bases.  */
+            if (!ts->indirect_base) {
+                /* The liveness analysis already ensures that temps are dead.
+                   Keep an assert for safety. */
+                assert(ts->val_type == TEMP_VAL_DEAD);
+                continue;
+            }
 #endif
+            temp_dead(s, ts);
         }
     }
 
@@ -1911,6 +1942,12 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
         if (!ots->mem_allocated) {
             temp_allocate_frame(s, args[0]);
         }
+        if (ots->indirect_reg) {
+            tcg_regset_set_reg(allocated_regs, ts->reg);
+            temp_load(s, ots->mem_base,
+                      tcg_target_available_regs[TCG_TYPE_PTR],
+                      allocated_regs);
+        }
         tcg_out_st(s, otype, ts->reg, ots->mem_base->reg, ots->mem_offset);
         if (IS_DEAD_ARG(1)) {
             temp_dead(s, ts);
@@ -1951,7 +1988,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
         ots->mem_coherent = 0;
         s->reg_to_temp[ots->reg] = ots;
         if (NEED_SYNC_ARG(0)) {
-            tcg_reg_sync(s, ots->reg);
+            tcg_reg_sync(s, ots->reg, allocated_regs);
         }
     }
 }
@@ -2051,7 +2088,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
             /* XXX: permit generic clobber register list ? */ 
             for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
                 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
-                    tcg_reg_free(s, reg);
+                    tcg_reg_free(s, reg, allocated_regs);
                 }
             }
         }
@@ -2108,7 +2145,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
             tcg_out_mov(s, ts->type, ts->reg, reg);
         }
         if (NEED_SYNC_ARG(i)) {
-            tcg_reg_sync(s, reg);
+            tcg_reg_sync(s, reg, allocated_regs);
         }
         if (IS_DEAD_ARG(i)) {
             temp_dead(s, ts);
@@ -2179,7 +2216,7 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
         if (arg != TCG_CALL_DUMMY_ARG) {
             ts = &s->temps[arg];
             reg = tcg_target_call_iarg_regs[i];
-            tcg_reg_free(s, reg);
+            tcg_reg_free(s, reg, allocated_regs);
 
             if (ts->val_type == TEMP_VAL_REG) {
                 if (ts->reg != reg) {
@@ -2207,7 +2244,7 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
     /* clobber call registers */
     for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
         if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
-            tcg_reg_free(s, reg);
+            tcg_reg_free(s, reg, allocated_regs);
         }
     }
 
@@ -2243,7 +2280,7 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
             ts->mem_coherent = 0;
             s->reg_to_temp[reg] = ts;
             if (NEED_SYNC_ARG(i)) {
-                tcg_reg_sync(s, reg);
+                tcg_reg_sync(s, reg, allocated_regs);
             }
             if (IS_DEAD_ARG(i)) {
                 temp_dead(s, ts);
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 83da5fb..d181694 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -453,6 +453,8 @@ typedef struct TCGTemp {
     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
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 12/14] tcg: Allocate indirect_base temporaries in a different order
  2015-12-17 19:58 [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows Richard Henderson
                   ` (9 preceding siblings ...)
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 11/14] tcg: Implement indirect memory registers Richard Henderson
@ 2015-12-17 20:00 ` Richard Henderson
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 13/14] target-sparc: Tidy global register initialization Richard Henderson
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 14/14] target-sparc: Use global registers for the register window Richard Henderson
  12 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2015-12-17 20:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien

Since we've not got liveness analysis for indirect bases,
placing them at the end of the call-saved registers makes
it more likely that it'll stay live.

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

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 7150a3f..1b17827 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -317,6 +317,8 @@ static const TCGHelperInfo all_helpers[] = {
 #include "exec/helper-tcg.h"
 };
 
+static int indirect_reg_alloc_order[ARRAY_SIZE(tcg_target_reg_alloc_order)];
+
 void tcg_context_init(TCGContext *s)
 {
     int op, total_args, n, i;
@@ -359,6 +361,21 @@ void tcg_context_init(TCGContext *s)
     }
 
     tcg_target_init(s);
+
+    /* Reverse the order of the saved registers, assuming they're all at
+       the start of tcg_target_reg_alloc_order.  */
+    for (n = 0; n < ARRAY_SIZE(tcg_target_reg_alloc_order); ++n) {
+        int r = tcg_target_reg_alloc_order[n];
+        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, r)) {
+            break;
+        }
+    }
+    for (i = 0; i < n; ++i) {
+        indirect_reg_alloc_order[i] = tcg_target_reg_alloc_order[n - 1 - i];
+    }
+    for (; i < ARRAY_SIZE(tcg_target_reg_alloc_order); ++i) {
+        indirect_reg_alloc_order[i] = tcg_target_reg_alloc_order[i];
+    }
 }
 
 void tcg_prologue_init(TCGContext *s)
@@ -1700,24 +1717,26 @@ static void tcg_reg_free(TCGContext *s, TCGReg reg, TCGRegSet allocated_regs)
 
 /* Allocate a register belonging to reg1 & ~reg2 */
 static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet desired_regs,
-                            TCGRegSet allocated_regs)
+                            TCGRegSet allocated_regs, bool rev)
 {
-    int i;
+    int i, n = ARRAY_SIZE(tcg_target_reg_alloc_order);
+    const int *order;
     TCGReg reg;
     TCGRegSet reg_ct;
 
     tcg_regset_andnot(reg_ct, desired_regs, allocated_regs);
+    order = rev ? indirect_reg_alloc_order : tcg_target_reg_alloc_order;
 
     /* first try free registers */
-    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
-        reg = tcg_target_reg_alloc_order[i];
+    for(i = 0; i < n; i++) {
+        reg = order[i];
         if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == NULL)
             return reg;
     }
 
     /* XXX: do better spill choice */
-    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
-        reg = tcg_target_reg_alloc_order[i];
+    for(i = 0; i < n; i++) {
+        reg = order[i];
         if (tcg_regset_test_reg(reg_ct, reg)) {
             tcg_reg_free(s, reg, allocated_regs);
             return reg;
@@ -1738,12 +1757,12 @@ static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs,
     case TEMP_VAL_REG:
         return;
     case TEMP_VAL_CONST:
-        reg = tcg_reg_alloc(s, desired_regs, allocated_regs);
+        reg = tcg_reg_alloc(s, desired_regs, allocated_regs, ts->indirect_base);
         tcg_out_movi(s, ts->type, reg, ts->val);
         ts->mem_coherent = 0;
         break;
     case TEMP_VAL_MEM:
-        reg = tcg_reg_alloc(s, desired_regs, allocated_regs);
+        reg = tcg_reg_alloc(s, desired_regs, allocated_regs, ts->indirect_base);
         if (ts->indirect_reg) {
             tcg_regset_set_reg(allocated_regs, reg);
             temp_load(s, ts->mem_base,
@@ -1980,7 +1999,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
                    input one. */
                 tcg_regset_set_reg(allocated_regs, ts->reg);
                 ots->reg = tcg_reg_alloc(s, tcg_target_available_regs[otype],
-                                         allocated_regs);
+                                         allocated_regs, ots->indirect_base);
             }
             tcg_out_mov(s, otype, ots->reg, ts->reg);
         }
@@ -2065,7 +2084,8 @@ static void tcg_reg_alloc_op(TCGContext *s,
         allocate_in_reg:
             /* allocate a new register matching the constraint 
                and move the temporary register into it */
-            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
+            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs,
+                                ts->indirect_base);
             tcg_out_mov(s, ts->type, reg, ts->reg);
         }
         new_args[i] = reg;
@@ -2114,7 +2134,8 @@ static void tcg_reg_alloc_op(TCGContext *s,
                     tcg_regset_test_reg(arg_ct->u.regs, reg)) {
                     goto oarg_end;
                 }
-                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
+                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs,
+                                    ts->indirect_base);
             }
             tcg_regset_set_reg(allocated_regs, reg);
             /* if a fixed register is used, then a move will be done afterwards */
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 13/14] target-sparc: Tidy global register initialization
  2015-12-17 19:58 [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows Richard Henderson
                   ` (10 preceding siblings ...)
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 12/14] tcg: Allocate indirect_base temporaries in a different order Richard Henderson
@ 2015-12-17 20:00 ` Richard Henderson
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 14/14] target-sparc: Use global registers for the register window Richard Henderson
  12 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2015-12-17 20:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien

Create tables for the various global registers that need allocation.
Remove one level of indirection from  gregnames and fregnames.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/translate.c | 157 +++++++++++++++++++++--------------------------
 1 file changed, 70 insertions(+), 87 deletions(-)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 61452a1..c13a9d3 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5320,106 +5320,89 @@ void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
 
 void gen_intermediate_code_init(CPUSPARCState *env)
 {
-    unsigned int i;
     static int inited;
-    static const char * const gregnames[8] = {
-        NULL, // g0 not used
-        "g1",
-        "g2",
-        "g3",
-        "g4",
-        "g5",
-        "g6",
-        "g7",
+    static const char gregnames[8][4] = {
+        "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
     };
-    static const char * const fregnames[32] = {
+    static const char fregnames[32][4] = {
         "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
         "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
         "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
         "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
     };
 
-    /* init various static tables */
-    if (!inited) {
-        inited = 1;
-
-        cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
-        cpu_regwptr = tcg_global_mem_new_ptr(cpu_env,
-                                             offsetof(CPUSPARCState, regwptr),
-                                             "regwptr");
+    static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = {
 #ifdef TARGET_SPARC64
-        cpu_xcc = tcg_global_mem_new_i32(cpu_env, offsetof(CPUSPARCState, xcc),
-                                         "xcc");
-        cpu_asi = tcg_global_mem_new_i32(cpu_env, offsetof(CPUSPARCState, asi),
-                                         "asi");
-        cpu_fprs = tcg_global_mem_new_i32(cpu_env,
-                                          offsetof(CPUSPARCState, fprs),
-                                          "fprs");
-        cpu_gsr = tcg_global_mem_new(cpu_env, offsetof(CPUSPARCState, gsr),
-                                     "gsr");
-        cpu_tick_cmpr = tcg_global_mem_new(cpu_env,
-                                           offsetof(CPUSPARCState, tick_cmpr),
-                                           "tick_cmpr");
-        cpu_stick_cmpr = tcg_global_mem_new(cpu_env,
-                                            offsetof(CPUSPARCState, stick_cmpr),
-                                            "stick_cmpr");
-        cpu_hstick_cmpr = tcg_global_mem_new(cpu_env,
-                                             offsetof(CPUSPARCState, hstick_cmpr),
-                                             "hstick_cmpr");
-        cpu_hintp = tcg_global_mem_new(cpu_env, offsetof(CPUSPARCState, hintp),
-                                       "hintp");
-        cpu_htba = tcg_global_mem_new(cpu_env, offsetof(CPUSPARCState, htba),
-                                      "htba");
-        cpu_hver = tcg_global_mem_new(cpu_env, offsetof(CPUSPARCState, hver),
-                                      "hver");
-        cpu_ssr = tcg_global_mem_new(cpu_env,
-                                     offsetof(CPUSPARCState, ssr), "ssr");
-        cpu_ver = tcg_global_mem_new(cpu_env,
-                                     offsetof(CPUSPARCState, version), "ver");
-        cpu_softint = tcg_global_mem_new_i32(cpu_env,
-                                             offsetof(CPUSPARCState, softint),
-                                             "softint");
+        { &cpu_xcc, offsetof(CPUSPARCState, xcc), "xcc" },
+        { &cpu_asi, offsetof(CPUSPARCState, asi), "asi" },
+        { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" },
+        { &cpu_softint, offsetof(CPUSPARCState, softint), "softint" },
 #else
-        cpu_wim = tcg_global_mem_new(cpu_env, offsetof(CPUSPARCState, wim),
-                                     "wim");
+        { &cpu_wim, offsetof(CPUSPARCState, wim), "wim" },
+#endif
+        { &cpu_cc_op, offsetof(CPUSPARCState, cc_op), "cc_op" },
+        { &cpu_psr, offsetof(CPUSPARCState, psr), "psr" },
+    };
+
+    static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
+#ifdef TARGET_SPARC64
+        { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" },
+        { &cpu_tick_cmpr, offsetof(CPUSPARCState, tick_cmpr), "tick_cmpr" },
+        { &cpu_stick_cmpr, offsetof(CPUSPARCState, stick_cmpr), "stick_cmpr" },
+        { &cpu_hstick_cmpr, offsetof(CPUSPARCState, hstick_cmpr),
+          "hstick_cmpr" },
+        { &cpu_hintp, offsetof(CPUSPARCState, hintp), "hintp" },
+        { &cpu_htba, offsetof(CPUSPARCState, htba), "htba" },
+        { &cpu_hver, offsetof(CPUSPARCState, hver), "hver" },
+        { &cpu_ssr, offsetof(CPUSPARCState, ssr), "ssr" },
+        { &cpu_ver, offsetof(CPUSPARCState, version), "ver" },
 #endif
-        cpu_cond = tcg_global_mem_new(cpu_env, offsetof(CPUSPARCState, cond),
-                                      "cond");
-        cpu_cc_src = tcg_global_mem_new(cpu_env,
-                                        offsetof(CPUSPARCState, cc_src),
-                                        "cc_src");
-        cpu_cc_src2 = tcg_global_mem_new(cpu_env,
-                                         offsetof(CPUSPARCState, cc_src2),
-                                         "cc_src2");
-        cpu_cc_dst = tcg_global_mem_new(cpu_env,
-                                        offsetof(CPUSPARCState, cc_dst),
-                                        "cc_dst");
-        cpu_cc_op = tcg_global_mem_new_i32(cpu_env,
-                                           offsetof(CPUSPARCState, cc_op),
-                                           "cc_op");
-        cpu_psr = tcg_global_mem_new_i32(cpu_env, offsetof(CPUSPARCState, psr),
-                                         "psr");
-        cpu_fsr = tcg_global_mem_new(cpu_env, offsetof(CPUSPARCState, fsr),
-                                     "fsr");
-        cpu_pc = tcg_global_mem_new(cpu_env, offsetof(CPUSPARCState, pc),
-                                    "pc");
-        cpu_npc = tcg_global_mem_new(cpu_env, offsetof(CPUSPARCState, npc),
-                                     "npc");
-        cpu_y = tcg_global_mem_new(cpu_env, offsetof(CPUSPARCState, y), "y");
+        { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" },
+        { &cpu_cc_src, offsetof(CPUSPARCState, cc_src), "cc_src" },
+        { &cpu_cc_src2, offsetof(CPUSPARCState, cc_src2), "cc_src2" },
+        { &cpu_cc_dst, offsetof(CPUSPARCState, cc_dst), "cc_dst" },
+        { &cpu_fsr, offsetof(CPUSPARCState, fsr), "fsr" },
+        { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" },
+        { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" },
+        { &cpu_y, offsetof(CPUSPARCState, y), "y" },
 #ifndef CONFIG_USER_ONLY
-        cpu_tbr = tcg_global_mem_new(cpu_env, offsetof(CPUSPARCState, tbr),
-                                     "tbr");
+        { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" },
 #endif
-        for (i = 1; i < 8; i++) {
-            cpu_gregs[i] = tcg_global_mem_new(cpu_env,
-                                              offsetof(CPUSPARCState, gregs[i]),
-                                              gregnames[i]);
-        }
-        for (i = 0; i < TARGET_DPREGS; i++) {
-            cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env,
-                                                offsetof(CPUSPARCState, fpr[i]),
-                                                fregnames[i]);
-        }
+    };
+
+    unsigned int i;
+
+    /* init various static tables */
+    if (inited) {
+        return;
+    }
+    inited = 1;
+
+    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+
+    cpu_regwptr = tcg_global_mem_new_ptr(cpu_env,
+                                         offsetof(CPUSPARCState, regwptr),
+                                         "regwptr");
+
+    for (i = 0; i < ARRAY_SIZE(r32); ++i) {
+        *r32[i].ptr = tcg_global_mem_new_i32(cpu_env, r32[i].off, r32[i].name);
+    }
+
+    for (i = 0; i < ARRAY_SIZE(rtl); ++i) {
+        *rtl[i].ptr = tcg_global_mem_new(cpu_env, rtl[i].off, rtl[i].name);
+    }
+
+    TCGV_UNUSED(cpu_gregs[0]);
+    for (i = 1; i < 8; ++i) {
+        cpu_gregs[i] = tcg_global_mem_new(cpu_env,
+                                          offsetof(CPUSPARCState, gregs[i]),
+                                          gregnames[i]);
+    }
+
+    for (i = 0; i < TARGET_DPREGS; i++) {
+        cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env,
+                                            offsetof(CPUSPARCState, fpr[i]),
+                                            fregnames[i]);
     }
 }
 
-- 
2.5.0

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

* [Qemu-devel] [PATCH v2 14/14] target-sparc: Use global registers for the register window
  2015-12-17 19:58 [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows Richard Henderson
                   ` (11 preceding siblings ...)
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 13/14] target-sparc: Tidy global register initialization Richard Henderson
@ 2015-12-17 20:00 ` Richard Henderson
  12 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2015-12-17 20:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien

Via indirection off cpu_regwptr.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-sparc/translate.c | 49 ++++++++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 22 deletions(-)

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index c13a9d3..c818a36 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -46,7 +46,8 @@ static TCGv_ptr cpu_env, cpu_regwptr;
 static TCGv cpu_cc_src, cpu_cc_src2, cpu_cc_dst;
 static TCGv_i32 cpu_cc_op;
 static TCGv_i32 cpu_psr;
-static TCGv cpu_fsr, cpu_pc, cpu_npc, cpu_gregs[8];
+static TCGv cpu_fsr, cpu_pc, cpu_npc;
+static TCGv cpu_regs[32];
 static TCGv cpu_y;
 #ifndef CONFIG_USER_ONLY
 static TCGv cpu_tbr;
@@ -276,36 +277,31 @@ static inline void gen_address_mask(DisasContext *dc, TCGv addr)
 
 static inline TCGv gen_load_gpr(DisasContext *dc, int reg)
 {
-    if (reg == 0 || reg >= 8) {
+    if (reg > 0) {
+        assert(reg < 32);
+        return cpu_regs[reg];
+    } else {
         TCGv t = get_temp_tl(dc);
-        if (reg == 0) {
-            tcg_gen_movi_tl(t, 0);
-        } else {
-            tcg_gen_ld_tl(t, cpu_regwptr, (reg - 8) * sizeof(target_ulong));
-        }
+        tcg_gen_movi_tl(t, 0);
         return t;
-    } else {
-        return cpu_gregs[reg];
     }
 }
 
 static inline void gen_store_gpr(DisasContext *dc, int reg, TCGv v)
 {
     if (reg > 0) {
-        if (reg < 8) {
-            tcg_gen_mov_tl(cpu_gregs[reg], v);
-        } else {
-            tcg_gen_st_tl(v, cpu_regwptr, (reg - 8) * sizeof(target_ulong));
-        }
+        assert(reg < 32);
+        tcg_gen_mov_tl(cpu_regs[reg], v);
     }
 }
 
 static inline TCGv gen_dest_gpr(DisasContext *dc, int reg)
 {
-    if (reg == 0 || reg >= 8) {
-        return get_temp_tl(dc);
+    if (reg > 0) {
+        assert(reg < 32);
+        return cpu_regs[reg];
     } else {
-        return cpu_gregs[reg];
+        return get_temp_tl(dc);
     }
 }
 
@@ -5321,8 +5317,11 @@ void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
 void gen_intermediate_code_init(CPUSPARCState *env)
 {
     static int inited;
-    static const char gregnames[8][4] = {
+    static const char gregnames[32][4] = {
         "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
+        "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
+        "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
+        "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
     };
     static const char fregnames[32][4] = {
         "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
@@ -5392,11 +5391,17 @@ void gen_intermediate_code_init(CPUSPARCState *env)
         *rtl[i].ptr = tcg_global_mem_new(cpu_env, rtl[i].off, rtl[i].name);
     }
 
-    TCGV_UNUSED(cpu_gregs[0]);
+    TCGV_UNUSED(cpu_regs[0]);
     for (i = 1; i < 8; ++i) {
-        cpu_gregs[i] = tcg_global_mem_new(cpu_env,
-                                          offsetof(CPUSPARCState, gregs[i]),
-                                          gregnames[i]);
+        cpu_regs[i] = tcg_global_mem_new(cpu_env,
+                                         offsetof(CPUSPARCState, gregs[i]),
+                                         gregnames[i]);
+    }
+
+    for (i = 8; i < 32; ++i) {
+        cpu_regs[i] = tcg_global_mem_new(cpu_regwptr,
+                                         (i - 8) * sizeof(target_ulong),
+                                         gregnames[i]);
     }
 
     for (i = 0; i < TARGET_DPREGS; i++) {
-- 
2.5.0

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

* Re: [Qemu-devel] [PATCH v2 02/14] tcg: Change ts->mem_reg to ts->mem_base
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 02/14] tcg: Change ts->mem_reg to ts->mem_base Richard Henderson
@ 2015-12-31 10:52   ` Aurelien Jarno
  0 siblings, 0 replies; 26+ messages in thread
From: Aurelien Jarno @ 2015-12-31 10:52 UTC (permalink / raw)
  To: Richard Henderson; +Cc: mark.cave-ayland, qemu-devel

On 2015-12-17 12:00, Richard Henderson wrote:
> Chain the temporaries together via pointers intstead of indices.
> The mem_reg value is now mem_base->reg.  This will be important later.
> 
> This does require that the frame pointer have a global temporary
> allocated for it.  This is simple bar the existing reserved_regs check.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  tcg/tcg.c | 65 +++++++++++++++++++++++++++++++++++----------------------------
>  tcg/tcg.h |  4 ++--
>  2 files changed, 38 insertions(+), 31 deletions(-)

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 03/14] tcg: Tidy temporary allocation
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 03/14] tcg: Tidy temporary allocation Richard Henderson
@ 2015-12-31 11:13   ` Aurelien Jarno
  0 siblings, 0 replies; 26+ messages in thread
From: Aurelien Jarno @ 2015-12-31 11:13 UTC (permalink / raw)
  To: Richard Henderson; +Cc: mark.cave-ayland, qemu-devel

On 2015-12-17 12:00, Richard Henderson wrote:
> In particular, make sure the memory is memset before use.
> Continues the increased use of TCGTemp pointers instead of
> integer indices where appropriate.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  tcg/tcg.c | 123 ++++++++++++++++++++++++++++----------------------------------
>  1 file changed, 56 insertions(+), 67 deletions(-)
> 
> diff --git a/tcg/tcg.c b/tcg/tcg.c
> index b1864d3..0a6edfb 100644
> --- a/tcg/tcg.c
> +++ b/tcg/tcg.c
> @@ -429,32 +429,45 @@ void tcg_func_start(TCGContext *s)
>      s->be = tcg_malloc(sizeof(TCGBackendData));
>  }
>  
> -static inline void tcg_temp_alloc(TCGContext *s, int n)
> +static inline int temp_idx(TCGContext *s, TCGTemp *ts)
>  {
> -    if (n > TCG_MAX_TEMPS)
> -        tcg_abort();
> +    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++;
> +    tcg_debug_assert(n < TCG_MAX_TEMPS);
> +    return memset(&s->temps[n], 0, sizeof(TCGTemp));
> +}
> +
> +static inline TCGTemp *tcg_global_alloc(TCGContext *s)
> +{
> +    tcg_debug_assert(s->nb_globals == s->nb_temps);
> +    s->nb_globals++;
> +    return tcg_temp_alloc(s);
>  }

This is transforming an abort() which can happen all the time in an
assert which can happen only when TCG debug is enabled. Is it really
something we want? Maybe we should add a tcg_assert() function.

Otherwise it looks fine.

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 04/14] tcg: More use of TCGReg where appropriate
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 04/14] tcg: More use of TCGReg where appropriate Richard Henderson
@ 2015-12-31 11:14   ` Aurelien Jarno
  0 siblings, 0 replies; 26+ messages in thread
From: Aurelien Jarno @ 2015-12-31 11:14 UTC (permalink / raw)
  To: Richard Henderson; +Cc: mark.cave-ayland, qemu-devel

On 2015-12-17 12:00, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  tcg/tcg.c | 26 +++++++++++++++-----------
>  tcg/tcg.h |  8 ++++----
>  2 files changed, 19 insertions(+), 15 deletions(-)

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 05/14] tcg: Remove tcg_get_arg_str_i32/64
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 05/14] tcg: Remove tcg_get_arg_str_i32/64 Richard Henderson
@ 2015-12-31 11:15   ` Aurelien Jarno
  0 siblings, 0 replies; 26+ messages in thread
From: Aurelien Jarno @ 2015-12-31 11:15 UTC (permalink / raw)
  To: Richard Henderson; +Cc: mark.cave-ayland, qemu-devel

On 2015-12-17 12:00, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  tcg/tcg.c | 10 ----------
>  tcg/tcg.h |  5 -----
>  2 files changed, 15 deletions(-)

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 06/14] tcg: Change reg_to_temp to TCGTemp pointer
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 06/14] tcg: Change reg_to_temp to TCGTemp pointer Richard Henderson
@ 2015-12-31 11:19   ` Aurelien Jarno
  0 siblings, 0 replies; 26+ messages in thread
From: Aurelien Jarno @ 2015-12-31 11:19 UTC (permalink / raw)
  To: Richard Henderson; +Cc: mark.cave-ayland, qemu-devel

On 2015-12-17 12:00, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  tcg/tcg.c | 113 ++++++++++++++++++++++++++++++--------------------------------
>  tcg/tcg.h |   6 ++--
>  2 files changed, 57 insertions(+), 62 deletions(-)

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 07/14] tcg: Change temp_dead argument to TCGTemp
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 07/14] tcg: Change temp_dead argument to TCGTemp Richard Henderson
@ 2015-12-31 11:24   ` Aurelien Jarno
  0 siblings, 0 replies; 26+ messages in thread
From: Aurelien Jarno @ 2015-12-31 11:24 UTC (permalink / raw)
  To: Richard Henderson; +Cc: mark.cave-ayland, qemu-devel

On 2015-12-17 12:00, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  tcg/tcg.c | 48 +++++++++++++++++++++++-------------------------
>  1 file changed, 23 insertions(+), 25 deletions(-)

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 08/14] tcg: Change temp_sync argument to TCGTemp
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 08/14] tcg: Change temp_sync " Richard Henderson
@ 2015-12-31 11:24   ` Aurelien Jarno
  0 siblings, 0 replies; 26+ messages in thread
From: Aurelien Jarno @ 2015-12-31 11:24 UTC (permalink / raw)
  To: Richard Henderson; +Cc: mark.cave-ayland, qemu-devel

On 2015-12-17 12:00, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  tcg/tcg.c | 55 ++++++++++++++++++++++++++++---------------------------
>  1 file changed, 28 insertions(+), 27 deletions(-)

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 09/14] tcg: Change temp_save argument to TCGTemp
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 09/14] tcg: Change temp_save " Richard Henderson
@ 2015-12-31 11:24   ` Aurelien Jarno
  0 siblings, 0 replies; 26+ messages in thread
From: Aurelien Jarno @ 2015-12-31 11:24 UTC (permalink / raw)
  To: Richard Henderson; +Cc: mark.cave-ayland, qemu-devel

On 2015-12-17 12:00, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  tcg/tcg.c | 16 +++++++---------
>  1 file changed, 7 insertions(+), 9 deletions(-)

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 10/14] tcg: Introduce temp_load
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 10/14] tcg: Introduce temp_load Richard Henderson
@ 2015-12-31 11:33   ` Aurelien Jarno
  2016-01-15 22:08     ` Richard Henderson
  0 siblings, 1 reply; 26+ messages in thread
From: Aurelien Jarno @ 2015-12-31 11:33 UTC (permalink / raw)
  To: Richard Henderson; +Cc: mark.cave-ayland, qemu-devel

On 2015-12-17 12:00, Richard Henderson wrote:
> Unify all of the places that realize a temporary into a register.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  tcg/tcg.c | 116 ++++++++++++++++++++++++++++----------------------------------
>  1 file changed, 52 insertions(+), 64 deletions(-)
> 
> diff --git a/tcg/tcg.c b/tcg/tcg.c
> index 6f40bf3..c51e0ec 100644
> --- a/tcg/tcg.c
> +++ b/tcg/tcg.c

[ snip ]

> @@ -2162,23 +2163,9 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
>  #endif
>          if (arg != TCG_CALL_DUMMY_ARG) {
>              ts = &s->temps[arg];
> -            if (ts->val_type == TEMP_VAL_REG) {
> -                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
> -            } else if (ts->val_type == TEMP_VAL_MEM) {
> -                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
> -                                    s->reserved_regs);
> -                /* XXX: not correct if reading values from the stack */

Shouldn't we keep this comment by moving it to temp_load?

> -                tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
> -                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
> -            } else if (ts->val_type == TEMP_VAL_CONST) {
> -                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
> -                                    s->reserved_regs);
> -                /* XXX: sign extend may be needed on some targets */

Same here.

> -                tcg_out_movi(s, ts->type, reg, ts->val);
> -                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
> -            } else {
> -                tcg_abort();
> -            }
> +            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);
>          }
>  #ifndef TCG_TARGET_STACK_GROWSUP
>          stack_offset += sizeof(tcg_target_long);
> @@ -2193,18 +2180,19 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
>              ts = &s->temps[arg];
>              reg = tcg_target_call_iarg_regs[i];
>              tcg_reg_free(s, reg);
> +
>              if (ts->val_type == TEMP_VAL_REG) {
>                  if (ts->reg != reg) {
>                      tcg_out_mov(s, ts->type, reg, ts->reg);
>                  }
> -            } else if (ts->val_type == TEMP_VAL_MEM) {
> -                tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
> -            } else if (ts->val_type == TEMP_VAL_CONST) {
> -                /* XXX: sign extend ? */

And here.

> -                tcg_out_movi(s, ts->type, reg, ts->val);
>              } else {
> -                tcg_abort();
> +                TCGRegSet arg_set;
> +
> +                tcg_regset_clear(arg_set);
> +                tcg_regset_set_reg(arg_set, reg);
> +                temp_load(s, ts, arg_set, allocated_regs);
>              }
> +
>              tcg_regset_set_reg(allocated_regs, reg);
>          }
>      }

Otherwise it's a nice cleanup :-).

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 11/14] tcg: Implement indirect memory registers
  2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 11/14] tcg: Implement indirect memory registers Richard Henderson
@ 2015-12-31 11:54   ` Aurelien Jarno
  2016-01-15 22:31     ` Richard Henderson
  0 siblings, 1 reply; 26+ messages in thread
From: Aurelien Jarno @ 2015-12-31 11:54 UTC (permalink / raw)
  To: Richard Henderson; +Cc: mark.cave-ayland, qemu-devel

On 2015-12-17 12:00, Richard Henderson wrote:
> That is, global_mem registers whose base is another global_mem
> register, rather than a fixed register.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  tcg/tcg.c | 95 ++++++++++++++++++++++++++++++++++++++++++++-------------------
>  tcg/tcg.h |  2 ++
>  2 files changed, 68 insertions(+), 29 deletions(-)
> 
> diff --git a/tcg/tcg.c b/tcg/tcg.c
> index c51e0ec..7150a3f 100644
> --- a/tcg/tcg.c
> +++ b/tcg/tcg.c
> @@ -509,17 +509,23 @@ int tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
>      TCGContext *s = &tcg_ctx;
>      TCGTemp *base_ts = &s->temps[GET_TCGV_PTR(base)];
>      TCGTemp *ts = tcg_global_alloc(s);
> -    int bigendian = 0;
> +    int indirect_reg = 0, bigendian = 0;
>  #ifdef HOST_WORDS_BIGENDIAN
>      bigendian = 1;
>  #endif
>  
> +    if (!base_ts->fixed_reg) {
> +        indirect_reg = 1;
> +        base_ts->indirect_base = 1;
> +    }
> +
>      if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
>          TCGTemp *ts2 = tcg_global_alloc(s);
>          char buf[64];
>  
>          ts->base_type = TCG_TYPE_I64;
>          ts->type = TCG_TYPE_I32;
> +        ts->indirect_reg = indirect_reg;

Do we really need to add this new bit, while we can simply test
ts->mem_base->fixed_reg? This means one more derefence, but anyway it
has to be done later when calling temp_load?

>          ts->mem_allocated = 1;
>          ts->mem_base = base_ts;
>          ts->mem_offset = offset + bigendian * 4;

> @@ -1781,13 +1803,16 @@ static inline void temp_save(TCGContext *s, TCGTemp *ts,
>                               TCGRegSet allocated_regs)
>  {
>  #ifdef USE_LIVENESS_ANALYSIS
> -    /* The liveness analysis already ensures that globals are back
> -       in memory. Keep an assert for safety. */
> -    tcg_debug_assert(ts->val_type == TEMP_VAL_MEM || ts->fixed_reg);
> -#else
> +    /* ??? Liveness does not yet incorporate indirect bases.  */
> +    if (!ts->indirect_base) {
> +        /* The liveness analysis already ensures that globals are back
> +           in memory. Keep an assert for safety. */
> +        tcg_debug_assert(ts->val_type == TEMP_VAL_MEM || ts->fixed_reg);
> +        return;
> +    }

This basically disables the assert. What does it mean in practice? Can
it generates bad code?

> +#endif
>      temp_sync(s, ts, allocated_regs);
>      temp_dead(s, ts);
> -#endif
>  }
>  
>  /* save globals to their canonical location and assume they can be
> @@ -1812,12 +1837,15 @@ static void sync_globals(TCGContext *s, TCGRegSet allocated_regs)
>      for (i = 0; i < s->nb_globals; i++) {
>          TCGTemp *ts = &s->temps[i];
>  #ifdef USE_LIVENESS_ANALYSIS
> -        tcg_debug_assert(ts->val_type != TEMP_VAL_REG
> -                         || ts->fixed_reg
> -                         || ts->mem_coherent);
> -#else
> -        temp_sync(s, ts, allocated_regs);
> +        /* ??? Liveness does not yet incorporate indirect bases.  */
> +        if (!ts->indirect_base) {
> +            tcg_debug_assert(ts->val_type != TEMP_VAL_REG
> +                             || ts->fixed_reg
> +                             || ts->mem_coherent);
> +            continue;
> +        }

Same here.

>  #endif
> +        temp_sync(s, ts, allocated_regs);
>      }
>  }
>  
> @@ -1833,12 +1861,15 @@ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
>              temp_save(s, ts, allocated_regs);
>          } else {
>  #ifdef USE_LIVENESS_ANALYSIS
> -            /* The liveness analysis already ensures that temps are dead.
> -               Keep an assert for safety. */
> -            assert(ts->val_type == TEMP_VAL_DEAD);
> -#else
> -            temp_dead(s, ts);
> +            /* ??? Liveness does not yet incorporate indirect bases.  */
> +            if (!ts->indirect_base) {
> +                /* The liveness analysis already ensures that temps are dead.
> +                   Keep an assert for safety. */
> +                assert(ts->val_type == TEMP_VAL_DEAD);
> +                continue;
> +            }

And here.

>  #endif
> +            temp_dead(s, ts);
>          }
>      }
>  

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH v2 10/14] tcg: Introduce temp_load
  2015-12-31 11:33   ` Aurelien Jarno
@ 2016-01-15 22:08     ` Richard Henderson
  0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-01-15 22:08 UTC (permalink / raw)
  To: Aurelien Jarno; +Cc: mark.cave-ayland, qemu-devel

On 12/31/2015 03:33 AM, Aurelien Jarno wrote:
>> -            if (ts->val_type == TEMP_VAL_REG) {
>> -                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
>> -            } else if (ts->val_type == TEMP_VAL_MEM) {
>> -                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
>> -                                    s->reserved_regs);
>> -                /* XXX: not correct if reading values from the stack */
> 
> Shouldn't we keep this comment by moving it to temp_load?

No, because I believe the comment to be inaccurate.

> 
>> -                tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
>> -                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
>> -            } else if (ts->val_type == TEMP_VAL_CONST) {
>> -                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
>> -                                    s->reserved_regs);
>> -                /* XXX: sign extend may be needed on some targets */
> 
> Same here.
> 
>> -                tcg_out_movi(s, ts->type, reg, ts->val);

Likewise.  If the target needs sign-extend, it will do it here in movi given
the type.

>> -                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
>> -            } else {
>> -                tcg_abort();
>> -            }
>> +            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);
>>          }
>>  #ifndef TCG_TARGET_STACK_GROWSUP
>>          stack_offset += sizeof(tcg_target_long);
>> @@ -2193,18 +2180,19 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
>>              ts = &s->temps[arg];
>>              reg = tcg_target_call_iarg_regs[i];
>>              tcg_reg_free(s, reg);
>> +
>>              if (ts->val_type == TEMP_VAL_REG) {
>>                  if (ts->reg != reg) {
>>                      tcg_out_mov(s, ts->type, reg, ts->reg);
>>                  }
>> -            } else if (ts->val_type == TEMP_VAL_MEM) {
>> -                tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
>> -            } else if (ts->val_type == TEMP_VAL_CONST) {
>> -                /* XXX: sign extend ? */
> 
> And here.
> 
>> -                tcg_out_movi(s, ts->type, reg, ts->val);

Likewise.


r~

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

* Re: [Qemu-devel] [PATCH v2 11/14] tcg: Implement indirect memory registers
  2015-12-31 11:54   ` Aurelien Jarno
@ 2016-01-15 22:31     ` Richard Henderson
  0 siblings, 0 replies; 26+ messages in thread
From: Richard Henderson @ 2016-01-15 22:31 UTC (permalink / raw)
  To: Aurelien Jarno; +Cc: mark.cave-ayland, qemu-devel

On 12/31/2015 03:54 AM, Aurelien Jarno wrote:
> On 2015-12-17 12:00, Richard Henderson wrote:
>> That is, global_mem registers whose base is another global_mem
>> register, rather than a fixed register.
>>
>> Signed-off-by: Richard Henderson <rth@twiddle.net>
>> ---
>>  tcg/tcg.c | 95 ++++++++++++++++++++++++++++++++++++++++++++-------------------
>>  tcg/tcg.h |  2 ++
>>  2 files changed, 68 insertions(+), 29 deletions(-)
>>
>> diff --git a/tcg/tcg.c b/tcg/tcg.c
>> index c51e0ec..7150a3f 100644
>> --- a/tcg/tcg.c
>> +++ b/tcg/tcg.c
>> @@ -509,17 +509,23 @@ int tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
>>      TCGContext *s = &tcg_ctx;
>>      TCGTemp *base_ts = &s->temps[GET_TCGV_PTR(base)];
>>      TCGTemp *ts = tcg_global_alloc(s);
>> -    int bigendian = 0;
>> +    int indirect_reg = 0, bigendian = 0;
>>  #ifdef HOST_WORDS_BIGENDIAN
>>      bigendian = 1;
>>  #endif
>>  
>> +    if (!base_ts->fixed_reg) {
>> +        indirect_reg = 1;
>> +        base_ts->indirect_base = 1;
>> +    }
>> +
>>      if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
>>          TCGTemp *ts2 = tcg_global_alloc(s);
>>          char buf[64];
>>  
>>          ts->base_type = TCG_TYPE_I64;
>>          ts->type = TCG_TYPE_I32;
>> +        ts->indirect_reg = indirect_reg;
> 
> Do we really need to add this new bit, while we can simply test
> ts->mem_base->fixed_reg? This means one more derefence, but anyway it
> has to be done later when calling temp_load?

I thought it cleaner to have the bit.  We're using 7 of 32 (or 39 of 64) from
the word, so we're not really short of bit space.

>> +    /* ??? Liveness does not yet incorporate indirect bases.  */
>> +    if (!ts->indirect_base) {
>> +        /* The liveness analysis already ensures that globals are back
>> +           in memory. Keep an assert for safety. */
>> +        tcg_debug_assert(ts->val_type == TEMP_VAL_MEM || ts->fixed_reg);
>> +        return;
>> +    }
> 
> This basically disables the assert. What does it mean in practice? Can
> it generates bad code?

Since we have no liveness info for the indirect base, we don't know exactly
where it begins and ends life.  That could be fixed with additional effort,
but it didn't seem to be required during this initial implementation.

Since we don't have liveness info, I simply want to follow the path we would
take when liveness info isn't computed.  We do not generate bad code.


r~

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

end of thread, other threads:[~2016-01-15 22:31 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-17 19:58 [Qemu-devel] [PATCH v2 00/14] tcg: Improve sparc register windows Richard Henderson
2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 02/14] tcg: Change ts->mem_reg to ts->mem_base Richard Henderson
2015-12-31 10:52   ` Aurelien Jarno
2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 03/14] tcg: Tidy temporary allocation Richard Henderson
2015-12-31 11:13   ` Aurelien Jarno
2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 04/14] tcg: More use of TCGReg where appropriate Richard Henderson
2015-12-31 11:14   ` Aurelien Jarno
2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 05/14] tcg: Remove tcg_get_arg_str_i32/64 Richard Henderson
2015-12-31 11:15   ` Aurelien Jarno
2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 06/14] tcg: Change reg_to_temp to TCGTemp pointer Richard Henderson
2015-12-31 11:19   ` Aurelien Jarno
2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 07/14] tcg: Change temp_dead argument to TCGTemp Richard Henderson
2015-12-31 11:24   ` Aurelien Jarno
2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 08/14] tcg: Change temp_sync " Richard Henderson
2015-12-31 11:24   ` Aurelien Jarno
2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 09/14] tcg: Change temp_save " Richard Henderson
2015-12-31 11:24   ` Aurelien Jarno
2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 10/14] tcg: Introduce temp_load Richard Henderson
2015-12-31 11:33   ` Aurelien Jarno
2016-01-15 22:08     ` Richard Henderson
2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 11/14] tcg: Implement indirect memory registers Richard Henderson
2015-12-31 11:54   ` Aurelien Jarno
2016-01-15 22:31     ` Richard Henderson
2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 12/14] tcg: Allocate indirect_base temporaries in a different order Richard Henderson
2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 13/14] target-sparc: Tidy global register initialization Richard Henderson
2015-12-17 20:00 ` [Qemu-devel] [PATCH v2 14/14] target-sparc: Use global registers for the register window Richard Henderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.