Commit b0411142 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20150609' into staging



Collected TCG patches

# gpg: Signature made Tue Jun  9 15:06:18 2015 BST using RSA key ID 4DD0279B
# gpg: Good signature from "Richard Henderson <rth7680@gmail.com>"
# gpg:                 aka "Richard Henderson <rth@redhat.com>"
# gpg:                 aka "Richard Henderson <rth@twiddle.net>"

* remotes/rth/tags/pull-tcg-20150609:
  tcg/optimize: rename tcg_constant_folding
  tcg/optimize: fold constant test in tcg_opt_gen_mov
  tcg/optimize: fold temp copies test in tcg_opt_gen_mov
  tcg/optimize: remove opc argument from tcg_opt_gen_mov
  tcg/optimize: remove opc argument from tcg_opt_gen_movi
  tcg: fix dead computation for repeated input arguments
  tcg: fix register allocation with two aliased dead inputs
  tcg: Handle MO_AMASK in tcg_dump_ops
  tcg: Mask TCGMemOp appropriately for indexing

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 44ee94e4 36e60ef6
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1004,7 +1004,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
    tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, oi);
    tcg_out_adr(s, TCG_REG_X3, lb->raddr);
    tcg_out_call(s, qemu_ld_helpers[opc & ~MO_SIGN]);
    tcg_out_call(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SIZE)]);
    if (opc & MO_SIGN) {
        tcg_out_sxt(s, lb->type, size, lb->datalo_reg, TCG_REG_X0);
    } else {
@@ -1027,7 +1027,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
    tcg_out_mov(s, size == MO_64, TCG_REG_X2, lb->datalo_reg);
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X3, oi);
    tcg_out_adr(s, TCG_REG_X4, lb->raddr);
    tcg_out_call(s, qemu_st_helpers[opc]);
    tcg_out_call(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
    tcg_out_goto(s, lb->raddr);
}

+3 −3
Original line number Diff line number Diff line
@@ -1260,9 +1260,9 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
       icache usage.  For pre-armv6, use the signed helpers since we do
       not have a single insn sign-extend.  */
    if (use_armv6_instructions) {
        func = qemu_ld_helpers[opc & ~MO_SIGN];
        func = qemu_ld_helpers[opc & (MO_BSWAP | MO_SIZE)];
    } else {
        func = qemu_ld_helpers[opc];
        func = qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)];
        if (opc & MO_SIGN) {
            opc = MO_UL;
        }
@@ -1337,7 +1337,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
    argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14);

    /* Tail-call to the helper, which will return to the fast path.  */
    tcg_out_goto(s, COND_AL, qemu_st_helpers[opc]);
    tcg_out_goto(s, COND_AL, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
}
#endif /* SOFTMMU */

+2 −2
Original line number Diff line number Diff line
@@ -1307,7 +1307,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
                     (uintptr_t)l->raddr);
    }

    tcg_out_call(s, qemu_ld_helpers[opc & ~MO_SIGN]);
    tcg_out_call(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SIZE)]);

    data_reg = l->datalo_reg;
    switch (opc & MO_SSIZE) {
@@ -1413,7 +1413,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)

    /* "Tail call" to the helper, with the return address back inline.  */
    tcg_out_push(s, retaddr);
    tcg_out_jmp(s, qemu_st_helpers[opc]);
    tcg_out_jmp(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
}
#elif defined(__x86_64__) && defined(__linux__)
# include <asm/prctl.h>
+2 −2
Original line number Diff line number Diff line
@@ -1031,7 +1031,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
    }
    i = tcg_out_call_iarg_imm(s, i, oi);
    i = tcg_out_call_iarg_imm(s, i, (intptr_t)l->raddr);
    tcg_out_call_int(s, qemu_ld_helpers[opc], false);
    tcg_out_call_int(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)], false);
    /* delay slot */
    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);

@@ -1094,7 +1094,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
       computation to take place in the return address register.  */
    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (intptr_t)l->raddr);
    i = tcg_out_call_iarg_reg(s, i, TCG_REG_RA);
    tcg_out_call_int(s, qemu_st_helpers[opc], true);
    tcg_out_call_int(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)], true);
    /* delay slot */
    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
}
+59 −90
Original line number Diff line number Diff line
@@ -193,10 +193,42 @@ static bool temps_are_copies(TCGArg arg1, TCGArg arg2)
    return false;
}

static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg *args,
                             TCGArg dst, TCGArg val)
{
    TCGOpcode new_op = op_to_movi(op->opc);
    tcg_target_ulong mask;

    op->opc = new_op;

    reset_temp(dst);
    temps[dst].state = TCG_TEMP_CONST;
    temps[dst].val = val;
    mask = val;
    if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) {
        /* High bits of the destination are now garbage.  */
        mask |= ~0xffffffffull;
    }
    temps[dst].mask = mask;

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

static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg *args,
                            TCGOpcode old_op, TCGArg dst, TCGArg src)
                            TCGArg dst, TCGArg src)
{
    TCGOpcode new_op = op_to_mov(old_op);
    if (temps_are_copies(dst, src)) {
        tcg_op_remove(s, op);
        return;
    }

    if (temps[src].state == TCG_TEMP_CONST) {
        tcg_opt_gen_movi(s, op, args, dst, temps[src].val);
        return;
    }

    TCGOpcode new_op = op_to_mov(op->opc);
    tcg_target_ulong mask;

    op->opc = new_op;
@@ -228,28 +260,6 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg *args,
    args[1] = src;
}

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;

    op->opc = new_op;

    reset_temp(dst);
    temps[dst].state = TCG_TEMP_CONST;
    temps[dst].val = val;
    mask = val;
    if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) {
        /* High bits of the destination are now garbage.  */
        mask |= ~0xffffffffull;
    }
    temps[dst].mask = mask;

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

static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
{
    uint64_t l64, h64;
@@ -564,7 +574,7 @@ static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
}

/* Propagate constants and copies, fold constant expressions. */
static void tcg_constant_folding(TCGContext *s)
void tcg_optimize(TCGContext *s)
{
    int oi, oi_next, nb_temps, nb_globals;

@@ -670,7 +680,7 @@ static void tcg_constant_folding(TCGContext *s)
        CASE_OP_32_64(rotr):
            if (temps[args[1]].state == TCG_TEMP_CONST
                && temps[args[1]].val == 0) {
                tcg_opt_gen_movi(s, op, args, opc, args[0], 0);
                tcg_opt_gen_movi(s, op, args, args[0], 0);
                continue;
            }
            break;
@@ -775,7 +785,8 @@ static void tcg_constant_folding(TCGContext *s)
            if (temps[args[1]].state != TCG_TEMP_CONST
                && temps[args[2]].state == TCG_TEMP_CONST
                && temps[args[2]].val == 0) {
                goto do_mov3;
                tcg_opt_gen_mov(s, op, args, args[0], args[1]);
                continue;
            }
            break;
        CASE_OP_32_64(and):
@@ -784,16 +795,10 @@ static void tcg_constant_folding(TCGContext *s)
            if (temps[args[1]].state != TCG_TEMP_CONST
                && temps[args[2]].state == TCG_TEMP_CONST
                && temps[args[2]].val == -1) {
                goto do_mov3;
                tcg_opt_gen_mov(s, op, args, args[0], args[1]);
                continue;
            }
            break;
        do_mov3:
            if (temps_are_copies(args[0], args[1])) {
                tcg_op_remove(s, op);
            } else {
                tcg_opt_gen_mov(s, op, args, opc, args[0], args[1]);
            }
            continue;
        default:
            break;
        }
@@ -942,19 +947,12 @@ static void tcg_constant_folding(TCGContext *s)

        if (partmask == 0) {
            assert(nb_oargs == 1);
            tcg_opt_gen_movi(s, op, args, opc, args[0], 0);
            tcg_opt_gen_movi(s, op, args, args[0], 0);
            continue;
        }
        if (affected == 0) {
            assert(nb_oargs == 1);
            if (temps_are_copies(args[0], args[1])) {
                tcg_op_remove(s, op);
            } else if (temps[args[1]].state != TCG_TEMP_CONST) {
                tcg_opt_gen_mov(s, op, args, opc, args[0], args[1]);
            } else {
                tcg_opt_gen_movi(s, op, args, opc,
                                 args[0], temps[args[1]].val);
            }
            tcg_opt_gen_mov(s, op, args, args[0], args[1]);
            continue;
        }

@@ -966,7 +964,7 @@ static void tcg_constant_folding(TCGContext *s)
        CASE_OP_32_64(mulsh):
            if ((temps[args[2]].state == TCG_TEMP_CONST
                && temps[args[2]].val == 0)) {
                tcg_opt_gen_movi(s, op, args, opc, args[0], 0);
                tcg_opt_gen_movi(s, op, args, args[0], 0);
                continue;
            }
            break;
@@ -979,14 +977,7 @@ static void tcg_constant_folding(TCGContext *s)
        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])) {
                    tcg_op_remove(s, op);
                } else if (temps[args[1]].state != TCG_TEMP_CONST) {
                    tcg_opt_gen_mov(s, op, args, opc, args[0], args[1]);
                } else {
                    tcg_opt_gen_movi(s, op, args, opc,
                                     args[0], temps[args[1]].val);
                }
                tcg_opt_gen_mov(s, op, args, args[0], args[1]);
                continue;
            }
            break;
@@ -1000,7 +991,7 @@ static void tcg_constant_folding(TCGContext *s)
        CASE_OP_32_64(sub):
        CASE_OP_32_64(xor):
            if (temps_are_copies(args[1], args[2])) {
                tcg_opt_gen_movi(s, op, args, opc, args[0], 0);
                tcg_opt_gen_movi(s, op, args, args[0], 0);
                continue;
            }
            break;
@@ -1013,20 +1004,10 @@ static void tcg_constant_folding(TCGContext *s)
           allocator where needed and possible.  Also detect copies. */
        switch (opc) {
        CASE_OP_32_64(mov):
            if (temps_are_copies(args[0], args[1])) {
                tcg_op_remove(s, op);
                break;
            }
            if (temps[args[1]].state != TCG_TEMP_CONST) {
                tcg_opt_gen_mov(s, op, args, opc, args[0], args[1]);
            tcg_opt_gen_mov(s, op, args, args[0], args[1]);
            break;
            }
            /* Source argument is constant.  Rewrite the operation and
               let movi case handle it. */
            args[1] = temps[args[1]].val;
            /* fallthrough */
        CASE_OP_32_64(movi):
            tcg_opt_gen_movi(s, op, args, opc, args[0], args[1]);
            tcg_opt_gen_movi(s, op, args, args[0], args[1]);
            break;

        CASE_OP_32_64(not):
@@ -1039,7 +1020,7 @@ static void tcg_constant_folding(TCGContext *s)
        case INDEX_op_ext32u_i64:
            if (temps[args[1]].state == TCG_TEMP_CONST) {
                tmp = do_constant_folding(opc, temps[args[1]].val, 0);
                tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
                tcg_opt_gen_movi(s, op, args, args[0], tmp);
                break;
            }
            goto do_default;
@@ -1047,7 +1028,7 @@ static void tcg_constant_folding(TCGContext *s)
        case INDEX_op_trunc_shr_i32:
            if (temps[args[1]].state == TCG_TEMP_CONST) {
                tmp = do_constant_folding(opc, temps[args[1]].val, args[2]);
                tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
                tcg_opt_gen_movi(s, op, args, args[0], tmp);
                break;
            }
            goto do_default;
@@ -1078,7 +1059,7 @@ static void tcg_constant_folding(TCGContext *s)
                && temps[args[2]].state == TCG_TEMP_CONST) {
                tmp = do_constant_folding(opc, temps[args[1]].val,
                                          temps[args[2]].val);
                tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
                tcg_opt_gen_movi(s, op, args, args[0], tmp);
                break;
            }
            goto do_default;
@@ -1088,7 +1069,7 @@ static void tcg_constant_folding(TCGContext *s)
                && 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, args, opc, args[0], tmp);
                tcg_opt_gen_movi(s, op, args, args[0], tmp);
                break;
            }
            goto do_default;
@@ -1096,7 +1077,7 @@ static void tcg_constant_folding(TCGContext *s)
        CASE_OP_32_64(setcond):
            tmp = do_constant_folding_cond(opc, args[1], args[2], args[3]);
            if (tmp != 2) {
                tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
                tcg_opt_gen_movi(s, op, args, args[0], tmp);
                break;
            }
            goto do_default;
@@ -1118,14 +1099,7 @@ static void tcg_constant_folding(TCGContext *s)
        CASE_OP_32_64(movcond):
            tmp = do_constant_folding_cond(opc, args[1], args[2], args[5]);
            if (tmp != 2) {
                if (temps_are_copies(args[0], args[4-tmp])) {
                    tcg_op_remove(s, op);
                } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) {
                    tcg_opt_gen_movi(s, op, args, opc,
                                     args[0], temps[args[4-tmp]].val);
                } else {
                    tcg_opt_gen_mov(s, op, args, opc, args[0], args[4-tmp]);
                }
                tcg_opt_gen_mov(s, op, args, args[0], args[4-tmp]);
                break;
            }
            goto do_default;
@@ -1154,8 +1128,8 @@ static void tcg_constant_folding(TCGContext *s)

                rl = args[0];
                rh = args[1];
                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));
                tcg_opt_gen_movi(s, op, args, rl, (uint32_t)a);
                tcg_opt_gen_movi(s, op2, args2, rh, (uint32_t)(a >> 32));

                /* We've done all we need to do with the movi.  Skip it.  */
                oi_next = op2->next;
@@ -1175,8 +1149,8 @@ static void tcg_constant_folding(TCGContext *s)

                rl = args[0];
                rh = args[1];
                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));
                tcg_opt_gen_movi(s, op, args, rl, (uint32_t)r);
                tcg_opt_gen_movi(s, op2, args2, rh, (uint32_t)(r >> 32));

                /* We've done all we need to do with the movi.  Skip it.  */
                oi_next = op2->next;
@@ -1260,7 +1234,7 @@ static void tcg_constant_folding(TCGContext *s)
            tmp = do_constant_folding_cond2(&args[1], &args[3], args[5]);
            if (tmp != 2) {
            do_setcond_const:
                tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
                tcg_opt_gen_movi(s, op, args, 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
@@ -1354,8 +1328,3 @@ static void tcg_constant_folding(TCGContext *s)
        }
    }
}

void tcg_optimize(TCGContext *s)
{
    tcg_constant_folding(s);
}
Loading