Jit: Fix "skip redundant flushes" for skipped instructions

Normally when an instruction is skipped (for instance due to branch
merging or BLR optimization), the registers that would have been flushed
at the end of that instruction will instead be flushed at the end of the
next instruction, which is maybe not perfect, but usually good enough.
However, since the addition of the "skip redundant flushes" logic in
fd511a689f, Dolphin has accidentally skipped flushing those registers,
which creates unnecessary register pressure. This commit restores the
old behavior.
This commit is contained in:
JosJuice
2024-05-29 21:37:58 +02:00
parent afdee595f6
commit acfba51b70
2 changed files with 34 additions and 11 deletions

View File

@@ -992,6 +992,11 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
IntializeSpeculativeConstants();
}
BitSet32 previous_gpr_in_use{};
BitSet32 previous_fpr_in_use{};
BitSet32 previous_gpr_will_be_written{};
BitSet32 previous_fpr_will_be_written{};
// Translate instructions
for (u32 i = 0; i < code_block.m_num_instructions; i++)
{
@@ -1233,12 +1238,17 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
gpr.Discard(op.gprDiscardable);
fpr.Discard(op.fprDiscardable);
}
gpr.Flush(~(op.gprWillBeRead | op.gprWillBeWritten) & (op.regsIn | op.regsOut),
gpr.Flush(~(op.gprWillBeRead | op.gprWillBeWritten) & previous_gpr_in_use,
RegCache::FlushMode::Full);
fpr.Flush(~(op.fprWillBeRead | op.fprWillBeWritten) & (op.fregsIn | op.GetFregsOut()),
fpr.Flush(~(op.fprWillBeRead | op.fprWillBeWritten) & previous_fpr_in_use,
RegCache::FlushMode::Full);
gpr.Flush(~op.gprWillBeWritten & op.regsOut, RegCache::FlushMode::Undirty);
fpr.Flush(~op.fprWillBeWritten & op.GetFregsOut(), RegCache::FlushMode::Undirty);
gpr.Flush(~op.gprWillBeWritten & previous_gpr_will_be_written, RegCache::FlushMode::Undirty);
fpr.Flush(~op.fprWillBeWritten & previous_fpr_will_be_written, RegCache::FlushMode::Undirty);
previous_gpr_in_use = op.gprWillBeRead | op.gprWillBeWritten;
previous_fpr_in_use = op.fprWillBeRead | op.fprWillBeWritten;
previous_gpr_will_be_written = op.gprWillBeWritten;
previous_fpr_will_be_written = op.fprWillBeWritten;
if (opinfo->flags & FL_LOADSTORE)
++js.numLoadStoreInst;

View File

@@ -1207,6 +1207,13 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
IntializeSpeculativeConstants();
}
BitSet32 previous_gpr_in_use{};
BitSet32 previous_fpr_in_use{};
BitSet8 previous_cr_in_use{};
BitSet32 previous_gpr_will_be_written{};
BitSet32 previous_fpr_will_be_written{};
BitSet8 previous_cr_will_be_written{};
// Translate instructions
for (u32 i = 0; i < code_block.m_num_instructions; i++)
{
@@ -1416,16 +1423,22 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
fpr.DiscardRegisters(op.fprDiscardable);
gpr.DiscardCRRegisters(op.crDiscardable);
}
gpr.FlushRegisters(~(op.gprWillBeRead | op.gprWillBeWritten) & (op.regsIn | op.regsOut),
gpr.FlushRegisters(~(op.gprWillBeRead | op.gprWillBeWritten) & previous_gpr_in_use,
FlushMode::Full);
fpr.FlushRegisters(~(op.fprWillBeRead | op.fprWillBeWritten) &
(op.fregsIn | op.GetFregsOut()),
fpr.FlushRegisters(~(op.fprWillBeRead | op.fprWillBeWritten) & previous_fpr_in_use,
FlushMode::Full);
gpr.FlushCRRegisters(~(op.crWillBeRead | op.crWillBeWritten) & (op.crIn | op.crOut),
gpr.FlushCRRegisters(~(op.crWillBeRead | op.crWillBeWritten) & previous_cr_in_use,
FlushMode::Full);
gpr.FlushRegisters(~op.gprWillBeWritten & op.regsOut, FlushMode::Undirty);
fpr.FlushRegisters(~op.fprWillBeWritten & op.GetFregsOut(), FlushMode::Undirty);
gpr.FlushCRRegisters(~op.crWillBeWritten & op.crOut, FlushMode::Undirty);
gpr.FlushRegisters(~op.gprWillBeWritten & previous_gpr_will_be_written, FlushMode::Undirty);
fpr.FlushRegisters(~op.fprWillBeWritten & previous_fpr_will_be_written, FlushMode::Undirty);
gpr.FlushCRRegisters(~op.crWillBeWritten & previous_cr_will_be_written, FlushMode::Undirty);
previous_gpr_in_use = op.gprWillBeRead | op.gprWillBeWritten;
previous_fpr_in_use = op.fprWillBeRead | op.fprWillBeWritten;
previous_cr_in_use = op.crWillBeRead | op.crWillBeWritten;
previous_gpr_will_be_written = op.gprWillBeWritten;
previous_fpr_will_be_written = op.fprWillBeWritten;
previous_cr_will_be_written = op.crWillBeWritten;
if (opinfo->flags & FL_LOADSTORE)
++js.numLoadStoreInst;