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

tcg: Put opcodes in a linked list



The previous setup required ops and args to be completely sequential,
and was error prone when it came to both iteration and optimization.

Reviewed-by: default avatarBastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: default avatarRichard Henderson <rth@twiddle.net>
parent fe700adb
Loading
Loading
Loading
Loading
+16 −6
Original line number Diff line number Diff line
@@ -11,8 +11,8 @@ static int exitreq_label;

static inline void gen_tb_start(TranslationBlock *tb)
{
    TCGv_i32 count;
    TCGv_i32 flag;
    TCGv_i32 count, flag, imm;
    int i;

    exitreq_label = gen_new_label();
    flag = tcg_temp_new_i32();
@@ -21,16 +21,25 @@ static inline void gen_tb_start(TranslationBlock *tb)
    tcg_gen_brcondi_i32(TCG_COND_NE, flag, 0, exitreq_label);
    tcg_temp_free_i32(flag);

    if (!(tb->cflags & CF_USE_ICOUNT))
    if (!(tb->cflags & CF_USE_ICOUNT)) {
        return;
    }

    icount_label = gen_new_label();
    count = tcg_temp_local_new_i32();
    tcg_gen_ld_i32(count, cpu_env,
                   -ENV_OFFSET + offsetof(CPUState, icount_decr.u32));

    imm = tcg_temp_new_i32();
    tcg_gen_movi_i32(imm, 0xdeadbeef);

    /* This is a horrid hack to allow fixing up the value later.  */
    icount_arg = tcg_ctx.gen_opparam_ptr + 1;
    tcg_gen_subi_i32(count, count, 0xdeadbeef);
    i = tcg_ctx.gen_last_op_idx;
    i = tcg_ctx.gen_op_buf[i].args;
    icount_arg = &tcg_ctx.gen_opparam_buf[i + 1];

    tcg_gen_sub_i32(count, count, imm);
    tcg_temp_free_i32(imm);

    tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label);
    tcg_gen_st16_i32(count, cpu_env,
@@ -49,7 +58,8 @@ static void gen_tb_end(TranslationBlock *tb, int num_insns)
        tcg_gen_exit_tb((uintptr_t)tb + TB_EXIT_ICOUNT_EXPIRED);
    }

    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
    /* Terminate the linked list.  */
    tcg_ctx.gen_op_buf[tcg_ctx.gen_last_op_idx].next = -1;
}

static inline void gen_io_start(void)
+116 −170
Original line number Diff line number Diff line
@@ -162,13 +162,13 @@ static bool temps_are_copies(TCGArg arg1, TCGArg arg2)
    return false;
}

static void tcg_opt_gen_mov(TCGContext *s, int op_index, TCGArg *gen_args,
static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg *args,
                            TCGOpcode old_op, TCGArg dst, TCGArg src)
{
    TCGOpcode new_op = op_to_mov(old_op);
    tcg_target_ulong mask;

    s->gen_opc_buf[op_index] = new_op;
    op->opc = new_op;

    reset_temp(dst);
    mask = temps[src].mask;
@@ -193,17 +193,17 @@ static void tcg_opt_gen_mov(TCGContext *s, int op_index, TCGArg *gen_args,
        temps[src].next_copy = dst;
    }

    gen_args[0] = dst;
    gen_args[1] = src;
    args[0] = dst;
    args[1] = src;
}

static void tcg_opt_gen_movi(TCGContext *s, int op_index, TCGArg *gen_args,
static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg *args,
                             TCGOpcode old_op, TCGArg dst, TCGArg val)
{
    TCGOpcode new_op = op_to_movi(old_op);
    tcg_target_ulong mask;

    s->gen_opc_buf[op_index] = new_op;
    op->opc = new_op;

    reset_temp(dst);
    temps[dst].state = TCG_TEMP_CONST;
@@ -215,8 +215,8 @@ static void tcg_opt_gen_movi(TCGContext *s, int op_index, TCGArg *gen_args,
    }
    temps[dst].mask = mask;

    gen_args[0] = dst;
    gen_args[1] = val;
    args[0] = dst;
    args[1] = val;
}

static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
@@ -533,11 +533,9 @@ static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
}

/* Propagate constants and copies, fold constant expressions. */
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                                    TCGArg *args, TCGOpDef *tcg_op_defs)
static void tcg_constant_folding(TCGContext *s)
{
    int nb_ops, op_index, nb_temps, nb_globals;
    TCGArg *gen_args;
    int oi, oi_next, nb_temps, nb_globals;

    /* Array VALS has an element for each temp.
       If this temp holds a constant then its value is kept in VALS' element.
@@ -548,24 +546,23 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
    nb_globals = s->nb_globals;
    reset_all_temps(nb_temps);

    nb_ops = tcg_opc_ptr - s->gen_opc_buf;
    gen_args = args;
    for (op_index = 0; op_index < nb_ops; op_index++) {
        TCGOpcode op = s->gen_opc_buf[op_index];
        const TCGOpDef *def = &tcg_op_defs[op];
    for (oi = s->gen_first_op_idx; oi >= 0; oi = oi_next) {
        tcg_target_ulong mask, partmask, affected;
        int nb_oargs, nb_iargs, nb_args, i;
        int nb_oargs, nb_iargs, i;
        TCGArg tmp;

        if (op == INDEX_op_call) {
            *gen_args++ = tmp = *args++;
            nb_oargs = tmp >> 16;
            nb_iargs = tmp & 0xffff;
            nb_args = nb_oargs + nb_iargs + def->nb_cargs;
        TCGOp * const op = &s->gen_op_buf[oi];
        TCGArg * const args = &s->gen_opparam_buf[op->args];
        TCGOpcode opc = op->opc;
        const TCGOpDef *def = &tcg_op_defs[opc];

        oi_next = op->next;
        if (opc == INDEX_op_call) {
            nb_oargs = op->callo;
            nb_iargs = op->calli;
        } else {
            nb_oargs = def->nb_oargs;
            nb_iargs = def->nb_iargs;
            nb_args = def->nb_args;
        }

        /* Do copy propagation */
@@ -576,7 +573,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
        }

        /* For commutative operations make constant second argument */
        switch (op) {
        switch (opc) {
        CASE_OP_32_64(add):
        CASE_OP_32_64(mul):
        CASE_OP_32_64(and):
@@ -634,7 +631,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,

        /* Simplify expressions for "shift/rot r, 0, a => movi r, 0",
           and "sub r, 0, a => neg r, a" case.  */
        switch (op) {
        switch (opc) {
        CASE_OP_32_64(shl):
        CASE_OP_32_64(shr):
        CASE_OP_32_64(sar):
@@ -642,9 +639,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
        CASE_OP_32_64(rotr):
            if (temps[args[1]].state == TCG_TEMP_CONST
                && temps[args[1]].val == 0) {
                tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], 0);
                args += 3;
                gen_args += 2;
                tcg_opt_gen_movi(s, op, args, opc, args[0], 0);
                continue;
            }
            break;
@@ -657,7 +652,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                    /* Proceed with possible constant folding. */
                    break;
                }
                if (op == INDEX_op_sub_i32) {
                if (opc == INDEX_op_sub_i32) {
                    neg_op = INDEX_op_neg_i32;
                    have_neg = TCG_TARGET_HAS_neg_i32;
                } else {
@@ -669,12 +664,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                }
                if (temps[args[1]].state == TCG_TEMP_CONST
                    && temps[args[1]].val == 0) {
                    s->gen_opc_buf[op_index] = neg_op;
                    op->opc = neg_op;
                    reset_temp(args[0]);
                    gen_args[0] = args[0];
                    gen_args[1] = args[2];
                    args += 3;
                    gen_args += 2;
                    args[1] = args[2];
                    continue;
                }
            }
@@ -728,12 +720,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                if (!have_not) {
                    break;
                }
                s->gen_opc_buf[op_index] = not_op;
                op->opc = not_op;
                reset_temp(args[0]);
                gen_args[0] = args[0];
                gen_args[1] = args[i];
                args += 3;
                gen_args += 2;
                args[1] = args[i];
                continue;
            }
        default:
@@ -741,7 +730,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
        }

        /* Simplify expression for "op r, a, const => mov r, a" cases */
        switch (op) {
        switch (opc) {
        CASE_OP_32_64(add):
        CASE_OP_32_64(sub):
        CASE_OP_32_64(shl):
@@ -769,12 +758,10 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
            break;
        do_mov3:
            if (temps_are_copies(args[0], args[1])) {
                s->gen_opc_buf[op_index] = INDEX_op_nop;
                op->opc = INDEX_op_nop;
            } else {
                tcg_opt_gen_mov(s, op_index, gen_args, op, args[0], args[1]);
                gen_args += 2;
                tcg_opt_gen_mov(s, op, args, opc, args[0], args[1]);
            }
            args += 3;
            continue;
        default:
            break;
@@ -784,7 +771,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
           output argument is supported. */
        mask = -1;
        affected = -1;
        switch (op) {
        switch (opc) {
        CASE_OP_32_64(ext8s):
            if ((temps[args[1]].mask & 0x80) != 0) {
                break;
@@ -923,38 +910,31 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,

        if (partmask == 0) {
            assert(nb_oargs == 1);
            tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], 0);
            args += nb_args;
            gen_args += 2;
            tcg_opt_gen_movi(s, op, args, opc, args[0], 0);
            continue;
        }
        if (affected == 0) {
            assert(nb_oargs == 1);
            if (temps_are_copies(args[0], args[1])) {
                s->gen_opc_buf[op_index] = INDEX_op_nop;
                op->opc = INDEX_op_nop;
            } else if (temps[args[1]].state != TCG_TEMP_CONST) {
                tcg_opt_gen_mov(s, op_index, gen_args, op, args[0], args[1]);
                gen_args += 2;
                tcg_opt_gen_mov(s, op, args, opc, args[0], args[1]);
            } else {
                tcg_opt_gen_movi(s, op_index, gen_args, op,
                tcg_opt_gen_movi(s, op, args, opc,
                                 args[0], temps[args[1]].val);
                gen_args += 2;
            }
            args += nb_args;
            continue;
        }

        /* Simplify expression for "op r, a, 0 => movi r, 0" cases */
        switch (op) {
        switch (opc) {
        CASE_OP_32_64(and):
        CASE_OP_32_64(mul):
        CASE_OP_32_64(muluh):
        CASE_OP_32_64(mulsh):
            if ((temps[args[2]].state == TCG_TEMP_CONST
                && temps[args[2]].val == 0)) {
                tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], 0);
                args += 3;
                gen_args += 2;
                tcg_opt_gen_movi(s, op, args, opc, args[0], 0);
                continue;
            }
            break;
@@ -963,18 +943,15 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
        }

        /* Simplify expression for "op r, a, a => mov r, a" cases */
        switch (op) {
        switch (opc) {
        CASE_OP_32_64(or):
        CASE_OP_32_64(and):
            if (temps_are_copies(args[1], args[2])) {
                if (temps_are_copies(args[0], args[1])) {
                    s->gen_opc_buf[op_index] = INDEX_op_nop;
                    op->opc = INDEX_op_nop;
                } else {
                    tcg_opt_gen_mov(s, op_index, gen_args, op,
                                    args[0], args[1]);
                    gen_args += 2;
                    tcg_opt_gen_mov(s, op, args, opc, args[0], args[1]);
                }
                args += 3;
                continue;
            }
            break;
@@ -983,14 +960,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
        }

        /* Simplify expression for "op r, a, a => movi r, 0" cases */
        switch (op) {
        switch (opc) {
        CASE_OP_32_64(andc):
        CASE_OP_32_64(sub):
        CASE_OP_32_64(xor):
            if (temps_are_copies(args[1], args[2])) {
                tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], 0);
                gen_args += 2;
                args += 3;
                tcg_opt_gen_movi(s, op, args, opc, args[0], 0);
                continue;
            }
            break;
@@ -1001,17 +976,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
        /* Propagate constants through copy operations and do constant
           folding.  Constants will be substituted to arguments by register
           allocator where needed and possible.  Also detect copies. */
        switch (op) {
        switch (opc) {
        CASE_OP_32_64(mov):
            if (temps_are_copies(args[0], args[1])) {
                args += 2;
                s->gen_opc_buf[op_index] = INDEX_op_nop;
                op->opc = INDEX_op_nop;
                break;
            }
            if (temps[args[1]].state != TCG_TEMP_CONST) {
                tcg_opt_gen_mov(s, op_index, gen_args, op, args[0], args[1]);
                gen_args += 2;
                args += 2;
                tcg_opt_gen_mov(s, op, args, opc, args[0], args[1]);
                break;
            }
            /* Source argument is constant.  Rewrite the operation and
@@ -1019,9 +991,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
            args[1] = temps[args[1]].val;
            /* fallthrough */
        CASE_OP_32_64(movi):
            tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], args[1]);
            gen_args += 2;
            args += 2;
            tcg_opt_gen_movi(s, op, args, opc, args[0], args[1]);
            break;

        CASE_OP_32_64(not):
@@ -1033,20 +1003,16 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
        case INDEX_op_ext32s_i64:
        case INDEX_op_ext32u_i64:
            if (temps[args[1]].state == TCG_TEMP_CONST) {
                tmp = do_constant_folding(op, temps[args[1]].val, 0);
                tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp);
                gen_args += 2;
                args += 2;
                tmp = do_constant_folding(opc, temps[args[1]].val, 0);
                tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
                break;
            }
            goto do_default;

        case INDEX_op_trunc_shr_i32:
            if (temps[args[1]].state == TCG_TEMP_CONST) {
                tmp = do_constant_folding(op, temps[args[1]].val, args[2]);
                tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp);
                gen_args += 2;
                args += 3;
                tmp = do_constant_folding(opc, temps[args[1]].val, args[2]);
                tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
                break;
            }
            goto do_default;
@@ -1075,11 +1041,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
        CASE_OP_32_64(remu):
            if (temps[args[1]].state == TCG_TEMP_CONST
                && temps[args[2]].state == TCG_TEMP_CONST) {
                tmp = do_constant_folding(op, temps[args[1]].val,
                tmp = do_constant_folding(opc, temps[args[1]].val,
                                          temps[args[2]].val);
                tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp);
                gen_args += 2;
                args += 3;
                tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
                break;
            }
            goto do_default;
@@ -1089,54 +1053,44 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                && temps[args[2]].state == TCG_TEMP_CONST) {
                tmp = deposit64(temps[args[1]].val, args[3], args[4],
                                temps[args[2]].val);
                tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp);
                gen_args += 2;
                args += 5;
                tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
                break;
            }
            goto do_default;

        CASE_OP_32_64(setcond):
            tmp = do_constant_folding_cond(op, args[1], args[2], args[3]);
            tmp = do_constant_folding_cond(opc, args[1], args[2], args[3]);
            if (tmp != 2) {
                tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp);
                gen_args += 2;
                args += 4;
                tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
                break;
            }
            goto do_default;

        CASE_OP_32_64(brcond):
            tmp = do_constant_folding_cond(op, args[0], args[1], args[2]);
            tmp = do_constant_folding_cond(opc, args[0], args[1], args[2]);
            if (tmp != 2) {
                if (tmp) {
                    reset_all_temps(nb_temps);
                    s->gen_opc_buf[op_index] = INDEX_op_br;
                    gen_args[0] = args[3];
                    gen_args += 1;
                    op->opc = INDEX_op_br;
                    args[0] = args[3];
                } else {
                    s->gen_opc_buf[op_index] = INDEX_op_nop;
                    op->opc = INDEX_op_nop;
                }
                args += 4;
                break;
            }
            goto do_default;

        CASE_OP_32_64(movcond):
            tmp = do_constant_folding_cond(op, args[1], args[2], args[5]);
            tmp = do_constant_folding_cond(opc, args[1], args[2], args[5]);
            if (tmp != 2) {
                if (temps_are_copies(args[0], args[4-tmp])) {
                    s->gen_opc_buf[op_index] = INDEX_op_nop;
                    op->opc = INDEX_op_nop;
                } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) {
                    tcg_opt_gen_movi(s, op_index, gen_args, op,
                    tcg_opt_gen_movi(s, op, args, opc,
                                     args[0], temps[args[4-tmp]].val);
                    gen_args += 2;
                } else {
                    tcg_opt_gen_mov(s, op_index, gen_args, op,
                                    args[0], args[4-tmp]);
                    gen_args += 2;
                    tcg_opt_gen_mov(s, op, args, opc, args[0], args[4-tmp]);
                }
                args += 6;
                break;
            }
            goto do_default;
@@ -1154,24 +1108,31 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                uint64_t a = ((uint64_t)ah << 32) | al;
                uint64_t b = ((uint64_t)bh << 32) | bl;
                TCGArg rl, rh;
                TCGOp *op2;
                TCGArg *args2;

                if (op == INDEX_op_add2_i32) {
                if (opc == INDEX_op_add2_i32) {
                    a += b;
                } else {
                    a -= b;
                }

                /* We emit the extra nop when we emit the add2/sub2.  */
                assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
                op2 = &s->gen_op_buf[oi_next];
                assert(op2->opc == INDEX_op_nop);

                /* But we still have to allocate args for the op.  */
                op2->args = s->gen_next_parm_idx;
                s->gen_next_parm_idx += 2;
                args2 = &s->gen_opparam_buf[op2->args];

                rl = args[0];
                rh = args[1];
                tcg_opt_gen_movi(s, op_index, &gen_args[0],
                                 op, rl, (uint32_t)a);
                tcg_opt_gen_movi(s, ++op_index, &gen_args[2],
                                 op, rh, (uint32_t)(a >> 32));
                gen_args += 4;
                args += 6;
                tcg_opt_gen_movi(s, op, args, opc, rl, (uint32_t)a);
                tcg_opt_gen_movi(s, op2, args2, opc, rh, (uint32_t)(a >> 32));

                /* We've done all we need to do with the movi.  Skip it.  */
                oi_next = op2->next;
                break;
            }
            goto do_default;
@@ -1183,18 +1144,25 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                uint32_t b = temps[args[3]].val;
                uint64_t r = (uint64_t)a * b;
                TCGArg rl, rh;
                TCGOp *op2;
                TCGArg *args2;

                /* We emit the extra nop when we emit the mulu2.  */
                assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
                op2 = &s->gen_op_buf[oi_next];
                assert(op2->opc == INDEX_op_nop);

                /* But we still have to allocate args for the op.  */
                op2->args = s->gen_next_parm_idx;
                s->gen_next_parm_idx += 2;
                args2 = &s->gen_opparam_buf[op2->args];

                rl = args[0];
                rh = args[1];
                tcg_opt_gen_movi(s, op_index, &gen_args[0],
                                 op, rl, (uint32_t)r);
                tcg_opt_gen_movi(s, ++op_index, &gen_args[2],
                                 op, rh, (uint32_t)(r >> 32));
                gen_args += 4;
                args += 4;
                tcg_opt_gen_movi(s, op, args, opc, rl, (uint32_t)r);
                tcg_opt_gen_movi(s, op2, args2, opc, rh, (uint32_t)(r >> 32));

                /* We've done all we need to do with the movi.  Skip it.  */
                oi_next = op2->next;
                break;
            }
            goto do_default;
@@ -1205,12 +1173,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                if (tmp) {
            do_brcond_true:
                    reset_all_temps(nb_temps);
                    s->gen_opc_buf[op_index] = INDEX_op_br;
                    gen_args[0] = args[5];
                    gen_args += 1;
                    op->opc = INDEX_op_br;
                    args[0] = args[5];
                } else {
            do_brcond_false:
                    s->gen_opc_buf[op_index] = INDEX_op_nop;
                    op->opc = INDEX_op_nop;
                }
            } else if ((args[4] == TCG_COND_LT || args[4] == TCG_COND_GE)
                       && temps[args[2]].state == TCG_TEMP_CONST
@@ -1221,12 +1188,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                   vs the high word of the input.  */
            do_brcond_high:
                reset_all_temps(nb_temps);
                s->gen_opc_buf[op_index] = INDEX_op_brcond_i32;
                gen_args[0] = args[1];
                gen_args[1] = args[3];
                gen_args[2] = args[4];
                gen_args[3] = args[5];
                gen_args += 4;
                op->opc = INDEX_op_brcond_i32;
                args[0] = args[1];
                args[1] = args[3];
                args[2] = args[4];
                args[3] = args[5];
            } else if (args[4] == TCG_COND_EQ) {
                /* Simplify EQ comparisons where one of the pairs
                   can be simplified.  */
@@ -1246,12 +1212,10 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                }
            do_brcond_low:
                reset_all_temps(nb_temps);
                s->gen_opc_buf[op_index] = INDEX_op_brcond_i32;
                gen_args[0] = args[0];
                gen_args[1] = args[2];
                gen_args[2] = args[4];
                gen_args[3] = args[5];
                gen_args += 4;
                op->opc = INDEX_op_brcond_i32;
                args[1] = args[2];
                args[2] = args[4];
                args[3] = args[5];
            } else if (args[4] == TCG_COND_NE) {
                /* Simplify NE comparisons where one of the pairs
                   can be simplified.  */
@@ -1273,15 +1237,13 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
            } else {
                goto do_default;
            }
            args += 6;
            break;

        case INDEX_op_setcond2_i32:
            tmp = do_constant_folding_cond2(&args[1], &args[3], args[5]);
            if (tmp != 2) {
            do_setcond_const:
                tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp);
                gen_args += 2;
                tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
            } else if ((args[5] == TCG_COND_LT || args[5] == TCG_COND_GE)
                       && temps[args[3]].state == TCG_TEMP_CONST
                       && temps[args[4]].state == TCG_TEMP_CONST
@@ -1290,14 +1252,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                /* Simplify LT/GE comparisons vs zero to a single compare
                   vs the high word of the input.  */
            do_setcond_high:
                s->gen_opc_buf[op_index] = INDEX_op_setcond_i32;
                reset_temp(args[0]);
                temps[args[0]].mask = 1;
                gen_args[0] = args[0];
                gen_args[1] = args[2];
                gen_args[2] = args[4];
                gen_args[3] = args[5];
                gen_args += 4;
                op->opc = INDEX_op_setcond_i32;
                args[1] = args[2];
                args[2] = args[4];
                args[3] = args[5];
            } else if (args[5] == TCG_COND_EQ) {
                /* Simplify EQ comparisons where one of the pairs
                   can be simplified.  */
@@ -1318,12 +1278,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
            do_setcond_low:
                reset_temp(args[0]);
                temps[args[0]].mask = 1;
                s->gen_opc_buf[op_index] = INDEX_op_setcond_i32;
                gen_args[0] = args[0];
                gen_args[1] = args[1];
                gen_args[2] = args[3];
                gen_args[3] = args[5];
                gen_args += 4;
                op->opc = INDEX_op_setcond_i32;
                args[2] = args[3];
                args[3] = args[5];
            } else if (args[5] == TCG_COND_NE) {
                /* Simplify NE comparisons where one of the pairs
                   can be simplified.  */
@@ -1345,7 +1302,6 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
            } else {
                goto do_default;
            }
            args += 6;
            break;

        case INDEX_op_call:
@@ -1377,22 +1333,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                    }
                }
            }
            for (i = 0; i < nb_args; i++) {
                gen_args[i] = args[i];
            }
            args += nb_args;
            gen_args += nb_args;
            break;
        }
    }

    return gen_args;
}

TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr,
        TCGArg *args, TCGOpDef *tcg_op_defs)
void tcg_optimize(TCGContext *s)
{
    TCGArg *res;
    res = tcg_constant_folding(s, tcg_opc_ptr, args, tcg_op_defs);
    return res;
    tcg_constant_folding(s);
}
+101 −89

File changed.

Preview size limit exceeded, changes collapsed.

+157 −219

File changed.

Preview size limit exceeded, changes collapsed.

+41 −17
Original line number Diff line number Diff line
@@ -448,10 +448,28 @@ typedef struct TCGTempSet {
    unsigned long l[BITS_TO_LONGS(TCG_MAX_TEMPS)];
} TCGTempSet;

typedef struct TCGOp {
    TCGOpcode opc   : 8;

    /* The number of out and in parameter for a call.  */
    unsigned callo  : 2;
    unsigned calli  : 6;

    /* Index of the arguments for this op, or -1 for zero-operand ops.  */
    signed args     : 16;

    /* Index of the prex/next op, or -1 for the end of the list.  */
    signed prev     : 16;
    signed next     : 16;
} TCGOp;

QEMU_BUILD_BUG_ON(NB_OPS > 0xff);
QEMU_BUILD_BUG_ON(OPC_BUF_SIZE >= 0x7fff);
QEMU_BUILD_BUG_ON(OPPARAM_BUF_SIZE >= 0x7fff);

struct TCGContext {
    uint8_t *pool_cur, *pool_end;
    TCGPool *pool_first, *pool_current, *pool_first_large;
    TCGLabel *labels;
    int nb_labels;
    int nb_globals;
    int nb_temps;
@@ -469,9 +487,6 @@ struct TCGContext {
                               corresponding output argument needs to be
                               sync to memory. */
    
    /* tells in which temporary a given register is. It does not take
       into account fixed registers */
    int reg_to_temp[TCG_TARGET_NB_REGS];
    TCGRegSet reserved_regs;
    intptr_t current_frame_offset;
    intptr_t frame_start;
@@ -479,8 +494,6 @@ struct TCGContext {
    int frame_reg;

    tcg_insn_unit *code_ptr;
    TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */
    TCGTempSet free_temps[TCG_TYPE_COUNT * 2];

    GHashTable *helpers;

@@ -508,14 +521,10 @@ struct TCGContext {
    int goto_tb_issue_mask;
#endif

    uint16_t gen_opc_buf[OPC_BUF_SIZE];
    TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE];

    uint16_t *gen_opc_ptr;
    TCGArg *gen_opparam_ptr;
    target_ulong gen_opc_pc[OPC_BUF_SIZE];
    uint16_t gen_opc_icount[OPC_BUF_SIZE];
    uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
    int gen_first_op_idx;
    int gen_last_op_idx;
    int gen_next_op_idx;
    int gen_next_parm_idx;

    /* Code generation.  Note that we specifically do not use tcg_insn_unit
       here, because there's too much arithmetic throughout that relies
@@ -533,6 +542,22 @@ struct TCGContext {

    /* The TCGBackendData structure is private to tcg-target.c.  */
    struct TCGBackendData *be;

    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];

    TCGOp gen_op_buf[OPC_BUF_SIZE];
    TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE];

    target_ulong gen_opc_pc[OPC_BUF_SIZE];
    uint16_t gen_opc_icount[OPC_BUF_SIZE];
    uint8_t gen_opc_instr_start[OPC_BUF_SIZE];

    TCGLabel labels[TCG_MAX_LABELS];
};

extern TCGContext tcg_ctx;
@@ -540,7 +565,7 @@ extern TCGContext tcg_ctx;
/* The number of opcodes emitted so far.  */
static inline int tcg_op_buf_count(void)
{
    return tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
    return tcg_ctx.gen_next_op_idx;
}

/* Test for whether to terminate the TB for using too many opcodes.  */
@@ -718,8 +743,7 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs);
void tcg_gen_callN(TCGContext *s, void *func,
                   TCGArg ret, int nargs, TCGArg *args);

TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr, TCGArg *args,
                     TCGOpDef *tcg_op_def);
void tcg_optimize(TCGContext *s);

/* only used for debugging purposes */
void tcg_dump_ops(TCGContext *s);