[for-2.11,1/6] tcg: Add tcg_reg_alloc_new
diff mbox

Message ID 20170804062314.12594-2-rth@twiddle.net
State New
Headers show

Commit Message

Richard Henderson Aug. 4, 2017, 6:23 a.m. UTC
This allows the backend to allocate an otherwise unused register.
This can allow the backend to avoid having to reserve a full-time
temporary register.

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

Patch
diff mbox

diff --git a/tcg/tcg.h b/tcg/tcg.h
index ac94133870..dd97095af5 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -655,6 +655,7 @@  struct TCGContext {
     uintptr_t *tb_jmp_insn_offset; /* tb->jmp_target_arg if direct_jump */
     uintptr_t *tb_jmp_target_addr; /* tb->jmp_target_arg if !direct_jump */
 
+    TCGRegSet regs_in_use;
     TCGRegSet reserved_regs;
     intptr_t current_frame_offset;
     intptr_t frame_start;
diff --git a/tcg/tcg.c b/tcg/tcg.c
index fd8a3dfe93..787c8ba0f7 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -112,6 +112,8 @@  static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
 static void tcg_out_call(TCGContext *s, tcg_insn_unit *target);
 static int tcg_target_const_match(tcg_target_long val, TCGType type,
                                   const TCGArgConstraint *arg_ct);
+static TCGReg tcg_reg_alloc_new(TCGContext *s, TCGType t)
+    __attribute__((unused));
 #ifdef TCG_TARGET_NEED_LDST_LABELS
 static bool tcg_out_ldst_finalize(TCGContext *s);
 #endif
@@ -1947,16 +1949,19 @@  static void temp_sync(TCGContext *s, TCGTemp *ts,
             /* If we're going to free the temp immediately, then we won't
                require it later in a register, so attempt to store the
                constant to memory directly.  */
-            if (free_or_dead
-                && tcg_out_sti(s, ts->type, ts->val,
-                               ts->mem_base->reg, ts->mem_offset)) {
-                break;
+            if (free_or_dead) {
+                s->regs_in_use = -1;
+                if (tcg_out_sti(s, ts->type, ts->val,
+                                ts->mem_base->reg, ts->mem_offset)) {
+                    break;
+                }
             }
             temp_load(s, ts, tcg_target_available_regs[ts->type],
                       allocated_regs);
             /* fallthrough */
 
         case TEMP_VAL_REG:
+            s->regs_in_use = -1;
             tcg_out_st(s, ts->type, ts->reg,
                        ts->mem_base->reg, ts->mem_offset);
             break;
@@ -2015,6 +2020,14 @@  static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet desired_regs,
     tcg_abort();
 }
 
+static TCGReg tcg_reg_alloc_new(TCGContext *s, TCGType t)
+{
+    TCGReg r;
+    r = tcg_reg_alloc(s, tcg_target_available_regs[t], s->regs_in_use, 0);
+    tcg_regset_set_reg(s->regs_in_use, r);
+    return r;
+}
+
 /* 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,
@@ -2027,11 +2040,13 @@  static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs,
         return;
     case TEMP_VAL_CONST:
         reg = tcg_reg_alloc(s, desired_regs, allocated_regs, ts->indirect_base);
+        s->regs_in_use = 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, ts->indirect_base);
+        s->regs_in_use = -1;
         tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
         ts->mem_coherent = 1;
         break;
@@ -2105,6 +2120,7 @@  static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp *ots,
 {
     if (ots->fixed_reg) {
         /* For fixed registers, we do not do any constant propagation.  */
+        s->regs_in_use = s->reserved_regs;
         tcg_out_movi(s, ots->type, ots->reg, val);
         return;
     }
@@ -2129,17 +2145,16 @@  static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
     TCGTemp *ots = &s->temps[args[0]];
     tcg_target_ulong val = args[1];
 
+    s->regs_in_use = s->reserved_regs;
     tcg_reg_alloc_do_movi(s, ots, val, arg_life);
 }
 
 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
                               const TCGArg *args, TCGLifeData arg_life)
 {
-    TCGRegSet allocated_regs;
     TCGTemp *ts, *ots;
     TCGType otype, itype;
 
-    tcg_regset_set(allocated_regs, s->reserved_regs);
     ots = &s->temps[args[0]];
     ts = &s->temps[args[1]];
 
@@ -2153,6 +2168,7 @@  static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
         if (IS_DEAD_ARG(1)) {
             temp_dead(s, ts);
         }
+        s->regs_in_use = s->reserved_regs;
         tcg_reg_alloc_do_movi(s, ots, val, arg_life);
         return;
     }
@@ -2162,7 +2178,7 @@  static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
        the SOURCE value into its own register first, that way we
        don't have to reload SOURCE the next time it is used. */
     if (ts->val_type == TEMP_VAL_MEM) {
-        temp_load(s, ts, tcg_target_available_regs[itype], allocated_regs);
+        temp_load(s, ts, tcg_target_available_regs[itype], s->reserved_regs);
     }
 
     tcg_debug_assert(ts->val_type == TEMP_VAL_REG);
@@ -2173,12 +2189,14 @@  static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
         if (!ots->mem_allocated) {
             temp_allocate_frame(s, args[0]);
         }
+        s->regs_in_use = -1;
         tcg_out_st(s, otype, ts->reg, ots->mem_base->reg, ots->mem_offset);
         if (IS_DEAD_ARG(1)) {
             temp_dead(s, ts);
         }
         temp_dead(s, ots);
     } else {
+        TCGRegSet allocated_regs;
         if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
             /* the mov can be suppressed */
             if (ots->val_type == TEMP_VAL_REG) {
@@ -2188,19 +2206,21 @@  static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
             temp_dead(s, ts);
         } else {
             if (ots->val_type != TEMP_VAL_REG) {
-                /* When allocating a new register, make sure to not spill the
-                   input one. */
+                /* When allocating a new register, make sure to not
+                   spill the input one. */
+                allocated_regs = s->reserved_regs;
                 tcg_regset_set_reg(allocated_regs, ts->reg);
                 ots->reg = tcg_reg_alloc(s, tcg_target_available_regs[otype],
                                          allocated_regs, ots->indirect_base);
             }
+            s->regs_in_use = -1;
             tcg_out_mov(s, otype, ots->reg, ts->reg);
         }
         ots->val_type = TEMP_VAL_REG;
         ots->mem_coherent = 0;
         s->reg_to_temp[ots->reg] = ots;
         if (NEED_SYNC_ARG(0)) {
-            temp_sync(s, ots, allocated_regs, 0);
+            temp_sync(s, ots, s->reserved_regs, 0);
         }
     }
 }
@@ -2281,6 +2301,7 @@  static void tcg_reg_alloc_op(TCGContext *s,
                and move the temporary register into it */
             reg = tcg_reg_alloc(s, arg_ct->u.regs, i_allocated_regs,
                                 ts->indirect_base);
+            s->regs_in_use = -1;
             tcg_out_mov(s, ts->type, reg, ts->reg);
         }
         new_args[i] = reg;
@@ -2355,6 +2376,7 @@  static void tcg_reg_alloc_op(TCGContext *s,
     }
 
     /* emit instruction */
+    s->regs_in_use = i_allocated_regs | o_allocated_regs;
     tcg_out_op(s, opc, new_args, const_args);
     
     /* move the outputs in the correct register if needed */
@@ -2362,6 +2384,7 @@  static void tcg_reg_alloc_op(TCGContext *s,
         ts = &s->temps[args[i]];
         reg = new_args[i];
         if (ts->fixed_reg && ts->reg != reg) {
+            s->regs_in_use = -1;
             tcg_out_mov(s, ts->type, ts->reg, reg);
         }
         if (NEED_SYNC_ARG(i)) {
@@ -2420,6 +2443,7 @@  static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
             ts = &s->temps[arg];
             temp_load(s, ts, tcg_target_available_regs[ts->type],
                       s->reserved_regs);
+            s->regs_in_use = -1;
             tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
         }
 #ifndef TCG_TARGET_STACK_GROWSUP
@@ -2428,7 +2452,7 @@  static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
     }
     
     /* assign input registers */
-    tcg_regset_set(allocated_regs, s->reserved_regs);
+    allocated_regs = s->reserved_regs;
     for(i = 0; i < nb_regs; i++) {
         arg = args[nb_oargs + i];
         if (arg != TCG_CALL_DUMMY_ARG) {
@@ -2438,6 +2462,7 @@  static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
 
             if (ts->val_type == TEMP_VAL_REG) {
                 if (ts->reg != reg) {
+                    s->regs_in_use = -1;
                     tcg_out_mov(s, ts->type, reg, ts->reg);
                 }
             } else {
@@ -2458,7 +2483,7 @@  static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
             temp_dead(s, &s->temps[args[i]]);
         }
     }
-    
+
     /* clobber call registers */
     for (i = 0; i < TCG_TARGET_NB_REGS; i++) {
         if (tcg_regset_test_reg(tcg_target_call_clobber_regs, i)) {
@@ -2476,10 +2501,16 @@  static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
         save_globals(s, allocated_regs);
     }
 
+    s->regs_in_use = allocated_regs;
     tcg_out_call(s, func_addr);
 
     /* assign output registers and emit moves if needed */
-    for(i = 0; i < nb_oargs; i++) {
+    allocated_regs = s->reserved_regs;
+    for (i = 0; i < nb_oargs; i++) {
+        reg = tcg_target_call_oarg_regs[i];
+        tcg_regset_set_reg(allocated_regs, reg);
+    }
+    for (i = 0; i < nb_oargs; i++) {
         arg = args[i];
         ts = &s->temps[arg];
         reg = tcg_target_call_oarg_regs[i];
@@ -2487,6 +2518,7 @@  static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
 
         if (ts->fixed_reg) {
             if (ts->reg != reg) {
+                s->regs_in_use = -1;
                 tcg_out_mov(s, ts->type, ts->reg, reg);
             }
         } else {