mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-08-25 20:09:27 -05:00
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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user