Commit cf066674 authored by Richard Henderson's avatar Richard Henderson
Browse files

tcg: Make call address a constant parameter



Avoid allocating a tcg temporary to hold the constant address,
and instead place it directly into the op_call arguments.

At the same time, convert to the newly introduced tcg_out_call
backend function, rather than invoking tcg_out_op for the call.

Signed-off-by: default avatarRichard Henderson <rth@twiddle.net>
parent dddbb2e1
Loading
Loading
Loading
Loading
+33 −42
Original line number Diff line number Diff line
@@ -513,12 +513,8 @@ static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                                    TCGArg *args, TCGOpDef *tcg_op_defs)
{
    int i, nb_ops, op_index, nb_temps, nb_globals, nb_call_args;
    tcg_target_ulong mask, affected;
    TCGOpcode op;
    const TCGOpDef *def;
    int nb_ops, op_index, nb_temps, nb_globals;
    TCGArg *gen_args;
    TCGArg tmp;

    /* Array VALS has an element for each temp.
       If this temp holds a constant then its value is kept in VALS' element.
@@ -532,24 +528,29 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
    nb_ops = tcg_opc_ptr - s->gen_opc_buf;
    gen_args = args;
    for (op_index = 0; op_index < nb_ops; op_index++) {
        op = s->gen_opc_buf[op_index];
        def = &tcg_op_defs[op];
        /* Do copy propagation */
        TCGOpcode op = s->gen_opc_buf[op_index];
        const TCGOpDef *def = &tcg_op_defs[op];
        tcg_target_ulong mask, affected;
        int nb_oargs, nb_iargs, nb_args, i;
        TCGArg tmp;

        if (op == INDEX_op_call) {
            int nb_oargs = args[0] >> 16;
            int nb_iargs = args[0] & 0xffff;
            for (i = nb_oargs + 1; i < nb_oargs + nb_iargs + 1; i++) {
                if (temps[args[i]].state == TCG_TEMP_COPY) {
                    args[i] = find_better_copy(s, args[i]);
                }
            }
            *gen_args++ = tmp = *args++;
            nb_oargs = tmp >> 16;
            nb_iargs = tmp & 0xffff;
            nb_args = nb_oargs + nb_iargs + def->nb_cargs;
        } else {
            for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
            nb_oargs = def->nb_oargs;
            nb_iargs = def->nb_iargs;
            nb_args = def->nb_args;
        }

        /* Do copy propagation */
        for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
            if (temps[args[i]].state == TCG_TEMP_COPY) {
                args[i] = find_better_copy(s, args[i]);
            }
        }
        }

        /* For commutative operations make constant second argument */
        switch (op) {
@@ -882,7 +883,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,

        CASE_OP_32_64(qemu_ld):
            {
                TCGMemOp mop = args[def->nb_oargs + def->nb_iargs];
                TCGMemOp mop = args[nb_oargs + nb_iargs];
                if (!(mop & MO_SIGN)) {
                    mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1;
                }
@@ -900,15 +901,15 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
        }

        if (mask == 0) {
            assert(def->nb_oargs == 1);
            assert(nb_oargs == 1);
            s->gen_opc_buf[op_index] = op_to_movi(op);
            tcg_opt_gen_movi(gen_args, args[0], 0);
            args += def->nb_oargs + def->nb_iargs + def->nb_cargs;
            args += nb_args;
            gen_args += 2;
            continue;
        }
        if (affected == 0) {
            assert(def->nb_oargs == 1);
            assert(nb_oargs == 1);
            if (temps_are_copies(args[0], args[1])) {
                s->gen_opc_buf[op_index] = INDEX_op_nop;
            } else if (temps[args[1]].state != TCG_TEMP_CONST) {
@@ -920,7 +921,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                tcg_opt_gen_movi(gen_args, args[0], temps[args[1]].val);
                gen_args += 2;
            }
            args += def->nb_iargs + 1;
            args += nb_args;
            continue;
        }

@@ -1246,24 +1247,13 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
            break;

        case INDEX_op_call:
            nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
            if (!(args[nb_call_args + 1] & (TCG_CALL_NO_READ_GLOBALS |
                                            TCG_CALL_NO_WRITE_GLOBALS))) {
            if (!(args[nb_oargs + nb_iargs + 1]
                  & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
                for (i = 0; i < nb_globals; i++) {
                    reset_temp(i);
                }
            }
            for (i = 0; i < (args[0] >> 16); i++) {
                reset_temp(args[i + 1]);
            }
            i = nb_call_args + 3;
            while (i) {
                *gen_args = *args;
                args++;
                gen_args++;
                i--;
            }
            break;
            goto do_reset_output;

        default:
        do_default:
@@ -1275,7 +1265,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
            if (def->flags & TCG_OPF_BB_END) {
                reset_all_temps(nb_temps);
            } else {
                for (i = 0; i < def->nb_oargs; i++) {
        do_reset_output:
                for (i = 0; i < nb_oargs; i++) {
                    reset_temp(args[i]);
                    /* Save the corresponding known-zero bits mask for the
                       first output argument (only one supported so far). */
@@ -1284,11 +1275,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                    }
                }
            }
            for (i = 0; i < def->nb_args; i++) {
            for (i = 0; i < nb_args; i++) {
                gen_args[i] = args[i];
            }
            args += def->nb_args;
            gen_args += def->nb_args;
            args += nb_args;
            gen_args += nb_args;
            break;
        }
    }
+3 −13
Original line number Diff line number Diff line
@@ -390,11 +390,7 @@ static inline int tcg_gen_sizemask(int n, int is_64bit, int is_signed)
static inline void tcg_gen_helperN(void *func, int flags, int sizemask,
                                   TCGArg ret, int nargs, TCGArg *args)
{
    TCGv_ptr fn;
    fn = tcg_const_ptr(func);
    tcg_gen_callN(&tcg_ctx, fn, flags, sizemask, ret,
                  nargs, args);
    tcg_temp_free_ptr(fn);
    tcg_gen_callN(&tcg_ctx, func, flags, sizemask, ret, nargs, args);
}

/* Note: Both tcg_gen_helper32() and tcg_gen_helper64() are currently
@@ -405,29 +401,23 @@ static inline void tcg_gen_helperN(void *func, int flags, int sizemask,
static inline void tcg_gen_helper32(void *func, int sizemask, TCGv_i32 ret,
                                    TCGv_i32 a, TCGv_i32 b)
{
    TCGv_ptr fn;
    TCGArg args[2];
    fn = tcg_const_ptr(func);
    args[0] = GET_TCGV_I32(a);
    args[1] = GET_TCGV_I32(b);
    tcg_gen_callN(&tcg_ctx, fn,
    tcg_gen_callN(&tcg_ctx, func,
                  TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_SIDE_EFFECTS,
                  sizemask, GET_TCGV_I32(ret), 2, args);
    tcg_temp_free_ptr(fn);
}

static inline void tcg_gen_helper64(void *func, int sizemask, TCGv_i64 ret,
                                    TCGv_i64 a, TCGv_i64 b)
{
    TCGv_ptr fn;
    TCGArg args[2];
    fn = tcg_const_ptr(func);
    args[0] = GET_TCGV_I64(a);
    args[1] = GET_TCGV_I64(b);
    tcg_gen_callN(&tcg_ctx, fn,
    tcg_gen_callN(&tcg_ctx, func,
                  TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_SIDE_EFFECTS,
                  sizemask, GET_TCGV_I64(ret), 2, args);
    tcg_temp_free_ptr(fn);
}

/* 32 bit ops */
+1 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ DEF(discard, 1, 0, 0, TCG_OPF_NOT_PRESENT)
DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT)

/* variable number of parameters */
DEF(call, 0, 1, 2, TCG_OPF_CALL_CLOBBER)
DEF(call, 0, 0, 3, TCG_OPF_CALL_CLOBBER)

DEF(br, 0, 0, 1, TCG_OPF_BB_END)

+34 −95
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
                       const int *const_args);
static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
                       intptr_t arg2);
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 void tcg_out_tb_init(TCGContext *s);
@@ -705,7 +706,7 @@ int tcg_check_temp_count(void)
/* Note: we convert the 64 bit args to 32 bit and do some alignment
   and endian swap. Maybe it would be better to do the alignment
   and endian swap in tcg_reg_alloc_call(). */
void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
void tcg_gen_callN(TCGContext *s, void *func, unsigned int flags,
                   int sizemask, TCGArg ret, int nargs, TCGArg *args)
{
    int i;
@@ -832,11 +833,10 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
        *s->gen_opparam_ptr++ = args[i];
        real_args++;
    }
    *s->gen_opparam_ptr++ = GET_TCGV_PTR(func);

    *s->gen_opparam_ptr++ = (uintptr_t)func;
    *s->gen_opparam_ptr++ = flags;

    *nparam = (nb_rets << 16) | (real_args + 1);
    *nparam = (nb_rets << 16) | real_args;

    /* total parameters, needed to go backward in the instruction stream */
    *s->gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
@@ -1243,49 +1243,21 @@ void tcg_dump_ops(TCGContext *s)
            nb_iargs = arg & 0xffff;
            nb_cargs = def->nb_cargs;

            qemu_log(" %s ", def->name);

            /* function name */
            qemu_log("%s",
                     tcg_get_arg_str_idx(s, buf, sizeof(buf),
                                         args[nb_oargs + nb_iargs - 1]));
            /* flags */
            qemu_log(",$0x%" TCG_PRIlx, args[nb_oargs + nb_iargs]);
            /* nb out args */
            qemu_log(",$%d", nb_oargs);
            /* function name, flags, out args */
            qemu_log(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name,
                     tcg_find_helper(s, args[nb_oargs + nb_iargs]),
                     args[nb_oargs + nb_iargs + 1], nb_oargs);
            for (i = 0; i < nb_oargs; i++) {
                qemu_log(",");
                qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
                qemu_log(",%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
                                                   args[i]));
            }
            for(i = 0; i < (nb_iargs - 1); i++) {
                qemu_log(",");
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
                    qemu_log("<dummy>");
                } else {
                    qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
                                                       args[nb_oargs + i]));
                }
            }
        } else if (c == INDEX_op_movi_i32 || c == INDEX_op_movi_i64) {
            tcg_target_ulong val;
            const char *name;

            nb_oargs = def->nb_oargs;
            nb_iargs = def->nb_iargs;
            nb_cargs = def->nb_cargs;
            qemu_log(" %s %s,$", def->name,
                     tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
            val = args[1];
            name = tcg_find_helper(s, val);
            if (name) {
                qemu_log("%s", name);
            } else {
                if (c == INDEX_op_movi_i32) {
                    qemu_log("0x%x", (uint32_t)val);
                } else {
                    qemu_log("0x%" PRIx64 , (uint64_t)val);
            for (i = 0; i < nb_iargs; i++) {
                TCGArg arg = args[nb_oargs + i];
                const char *t = "<dummy>";
                if (arg != TCG_CALL_DUMMY_ARG) {
                    t = tcg_get_arg_str_idx(s, buf, sizeof(buf), arg);
                }
                qemu_log(",%s", t);
            }
        } else {
            qemu_log(" %s ", def->name);
@@ -1548,9 +1520,9 @@ static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps,
   temporaries are removed. */
static void tcg_liveness_analysis(TCGContext *s)
{
    int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
    int i, op_index, nb_args, nb_iargs, nb_oargs, nb_ops;
    TCGOpcode op, op_new, op_new2;
    TCGArg *args;
    TCGArg *args, arg;
    const TCGOpDef *def;
    uint8_t *dead_temps, *mem_temps;
    uint16_t dead_args;
@@ -1580,10 +1552,10 @@ static void tcg_liveness_analysis(TCGContext *s)

                nb_args = args[-1];
                args -= nb_args;
                nb_iargs = args[0] & 0xffff;
                nb_oargs = args[0] >> 16;
                args++;
                call_flags = args[nb_oargs + nb_iargs];
                arg = *args++;
                nb_iargs = arg & 0xffff;
                nb_oargs = arg >> 16;
                call_flags = args[nb_oargs + nb_iargs + 1];

                /* pure functions can be removed if their result is not
                   used */
@@ -2372,26 +2344,27 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
                              uint16_t dead_args, uint8_t sync_args)
{
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
    TCGArg arg, func_arg;
    TCGArg arg;
    TCGTemp *ts;
    intptr_t stack_offset;
    size_t call_stack_size;
    uintptr_t func_addr;
    int const_func_arg, allocate_args;
    tcg_insn_unit *func_addr;
    int allocate_args;
    TCGRegSet allocated_regs;
    const TCGArgConstraint *arg_ct;

    arg = *args++;

    nb_oargs = arg >> 16;
    nb_iargs = arg & 0xffff;
    nb_params = nb_iargs - 1;
    nb_params = nb_iargs;

    flags = args[nb_oargs + nb_iargs];
    func_addr = (tcg_insn_unit *)(intptr_t)args[nb_oargs + nb_iargs];
    flags = args[nb_oargs + nb_iargs + 1];

    nb_regs = ARRAY_SIZE(tcg_target_call_iarg_regs);
    if (nb_regs > nb_params)
    if (nb_regs > nb_params) {
        nb_regs = nb_params;
    }

    /* assign stack slots first */
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
@@ -2459,40 +2432,6 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
        }
    }
    
    /* assign function address */
    func_arg = args[nb_oargs + nb_iargs - 1];
    arg_ct = &def->args_ct[0];
    ts = &s->temps[func_arg];
    func_addr = ts->val;
    const_func_arg = 0;
    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);
        func_arg = reg;
        tcg_regset_set_reg(allocated_regs, reg);
    } else if (ts->val_type == TEMP_VAL_REG) {
        reg = ts->reg;
        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
            tcg_out_mov(s, ts->type, reg, ts->reg);
        }
        func_arg = reg;
        tcg_regset_set_reg(allocated_regs, reg);
    } else if (ts->val_type == TEMP_VAL_CONST) {
        if (tcg_target_const_match(func_addr, ts->type, arg_ct)) {
            const_func_arg = 1;
            func_arg = func_addr;
        } else {
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
            tcg_out_movi(s, ts->type, reg, func_addr);
            func_arg = reg;
            tcg_regset_set_reg(allocated_regs, reg);
        }
    } else {
        tcg_abort();
    }
        
    
    /* mark dead temporaries and free the associated registers */
    for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
        if (IS_DEAD_ARG(i)) {
@@ -2517,7 +2456,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
        save_globals(s, allocated_regs);
    }

    tcg_out_op(s, opc, &func_arg, &const_func_arg);
    tcg_out_call(s, func_addr);

    /* assign output registers and emit moves if needed */
    for(i = 0; i < nb_oargs; i++) {
+1 −1
Original line number Diff line number Diff line
@@ -725,7 +725,7 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs);
#define tcg_temp_free_ptr(T) tcg_temp_free_i64(TCGV_PTR_TO_NAT(T))
#endif

void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
void tcg_gen_callN(TCGContext *s, void *func, unsigned int flags,
                   int sizemask, TCGArg ret, int nargs, TCGArg *args);

void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,