mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-05-08 17:52:13 +00:00
tcg: Synchronize with qemu
This commit is contained in:
parent
006a13026a
commit
3996153514
183
qemu/tcg/tcg.c
183
qemu/tcg/tcg.c
|
@ -2159,104 +2159,109 @@ static void liveness_pass_1(TCGContext *s)
|
||||||
goto do_not_remove;
|
goto do_not_remove;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
do_remove:
|
goto do_remove;
|
||||||
tcg_op_remove(s, op);
|
}
|
||||||
} else {
|
goto do_not_remove;
|
||||||
do_not_remove:
|
|
||||||
/* output args are dead */
|
|
||||||
for (i = 0; i < nb_oargs; i++) {
|
|
||||||
ts = arg_temp(op->args[i]);
|
|
||||||
|
|
||||||
/* Remember the preference of the uses that followed. */
|
do_remove:
|
||||||
op->output_pref[i] = *la_temp_pref(ts);
|
tcg_op_remove(s, op);
|
||||||
|
break;
|
||||||
|
|
||||||
/* Output args are dead. */
|
do_not_remove:
|
||||||
if (ts->state & TS_DEAD) {
|
for (i = 0; i < nb_oargs; i++) {
|
||||||
arg_life |= DEAD_ARG << i;
|
ts = arg_temp(op->args[i]);
|
||||||
}
|
|
||||||
if (ts->state & TS_MEM) {
|
/* Remember the preference of the uses that followed. */
|
||||||
arg_life |= SYNC_ARG << i;
|
op->output_pref[i] = *la_temp_pref(ts);
|
||||||
}
|
|
||||||
ts->state = TS_DEAD;
|
/* Output args are dead. */
|
||||||
la_reset_pref(s, ts);
|
if (ts->state & TS_DEAD) {
|
||||||
|
arg_life |= DEAD_ARG << i;
|
||||||
}
|
}
|
||||||
|
if (ts->state & TS_MEM) {
|
||||||
/* If end of basic block, update. */
|
arg_life |= SYNC_ARG << i;
|
||||||
if (def->flags & TCG_OPF_BB_END) {
|
|
||||||
// Unicorn: do not optimize dead temps on brcond,
|
|
||||||
// this causes problem because check_exit_request() inserts
|
|
||||||
// brcond instruction in the middle of the TB,
|
|
||||||
// which incorrectly flags end-of-block
|
|
||||||
if (opc != INDEX_op_brcond_i32) {
|
|
||||||
la_bb_end(s, nb_globals, nb_temps);
|
|
||||||
} else {
|
|
||||||
// Unicorn: we do not touch dead temps for brcond,
|
|
||||||
// but we should refresh TCG globals In-Memory states,
|
|
||||||
// otherwise, important CPU states(especially conditional flags) might be forgotten,
|
|
||||||
// result in wrongly generated host code that run into wrong branch.
|
|
||||||
// Refer to https://github.com/unicorn-engine/unicorn/issues/287 for further information
|
|
||||||
tcg_la_br_end(s);
|
|
||||||
}
|
|
||||||
} else if (def->flags & TCG_OPF_SIDE_EFFECTS) {
|
|
||||||
la_global_sync(s, nb_globals);
|
|
||||||
if (def->flags & TCG_OPF_CALL_CLOBBER) {
|
|
||||||
la_cross_call(s, nb_temps);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ts->state = TS_DEAD;
|
||||||
|
la_reset_pref(s, ts);
|
||||||
|
}
|
||||||
|
|
||||||
/* Record arguments that die in this opcode. */
|
/* If end of basic block, update. */
|
||||||
|
if (def->flags & TCG_OPF_BB_EXIT) {
|
||||||
|
la_func_end(s, nb_globals, nb_temps);
|
||||||
|
} else if (def->flags & TCG_OPF_BB_END) {
|
||||||
|
// Unicorn: do not optimize dead temps on brcond,
|
||||||
|
// this causes problem because check_exit_request() inserts
|
||||||
|
// brcond instruction in the middle of the TB,
|
||||||
|
// which incorrectly flags end-of-block
|
||||||
|
if (opc != INDEX_op_brcond_i32) {
|
||||||
|
la_bb_end(s, nb_globals, nb_temps);
|
||||||
|
} else {
|
||||||
|
// Unicorn: we do not touch dead temps for brcond,
|
||||||
|
// but we should refresh TCG globals In-Memory states,
|
||||||
|
// otherwise, important CPU states(especially conditional flags) might be forgotten,
|
||||||
|
// result in wrongly generated host code that run into wrong branch.
|
||||||
|
// Refer to https://github.com/unicorn-engine/unicorn/issues/287 for further information
|
||||||
|
tcg_la_br_end(s);
|
||||||
|
}
|
||||||
|
} else if (def->flags & TCG_OPF_SIDE_EFFECTS) {
|
||||||
|
la_global_sync(s, nb_globals);
|
||||||
|
if (def->flags & TCG_OPF_CALL_CLOBBER) {
|
||||||
|
la_cross_call(s, nb_temps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Record arguments that die in this opcode. */
|
||||||
|
for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
|
||||||
|
ts = arg_temp(op->args[i]);
|
||||||
|
if (ts->state & TS_DEAD) {
|
||||||
|
arg_life |= DEAD_ARG << i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Input arguments are live for preceding opcodes. */
|
||||||
|
for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
|
||||||
|
ts = arg_temp(op->args[i]);
|
||||||
|
if (ts->state & TS_DEAD) {
|
||||||
|
/* For operands that were dead, initially allow
|
||||||
|
all regs for the type. */
|
||||||
|
*la_temp_pref(ts) = s->tcg_target_available_regs[ts->type];
|
||||||
|
ts->state &= ~TS_DEAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Incorporate constraints for this operand. */
|
||||||
|
switch (opc) {
|
||||||
|
case INDEX_op_mov_i32:
|
||||||
|
case INDEX_op_mov_i64:
|
||||||
|
/* Note that these are TCG_OPF_NOT_PRESENT and do not
|
||||||
|
have proper constraints. That said, special case
|
||||||
|
moves to propagate preferences backward. */
|
||||||
|
if (IS_DEAD_ARG(1)) {
|
||||||
|
*la_temp_pref(arg_temp(op->args[0]))
|
||||||
|
= *la_temp_pref(arg_temp(op->args[1]));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
|
for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
|
||||||
|
const TCGArgConstraint *ct = &def->args_ct[i];
|
||||||
|
TCGRegSet set, *pset;
|
||||||
|
|
||||||
ts = arg_temp(op->args[i]);
|
ts = arg_temp(op->args[i]);
|
||||||
if (ts->state & TS_DEAD) {
|
pset = la_temp_pref(ts);
|
||||||
arg_life |= DEAD_ARG << i;
|
set = *pset;
|
||||||
|
|
||||||
|
set &= ct->u.regs;
|
||||||
|
if (ct->ct & TCG_CT_IALIAS) {
|
||||||
|
set &= op->output_pref[ct->alias_index];
|
||||||
}
|
}
|
||||||
|
/* If the combination is not possible, restart. */
|
||||||
|
if (set == 0) {
|
||||||
|
set = ct->u.regs;
|
||||||
|
}
|
||||||
|
*pset = set;
|
||||||
}
|
}
|
||||||
/* Input arguments are live for preceding opcodes. */
|
break;
|
||||||
for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
|
|
||||||
ts = arg_temp(op->args[i]);
|
|
||||||
if (ts->state & TS_DEAD) {
|
|
||||||
/* For operands that were dead, initially allow
|
|
||||||
all regs for the type. */
|
|
||||||
*la_temp_pref(ts) = s->tcg_target_available_regs[ts->type];
|
|
||||||
ts->state &= ~TS_DEAD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Incorporate constraints for this operand. */
|
|
||||||
switch (opc) {
|
|
||||||
case INDEX_op_mov_i32:
|
|
||||||
case INDEX_op_mov_i64:
|
|
||||||
/* Note that these are TCG_OPF_NOT_PRESENT and do not
|
|
||||||
have proper constraints. That said, special case
|
|
||||||
moves to propagate preferences backward. */
|
|
||||||
if (IS_DEAD_ARG(1)) {
|
|
||||||
*la_temp_pref(arg_temp(op->args[0]))
|
|
||||||
= *la_temp_pref(arg_temp(op->args[1]));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
|
|
||||||
const TCGArgConstraint *ct = &def->args_ct[i];
|
|
||||||
TCGRegSet set, *pset;
|
|
||||||
|
|
||||||
ts = arg_temp(op->args[i]);
|
|
||||||
pset = la_temp_pref(ts);
|
|
||||||
set = *pset;
|
|
||||||
|
|
||||||
set &= ct->u.regs;
|
|
||||||
if (ct->ct & TCG_CT_IALIAS) {
|
|
||||||
set &= op->output_pref[ct->alias_index];
|
|
||||||
}
|
|
||||||
/* If the combination is not possible, restart. */
|
|
||||||
if (set == 0) {
|
|
||||||
set = ct->u.regs;
|
|
||||||
}
|
|
||||||
*pset = set;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue