mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-18 17:00:30 +02:00
ARM64 IR JIT: Join two mapped pairs into a quad with a ZIP1
Mapping a quad whose halves were in registers as pairs (two vs2i.p feeding a vi2f.q) flushed both and loaded the quad back, a store forwarding stall. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
108e66f2d1
commit
3d20d51c70
2 files changed
+66
No files matched your search
@@ -471,6 +471,8 @@ bool Arm64IRRegCache::TransferNativeReg(IRNativeReg nreg, IRNativeReg dest, MIPS
|
||||
return true;
|
||||
if (oldlanes == 1 && Transfer1ToVec(nreg, dest, first, lanes))
|
||||
return true;
|
||||
if (oldlanes == 2 && lanes == 4 && Transfer2ToVec4(nreg, dest, first))
|
||||
return true;
|
||||
}
|
||||
|
||||
return IRNativeRegCacheBase::TransferNativeReg(nreg, dest, type, first, lanes, flags);
|
||||
@@ -739,6 +741,69 @@ bool Arm64IRRegCache::Transfer1ToVec(IRNativeReg nreg, IRNativeReg dest, IRReg f
|
||||
return true;
|
||||
}
|
||||
|
||||
// Two pairs into a quad, like after two vs2i.p into the halves of one. Either half may be in memory.
|
||||
bool Arm64IRRegCache::Transfer2ToVec4(IRNativeReg nreg, IRNativeReg dest, IRReg first) {
|
||||
if ((first & 3) != 0)
|
||||
return false;
|
||||
|
||||
// Each half: the native reg holding just that pair, or -1 for in memory.
|
||||
IRNativeReg half[2];
|
||||
for (int h = 0; h < 2; ++h) {
|
||||
const IRReg m = first + h * 2;
|
||||
const IRNativeReg r = mr[m].nReg;
|
||||
if (r == -1) {
|
||||
if (mr[m].loc != MIPSLoc::MEM || mr[m + 1].loc != MIPSLoc::MEM)
|
||||
return false;
|
||||
} else if (nr[r].mipsReg != m || mr[m].lane != 0 || mr[m + 1].nReg != r || mr[m + 1].lane != 1 || (h == 0 && mr[m + 2].nReg == r)) {
|
||||
return false;
|
||||
}
|
||||
// The other half, if this instruction maps it separately.
|
||||
if (r != nreg && mr[m].spillLockIRIndex >= irIndex_)
|
||||
return false;
|
||||
half[h] = r;
|
||||
}
|
||||
if (half[0] != nreg && half[1] != nreg)
|
||||
return false;
|
||||
|
||||
const ARM64Reg destReg = EncodeRegToQuad(FromNativeReg(dest));
|
||||
auto Q = [&](IRNativeReg r) { return EncodeRegToQuad(FromNativeReg(r)); };
|
||||
if (half[0] != -1 && half[1] != -1) {
|
||||
fp_->ZIP1(64, destReg, Q(half[0]), Q(half[1]));
|
||||
} else {
|
||||
const int inReg = half[0] != -1 ? 0 : 1;
|
||||
if (dest != half[inReg]) {
|
||||
fp_->LDR(128, INDEX_UNSIGNED, destReg, CTXREG, GetMipsRegOffset(first));
|
||||
fp_->INS(64, destReg, inReg, Q(half[inReg]), 0);
|
||||
} else {
|
||||
IRNativeReg freeReg = FindFreeReg(MIPSLoc::FREG, MIPSMap::INIT);
|
||||
if (freeReg == -1)
|
||||
return false;
|
||||
fp_->LDR(64, INDEX_UNSIGNED, EncodeRegToDouble(FromNativeReg(freeReg)), CTXREG, GetMipsRegOffset(first + (1 - inReg) * 2));
|
||||
if (inReg == 0)
|
||||
fp_->INS(64, destReg, 1, Q(freeReg), 0);
|
||||
else
|
||||
fp_->ZIP1(64, destReg, Q(freeReg), destReg);
|
||||
}
|
||||
}
|
||||
|
||||
bool dirty = false;
|
||||
for (int h = 0; h < 2; ++h) {
|
||||
if (half[h] == -1)
|
||||
continue;
|
||||
dirty = dirty || nr[half[h]].isDirty;
|
||||
if (half[h] != dest)
|
||||
DiscardNativeReg(half[h]);
|
||||
}
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
mr[first + i].lane = i;
|
||||
mr[first + i].loc = MIPSLoc::FREG;
|
||||
mr[first + i].nReg = dest;
|
||||
}
|
||||
nr[dest].mipsReg = first;
|
||||
nr[dest].isDirty = dirty;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arm64IRRegCache::FlushAll(bool gprs, bool fprs) {
|
||||
// Note: make sure not to change the registers when flushing:
|
||||
// Branching code may expect the armreg to retain its value.
|
||||
|
||||
@@ -103,6 +103,7 @@ protected:
|
||||
private:
|
||||
bool TransferVecTo1(IRNativeReg nreg, IRNativeReg dest, IRReg first, int oldlanes);
|
||||
bool Transfer1ToVec(IRNativeReg nreg, IRNativeReg dest, IRReg first, int lanes);
|
||||
bool Transfer2ToVec4(IRNativeReg nreg, IRNativeReg dest, IRReg first);
|
||||
|
||||
IRNativeReg GPRToNativeReg(Arm64Gen::ARM64Reg r);
|
||||
IRNativeReg VFPToNativeReg(Arm64Gen::ARM64Reg r);
|
||||
|
||||
Reference in new issue
Block a user