PPCAnalyst: Clean up indexing expressions in Analyze()

Given we just access the same member repeatedly, just use a reference
and avoid repeated unnecessary indexing.
This commit is contained in:
Lioncash 2018-05-19 15:29:09 -04:00
parent c6bd237534
commit 5de99288bf
1 changed files with 56 additions and 52 deletions

View File

@ -833,39 +833,41 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, std:
BitSet32 fprInUse, gprInUse, gprInReg, fprInXmm;
for (int i = block->m_num_instructions - 1; i >= 0; i--)
{
bool opWantsCR0 = code[i].wantsCR0;
bool opWantsCR1 = code[i].wantsCR1;
bool opWantsFPRF = code[i].wantsFPRF;
bool opWantsCA = code[i].wantsCA;
code[i].wantsCR0 = wantsCR0 || code[i].canEndBlock;
code[i].wantsCR1 = wantsCR1 || code[i].canEndBlock;
code[i].wantsFPRF = wantsFPRF || code[i].canEndBlock;
code[i].wantsCA = wantsCA || code[i].canEndBlock;
wantsCR0 |= opWantsCR0 || code[i].canEndBlock;
wantsCR1 |= opWantsCR1 || code[i].canEndBlock;
wantsFPRF |= opWantsFPRF || code[i].canEndBlock;
wantsCA |= opWantsCA || code[i].canEndBlock;
wantsCR0 &= !code[i].outputCR0 || opWantsCR0;
wantsCR1 &= !code[i].outputCR1 || opWantsCR1;
wantsFPRF &= !code[i].outputFPRF || opWantsFPRF;
wantsCA &= !code[i].outputCA || opWantsCA;
code[i].gprInUse = gprInUse;
code[i].fprInUse = fprInUse;
code[i].gprInReg = gprInReg;
code[i].fprInXmm = fprInXmm;
CodeOp& op = code[i];
const bool opWantsCR0 = op.wantsCR0;
const bool opWantsCR1 = op.wantsCR1;
const bool opWantsFPRF = op.wantsFPRF;
const bool opWantsCA = op.wantsCA;
op.wantsCR0 = wantsCR0 || op.canEndBlock;
op.wantsCR1 = wantsCR1 || op.canEndBlock;
op.wantsFPRF = wantsFPRF || op.canEndBlock;
op.wantsCA = wantsCA || op.canEndBlock;
wantsCR0 |= opWantsCR0 || op.canEndBlock;
wantsCR1 |= opWantsCR1 || op.canEndBlock;
wantsFPRF |= opWantsFPRF || op.canEndBlock;
wantsCA |= opWantsCA || op.canEndBlock;
wantsCR0 &= !op.outputCR0 || opWantsCR0;
wantsCR1 &= !op.outputCR1 || opWantsCR1;
wantsFPRF &= !op.outputFPRF || opWantsFPRF;
wantsCA &= !op.outputCA || opWantsCA;
op.gprInUse = gprInUse;
op.fprInUse = fprInUse;
op.gprInReg = gprInReg;
op.fprInXmm = fprInXmm;
// TODO: if there's no possible endblocks or exceptions in between, tell the regcache
// we can throw away a register if it's going to be overwritten later.
gprInUse |= code[i].regsIn;
gprInReg |= code[i].regsIn;
fprInUse |= code[i].fregsIn;
if (strncmp(code[i].opinfo->opname, "stfd", 4))
fprInXmm |= code[i].fregsIn;
gprInUse |= op.regsIn;
gprInReg |= op.regsIn;
fprInUse |= op.fregsIn;
if (strncmp(op.opinfo->opname, "stfd", 4))
fprInXmm |= op.fregsIn;
// For now, we need to count output registers as "used" though; otherwise the flush
// will result in a redundant store (e.g. store to regcache, then store again to
// the same location later).
gprInUse |= code[i].regsOut;
if (code[i].fregOut >= 0)
fprInUse[code[i].fregOut] = true;
gprInUse |= op.regsOut;
if (op.fregOut >= 0)
fprInUse[op.fregOut] = true;
}
// Forward scan, for flags that need the other direction for calculation.
@ -873,55 +875,57 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, std:
BitSet8 gqrUsed, gqrModified;
for (u32 i = 0; i < block->m_num_instructions; i++)
{
gprBlockInputs |= code[i].regsIn & ~gprDefined;
gprDefined |= code[i].regsOut;
CodeOp& op = code[i];
code[i].fprIsSingle = fprIsSingle;
code[i].fprIsDuplicated = fprIsDuplicated;
code[i].fprIsStoreSafe = fprIsStoreSafe;
if (code[i].fregOut >= 0)
gprBlockInputs |= op.regsIn & ~gprDefined;
gprDefined |= op.regsOut;
op.fprIsSingle = fprIsSingle;
op.fprIsDuplicated = fprIsDuplicated;
op.fprIsStoreSafe = fprIsStoreSafe;
if (op.fregOut >= 0)
{
fprIsSingle[code[i].fregOut] = false;
fprIsDuplicated[code[i].fregOut] = false;
fprIsStoreSafe[code[i].fregOut] = false;
fprIsSingle[op.fregOut] = false;
fprIsDuplicated[op.fregOut] = false;
fprIsStoreSafe[op.fregOut] = false;
// Single, duplicated, and doesn't need PPC_FP.
if (code[i].opinfo->type == OpType::SingleFP)
if (op.opinfo->type == OpType::SingleFP)
{
fprIsSingle[code[i].fregOut] = true;
fprIsDuplicated[code[i].fregOut] = true;
fprIsStoreSafe[code[i].fregOut] = true;
fprIsSingle[op.fregOut] = true;
fprIsDuplicated[op.fregOut] = true;
fprIsStoreSafe[op.fregOut] = true;
}
// Single and duplicated, but might be a denormal (not safe to skip PPC_FP).
// TODO: if we go directly from a load to store, skip conversion entirely?
// TODO: if we go directly from a load to a float instruction, and the value isn't used
// for anything else, we can skip PPC_FP on a load too.
if (!strncmp(code[i].opinfo->opname, "lfs", 3))
if (!strncmp(op.opinfo->opname, "lfs", 3))
{
fprIsSingle[code[i].fregOut] = true;
fprIsDuplicated[code[i].fregOut] = true;
fprIsSingle[op.fregOut] = true;
fprIsDuplicated[op.fregOut] = true;
}
// Paired are still floats, but the top/bottom halves may differ.
if (code[i].opinfo->type == OpType::PS || code[i].opinfo->type == OpType::LoadPS)
if (op.opinfo->type == OpType::PS || op.opinfo->type == OpType::LoadPS)
{
fprIsSingle[code[i].fregOut] = true;
fprIsStoreSafe[code[i].fregOut] = true;
fprIsSingle[op.fregOut] = true;
fprIsStoreSafe[op.fregOut] = true;
}
// Careful: changing the float mode in a block breaks this optimization, since
// a previous float op might have had had FTZ off while the later store has FTZ
// on. So, discard all information we have.
if (!strncmp(code[i].opinfo->opname, "mtfs", 4))
if (!strncmp(op.opinfo->opname, "mtfs", 4))
fprIsStoreSafe = BitSet32(0);
}
if (code[i].opinfo->type == OpType::StorePS || code[i].opinfo->type == OpType::LoadPS)
if (op.opinfo->type == OpType::StorePS || op.opinfo->type == OpType::LoadPS)
{
int gqr = code[i].inst.OPCD == 4 ? code[i].inst.Ix : code[i].inst.I;
const int gqr = op.inst.OPCD == 4 ? op.inst.Ix : op.inst.I;
gqrUsed[gqr] = true;
}
if (code[i].inst.OPCD == 31 && code[i].inst.SUBOP10 == 467) // mtspr
if (op.inst.OPCD == 31 && op.inst.SUBOP10 == 467) // mtspr
{
int gqr = ((code[i].inst.SPRU << 5) | code[i].inst.SPRL) - SPR_GQR0;
const int gqr = ((op.inst.SPRU << 5) | op.inst.SPRL) - SPR_GQR0;
if (gqr >= 0 && gqr <= 7)
gqrModified[gqr] = true;
}