@@ -518,6 +518,11 @@ typedef struct TCGOp {
/* Make sure operands fit in the bitfields above. */
QEMU_BUILD_BUG_ON(NB_OPS > (1 << 8));
+static inline TCGRegSet output_pref(const TCGOp *op, unsigned i)
+{
+ return i < ARRAY_SIZE(op->output_pref) ? op->output_pref[i] : 0;
+}
+
typedef struct TCGProfile {
int64_t cpu_exec_time;
int64_t tb_count1;
@@ -1957,7 +1957,7 @@ static void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs)
if (have_prefs) {
for (i = 0; i < nb_oargs; ++i) {
- TCGRegSet set = op->output_pref[i];
+ TCGRegSet set = output_pref(op, i);
if (i == 0) {
ne_fprintf(f, " pref=");
@@ -2627,11 +2627,11 @@ static void liveness_pass_1(TCGContext *s)
}
ts->state = TS_DEAD;
la_reset_pref(ts);
-
- /* Not used -- it will be tcg_target_call_oarg_regs[i]. */
- op->output_pref[i] = 0;
}
+ /* Not used -- it will be tcg_target_call_oarg_reg(). */
+ memset(op->output_pref, 0, sizeof(op->output_pref));
+
if (!(call_flags & (TCG_CALL_NO_WRITE_GLOBALS |
TCG_CALL_NO_READ_GLOBALS))) {
la_global_kill(s, nb_globals);
@@ -2793,7 +2793,9 @@ static void liveness_pass_1(TCGContext *s)
ts = arg_temp(op->args[i]);
/* Remember the preference of the uses that followed. */
- op->output_pref[i] = *la_temp_pref(ts);
+ if (i < ARRAY_SIZE(op->output_pref)) {
+ op->output_pref[i] = *la_temp_pref(ts);
+ }
/* Output args are dead. */
if (ts->state & TS_DEAD) {
@@ -2863,7 +2865,7 @@ static void liveness_pass_1(TCGContext *s)
set &= ct->regs;
if (ct->ialias) {
- set &= op->output_pref[ct->alias_index];
+ set &= output_pref(op, ct->alias_index);
}
/* If the combination is not possible, restart. */
if (set == 0) {
@@ -3581,7 +3583,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp *op)
TCGType otype, itype;
allocated_regs = s->reserved_regs;
- preferred_regs = op->output_pref[0];
+ preferred_regs = output_pref(op, 0);
ots = arg_temp(op->args[0]);
ts = arg_temp(op->args[1]);
@@ -3696,7 +3698,7 @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp *op)
if (IS_DEAD_ARG(1)) {
temp_dead(s, its);
}
- tcg_reg_alloc_do_movi(s, ots, val, arg_life, op->output_pref[0]);
+ tcg_reg_alloc_do_movi(s, ots, val, arg_life, output_pref(op, 0));
return;
}
@@ -3712,7 +3714,7 @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp *op)
tcg_regset_set_reg(allocated_regs, its->reg);
}
ots->reg = tcg_reg_alloc(s, dup_out_regs, allocated_regs,
- op->output_pref[0], ots->indirect_base);
+ output_pref(op, 0), ots->indirect_base);
ots->val_type = TEMP_VAL_REG;
ots->mem_coherent = 0;
s->reg_to_temp[ots->reg] = ots;
@@ -3831,7 +3833,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
switch (arg_ct->pair) {
case 0: /* not paired */
if (arg_ct->ialias) {
- i_preferred_regs = op->output_pref[arg_ct->alias_index];
+ i_preferred_regs = output_pref(op, arg_ct->alias_index);
/*
* If the input is readonly, then it cannot also be an
@@ -3882,7 +3884,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
ts2 = i1 != i2 ? arg_temp(op->args[i2]) : NULL;
if (arg_ct->ialias) {
- i_preferred_regs = op->output_pref[arg_ct->alias_index];
+ i_preferred_regs = output_pref(op, arg_ct->alias_index);
if (IS_DEAD_ARG(i1) &&
IS_DEAD_ARG(i2) &&
!temp_readonly(ts) &&
@@ -3928,7 +3930,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
case 3: /* ialias with second output, no first input */
tcg_debug_assert(arg_ct->ialias);
- i_preferred_regs = op->output_pref[arg_ct->alias_index];
+ i_preferred_regs = output_pref(op, arg_ct->alias_index);
allocate_new_reg = true;
if (IS_DEAD_ARG(i) &&
@@ -4018,10 +4020,10 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
} else if (arg_ct->newreg) {
reg = tcg_reg_alloc(s, arg_ct->regs,
i_allocated_regs | o_allocated_regs,
- op->output_pref[k], ts->indirect_base);
+ output_pref(op, k), ts->indirect_base);
} else {
reg = tcg_reg_alloc(s, arg_ct->regs, o_allocated_regs,
- op->output_pref[k], ts->indirect_base);
+ output_pref(op, k), ts->indirect_base);
}
break;
@@ -4032,7 +4034,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
break;
}
reg = tcg_reg_alloc_pair(s, arg_ct->regs, o_allocated_regs,
- op->output_pref[k], ts->indirect_base);
+ output_pref(op, k), ts->indirect_base);
break;
case 2: /* second of pair */
@@ -4123,7 +4125,7 @@ static bool tcg_reg_alloc_dup2(TCGContext *s, const TCGOp *op)
}
ots->reg = tcg_reg_alloc(s, dup_out_regs, allocated_regs,
- op->output_pref[0], ots->indirect_base);
+ output_pref(op, 0), ots->indirect_base);
ots->val_type = TEMP_VAL_REG;
ots->mem_coherent = 0;
s->reg_to_temp[ots->reg] = ots;
We will shortly have the possibility of more that two outputs, though only for calls (for which preferences are moot). Avoid direct references to op->output_pref[] when possible. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- include/tcg/tcg.h | 5 +++++ tcg/tcg.c | 34 ++++++++++++++++++---------------- 2 files changed, 23 insertions(+), 16 deletions(-)