tcg/optimize: Rename "mask" to "z_mask"

Prepare for tracking different masks by renaming this one.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Luis Pires <luis.pires@eldorado.org.br>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2021-08-23 13:07:49 -07:00
parent 023462978a
commit b1fde411d0
1 changed files with 72 additions and 70 deletions

View File

@ -41,7 +41,7 @@ typedef struct TempOptInfo {
TCGTemp *prev_copy; TCGTemp *prev_copy;
TCGTemp *next_copy; TCGTemp *next_copy;
uint64_t val; uint64_t val;
uint64_t mask; uint64_t z_mask; /* mask bit is 0 if and only if value bit is 0 */
} TempOptInfo; } TempOptInfo;
static inline TempOptInfo *ts_info(TCGTemp *ts) static inline TempOptInfo *ts_info(TCGTemp *ts)
@ -81,7 +81,7 @@ static void reset_ts(TCGTemp *ts)
ti->next_copy = ts; ti->next_copy = ts;
ti->prev_copy = ts; ti->prev_copy = ts;
ti->is_const = false; ti->is_const = false;
ti->mask = -1; ti->z_mask = -1;
} }
static void reset_temp(TCGArg arg) static void reset_temp(TCGArg arg)
@ -111,14 +111,14 @@ static void init_ts_info(TCGTempSet *temps_used, TCGTemp *ts)
if (ts->kind == TEMP_CONST) { if (ts->kind == TEMP_CONST) {
ti->is_const = true; ti->is_const = true;
ti->val = ts->val; ti->val = ts->val;
ti->mask = ts->val; ti->z_mask = ts->val;
if (TCG_TARGET_REG_BITS > 32 && ts->type == TCG_TYPE_I32) { if (TCG_TARGET_REG_BITS > 32 && ts->type == TCG_TYPE_I32) {
/* High bits of a 32-bit quantity are garbage. */ /* High bits of a 32-bit quantity are garbage. */
ti->mask |= ~0xffffffffull; ti->z_mask |= ~0xffffffffull;
} }
} else { } else {
ti->is_const = false; ti->is_const = false;
ti->mask = -1; ti->z_mask = -1;
} }
} }
@ -186,7 +186,7 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg src)
const TCGOpDef *def; const TCGOpDef *def;
TempOptInfo *di; TempOptInfo *di;
TempOptInfo *si; TempOptInfo *si;
uint64_t mask; uint64_t z_mask;
TCGOpcode new_op; TCGOpcode new_op;
if (ts_are_copies(dst_ts, src_ts)) { if (ts_are_copies(dst_ts, src_ts)) {
@ -210,12 +210,12 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg src)
op->args[0] = dst; op->args[0] = dst;
op->args[1] = src; op->args[1] = src;
mask = si->mask; z_mask = si->z_mask;
if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) { if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) {
/* High bits of the destination are now garbage. */ /* High bits of the destination are now garbage. */
mask |= ~0xffffffffull; z_mask |= ~0xffffffffull;
} }
di->mask = mask; di->z_mask = z_mask;
if (src_ts->type == dst_ts->type) { if (src_ts->type == dst_ts->type) {
TempOptInfo *ni = ts_info(si->next_copy); TempOptInfo *ni = ts_info(si->next_copy);
@ -621,7 +621,7 @@ void tcg_optimize(TCGContext *s)
} }
QTAILQ_FOREACH_SAFE(op, &s->ops, link, op_next) { QTAILQ_FOREACH_SAFE(op, &s->ops, link, op_next) {
uint64_t mask, partmask, affected, tmp; uint64_t z_mask, partmask, affected, tmp;
int nb_oargs, nb_iargs; int nb_oargs, nb_iargs;
TCGOpcode opc = op->opc; TCGOpcode opc = op->opc;
const TCGOpDef *def = &tcg_op_defs[opc]; const TCGOpDef *def = &tcg_op_defs[opc];
@ -855,170 +855,172 @@ void tcg_optimize(TCGContext *s)
/* Simplify using known-zero bits. Currently only ops with a single /* Simplify using known-zero bits. Currently only ops with a single
output argument is supported. */ output argument is supported. */
mask = -1; z_mask = -1;
affected = -1; affected = -1;
switch (opc) { switch (opc) {
CASE_OP_32_64(ext8s): CASE_OP_32_64(ext8s):
if ((arg_info(op->args[1])->mask & 0x80) != 0) { if ((arg_info(op->args[1])->z_mask & 0x80) != 0) {
break; break;
} }
QEMU_FALLTHROUGH; QEMU_FALLTHROUGH;
CASE_OP_32_64(ext8u): CASE_OP_32_64(ext8u):
mask = 0xff; z_mask = 0xff;
goto and_const; goto and_const;
CASE_OP_32_64(ext16s): CASE_OP_32_64(ext16s):
if ((arg_info(op->args[1])->mask & 0x8000) != 0) { if ((arg_info(op->args[1])->z_mask & 0x8000) != 0) {
break; break;
} }
QEMU_FALLTHROUGH; QEMU_FALLTHROUGH;
CASE_OP_32_64(ext16u): CASE_OP_32_64(ext16u):
mask = 0xffff; z_mask = 0xffff;
goto and_const; goto and_const;
case INDEX_op_ext32s_i64: case INDEX_op_ext32s_i64:
if ((arg_info(op->args[1])->mask & 0x80000000) != 0) { if ((arg_info(op->args[1])->z_mask & 0x80000000) != 0) {
break; break;
} }
QEMU_FALLTHROUGH; QEMU_FALLTHROUGH;
case INDEX_op_ext32u_i64: case INDEX_op_ext32u_i64:
mask = 0xffffffffU; z_mask = 0xffffffffU;
goto and_const; goto and_const;
CASE_OP_32_64(and): CASE_OP_32_64(and):
mask = arg_info(op->args[2])->mask; z_mask = arg_info(op->args[2])->z_mask;
if (arg_is_const(op->args[2])) { if (arg_is_const(op->args[2])) {
and_const: and_const:
affected = arg_info(op->args[1])->mask & ~mask; affected = arg_info(op->args[1])->z_mask & ~z_mask;
} }
mask = arg_info(op->args[1])->mask & mask; z_mask = arg_info(op->args[1])->z_mask & z_mask;
break; break;
case INDEX_op_ext_i32_i64: case INDEX_op_ext_i32_i64:
if ((arg_info(op->args[1])->mask & 0x80000000) != 0) { if ((arg_info(op->args[1])->z_mask & 0x80000000) != 0) {
break; break;
} }
QEMU_FALLTHROUGH; QEMU_FALLTHROUGH;
case INDEX_op_extu_i32_i64: case INDEX_op_extu_i32_i64:
/* We do not compute affected as it is a size changing op. */ /* We do not compute affected as it is a size changing op. */
mask = (uint32_t)arg_info(op->args[1])->mask; z_mask = (uint32_t)arg_info(op->args[1])->z_mask;
break; break;
CASE_OP_32_64(andc): CASE_OP_32_64(andc):
/* Known-zeros does not imply known-ones. Therefore unless /* Known-zeros does not imply known-ones. Therefore unless
op->args[2] is constant, we can't infer anything from it. */ op->args[2] is constant, we can't infer anything from it. */
if (arg_is_const(op->args[2])) { if (arg_is_const(op->args[2])) {
mask = ~arg_info(op->args[2])->mask; z_mask = ~arg_info(op->args[2])->z_mask;
goto and_const; goto and_const;
} }
/* But we certainly know nothing outside args[1] may be set. */ /* But we certainly know nothing outside args[1] may be set. */
mask = arg_info(op->args[1])->mask; z_mask = arg_info(op->args[1])->z_mask;
break; break;
case INDEX_op_sar_i32: case INDEX_op_sar_i32:
if (arg_is_const(op->args[2])) { if (arg_is_const(op->args[2])) {
tmp = arg_info(op->args[2])->val & 31; tmp = arg_info(op->args[2])->val & 31;
mask = (int32_t)arg_info(op->args[1])->mask >> tmp; z_mask = (int32_t)arg_info(op->args[1])->z_mask >> tmp;
} }
break; break;
case INDEX_op_sar_i64: case INDEX_op_sar_i64:
if (arg_is_const(op->args[2])) { if (arg_is_const(op->args[2])) {
tmp = arg_info(op->args[2])->val & 63; tmp = arg_info(op->args[2])->val & 63;
mask = (int64_t)arg_info(op->args[1])->mask >> tmp; z_mask = (int64_t)arg_info(op->args[1])->z_mask >> tmp;
} }
break; break;
case INDEX_op_shr_i32: case INDEX_op_shr_i32:
if (arg_is_const(op->args[2])) { if (arg_is_const(op->args[2])) {
tmp = arg_info(op->args[2])->val & 31; tmp = arg_info(op->args[2])->val & 31;
mask = (uint32_t)arg_info(op->args[1])->mask >> tmp; z_mask = (uint32_t)arg_info(op->args[1])->z_mask >> tmp;
} }
break; break;
case INDEX_op_shr_i64: case INDEX_op_shr_i64:
if (arg_is_const(op->args[2])) { if (arg_is_const(op->args[2])) {
tmp = arg_info(op->args[2])->val & 63; tmp = arg_info(op->args[2])->val & 63;
mask = (uint64_t)arg_info(op->args[1])->mask >> tmp; z_mask = (uint64_t)arg_info(op->args[1])->z_mask >> tmp;
} }
break; break;
case INDEX_op_extrl_i64_i32: case INDEX_op_extrl_i64_i32:
mask = (uint32_t)arg_info(op->args[1])->mask; z_mask = (uint32_t)arg_info(op->args[1])->z_mask;
break; break;
case INDEX_op_extrh_i64_i32: case INDEX_op_extrh_i64_i32:
mask = (uint64_t)arg_info(op->args[1])->mask >> 32; z_mask = (uint64_t)arg_info(op->args[1])->z_mask >> 32;
break; break;
CASE_OP_32_64(shl): CASE_OP_32_64(shl):
if (arg_is_const(op->args[2])) { if (arg_is_const(op->args[2])) {
tmp = arg_info(op->args[2])->val & (TCG_TARGET_REG_BITS - 1); tmp = arg_info(op->args[2])->val & (TCG_TARGET_REG_BITS - 1);
mask = arg_info(op->args[1])->mask << tmp; z_mask = arg_info(op->args[1])->z_mask << tmp;
} }
break; break;
CASE_OP_32_64(neg): CASE_OP_32_64(neg):
/* Set to 1 all bits to the left of the rightmost. */ /* Set to 1 all bits to the left of the rightmost. */
mask = -(arg_info(op->args[1])->mask z_mask = -(arg_info(op->args[1])->z_mask
& -arg_info(op->args[1])->mask); & -arg_info(op->args[1])->z_mask);
break; break;
CASE_OP_32_64(deposit): CASE_OP_32_64(deposit):
mask = deposit64(arg_info(op->args[1])->mask, z_mask = deposit64(arg_info(op->args[1])->z_mask,
op->args[3], op->args[4], op->args[3], op->args[4],
arg_info(op->args[2])->mask); arg_info(op->args[2])->z_mask);
break; break;
CASE_OP_32_64(extract): CASE_OP_32_64(extract):
mask = extract64(arg_info(op->args[1])->mask, z_mask = extract64(arg_info(op->args[1])->z_mask,
op->args[2], op->args[3]); op->args[2], op->args[3]);
if (op->args[2] == 0) { if (op->args[2] == 0) {
affected = arg_info(op->args[1])->mask & ~mask; affected = arg_info(op->args[1])->z_mask & ~z_mask;
} }
break; break;
CASE_OP_32_64(sextract): CASE_OP_32_64(sextract):
mask = sextract64(arg_info(op->args[1])->mask, z_mask = sextract64(arg_info(op->args[1])->z_mask,
op->args[2], op->args[3]); op->args[2], op->args[3]);
if (op->args[2] == 0 && (tcg_target_long)mask >= 0) { if (op->args[2] == 0 && (tcg_target_long)z_mask >= 0) {
affected = arg_info(op->args[1])->mask & ~mask; affected = arg_info(op->args[1])->z_mask & ~z_mask;
} }
break; break;
CASE_OP_32_64(or): CASE_OP_32_64(or):
CASE_OP_32_64(xor): CASE_OP_32_64(xor):
mask = arg_info(op->args[1])->mask | arg_info(op->args[2])->mask; z_mask = arg_info(op->args[1])->z_mask
| arg_info(op->args[2])->z_mask;
break; break;
case INDEX_op_clz_i32: case INDEX_op_clz_i32:
case INDEX_op_ctz_i32: case INDEX_op_ctz_i32:
mask = arg_info(op->args[2])->mask | 31; z_mask = arg_info(op->args[2])->z_mask | 31;
break; break;
case INDEX_op_clz_i64: case INDEX_op_clz_i64:
case INDEX_op_ctz_i64: case INDEX_op_ctz_i64:
mask = arg_info(op->args[2])->mask | 63; z_mask = arg_info(op->args[2])->z_mask | 63;
break; break;
case INDEX_op_ctpop_i32: case INDEX_op_ctpop_i32:
mask = 32 | 31; z_mask = 32 | 31;
break; break;
case INDEX_op_ctpop_i64: case INDEX_op_ctpop_i64:
mask = 64 | 63; z_mask = 64 | 63;
break; break;
CASE_OP_32_64(setcond): CASE_OP_32_64(setcond):
case INDEX_op_setcond2_i32: case INDEX_op_setcond2_i32:
mask = 1; z_mask = 1;
break; break;
CASE_OP_32_64(movcond): CASE_OP_32_64(movcond):
mask = arg_info(op->args[3])->mask | arg_info(op->args[4])->mask; z_mask = arg_info(op->args[3])->z_mask
| arg_info(op->args[4])->z_mask;
break; break;
CASE_OP_32_64(ld8u): CASE_OP_32_64(ld8u):
mask = 0xff; z_mask = 0xff;
break; break;
CASE_OP_32_64(ld16u): CASE_OP_32_64(ld16u):
mask = 0xffff; z_mask = 0xffff;
break; break;
case INDEX_op_ld32u_i64: case INDEX_op_ld32u_i64:
mask = 0xffffffffu; z_mask = 0xffffffffu;
break; break;
CASE_OP_32_64(qemu_ld): CASE_OP_32_64(qemu_ld):
@ -1026,43 +1028,43 @@ void tcg_optimize(TCGContext *s)
MemOpIdx oi = op->args[nb_oargs + nb_iargs]; MemOpIdx oi = op->args[nb_oargs + nb_iargs];
MemOp mop = get_memop(oi); MemOp mop = get_memop(oi);
if (!(mop & MO_SIGN)) { if (!(mop & MO_SIGN)) {
mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1; z_mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1;
} }
} }
break; break;
CASE_OP_32_64(bswap16): CASE_OP_32_64(bswap16):
mask = arg_info(op->args[1])->mask; z_mask = arg_info(op->args[1])->z_mask;
if (mask <= 0xffff) { if (z_mask <= 0xffff) {
op->args[2] |= TCG_BSWAP_IZ; op->args[2] |= TCG_BSWAP_IZ;
} }
mask = bswap16(mask); z_mask = bswap16(z_mask);
switch (op->args[2] & (TCG_BSWAP_OZ | TCG_BSWAP_OS)) { switch (op->args[2] & (TCG_BSWAP_OZ | TCG_BSWAP_OS)) {
case TCG_BSWAP_OZ: case TCG_BSWAP_OZ:
break; break;
case TCG_BSWAP_OS: case TCG_BSWAP_OS:
mask = (int16_t)mask; z_mask = (int16_t)z_mask;
break; break;
default: /* undefined high bits */ default: /* undefined high bits */
mask |= MAKE_64BIT_MASK(16, 48); z_mask |= MAKE_64BIT_MASK(16, 48);
break; break;
} }
break; break;
case INDEX_op_bswap32_i64: case INDEX_op_bswap32_i64:
mask = arg_info(op->args[1])->mask; z_mask = arg_info(op->args[1])->z_mask;
if (mask <= 0xffffffffu) { if (z_mask <= 0xffffffffu) {
op->args[2] |= TCG_BSWAP_IZ; op->args[2] |= TCG_BSWAP_IZ;
} }
mask = bswap32(mask); z_mask = bswap32(z_mask);
switch (op->args[2] & (TCG_BSWAP_OZ | TCG_BSWAP_OS)) { switch (op->args[2] & (TCG_BSWAP_OZ | TCG_BSWAP_OS)) {
case TCG_BSWAP_OZ: case TCG_BSWAP_OZ:
break; break;
case TCG_BSWAP_OS: case TCG_BSWAP_OS:
mask = (int32_t)mask; z_mask = (int32_t)z_mask;
break; break;
default: /* undefined high bits */ default: /* undefined high bits */
mask |= MAKE_64BIT_MASK(32, 32); z_mask |= MAKE_64BIT_MASK(32, 32);
break; break;
} }
break; break;
@ -1074,9 +1076,9 @@ void tcg_optimize(TCGContext *s)
/* 32-bit ops generate 32-bit results. For the result is zero test /* 32-bit ops generate 32-bit results. For the result is zero test
below, we can ignore high bits, but for further optimizations we below, we can ignore high bits, but for further optimizations we
need to record that the high bits contain garbage. */ need to record that the high bits contain garbage. */
partmask = mask; partmask = z_mask;
if (!(def->flags & TCG_OPF_64BIT)) { if (!(def->flags & TCG_OPF_64BIT)) {
mask |= ~(tcg_target_ulong)0xffffffffu; z_mask |= ~(tcg_target_ulong)0xffffffffu;
partmask &= 0xffffffffu; partmask &= 0xffffffffu;
affected &= 0xffffffffu; affected &= 0xffffffffu;
} }
@ -1472,7 +1474,7 @@ void tcg_optimize(TCGContext *s)
vs the high word of the input. */ vs the high word of the input. */
do_setcond_high: do_setcond_high:
reset_temp(op->args[0]); reset_temp(op->args[0]);
arg_info(op->args[0])->mask = 1; arg_info(op->args[0])->z_mask = 1;
op->opc = INDEX_op_setcond_i32; op->opc = INDEX_op_setcond_i32;
op->args[1] = op->args[2]; op->args[1] = op->args[2];
op->args[2] = op->args[4]; op->args[2] = op->args[4];
@ -1498,7 +1500,7 @@ void tcg_optimize(TCGContext *s)
} }
do_setcond_low: do_setcond_low:
reset_temp(op->args[0]); reset_temp(op->args[0]);
arg_info(op->args[0])->mask = 1; arg_info(op->args[0])->z_mask = 1;
op->opc = INDEX_op_setcond_i32; op->opc = INDEX_op_setcond_i32;
op->args[2] = op->args[3]; op->args[2] = op->args[3];
op->args[3] = op->args[5]; op->args[3] = op->args[5];
@ -1543,7 +1545,7 @@ void tcg_optimize(TCGContext *s)
/* Default case: we know nothing about operation (or were unable /* Default case: we know nothing about operation (or were unable
to compute the operation result) so no propagation is done. to compute the operation result) so no propagation is done.
We trash everything if the operation is the end of a basic We trash everything if the operation is the end of a basic
block, otherwise we only trash the output args. "mask" is block, otherwise we only trash the output args. "z_mask" is
the non-zero bits mask for the first output arg. */ the non-zero bits mask for the first output arg. */
if (def->flags & TCG_OPF_BB_END) { if (def->flags & TCG_OPF_BB_END) {
memset(&temps_used, 0, sizeof(temps_used)); memset(&temps_used, 0, sizeof(temps_used));
@ -1554,7 +1556,7 @@ void tcg_optimize(TCGContext *s)
/* Save the corresponding known-zero bits mask for the /* Save the corresponding known-zero bits mask for the
first output argument (only one supported so far). */ first output argument (only one supported so far). */
if (i == 0) { if (i == 0) {
arg_info(op->args[i])->mask = mask; arg_info(op->args[i])->z_mask = z_mask;
} }
} }
} }