x86jit: Retain old lanes when there's space.

This commit is contained in:
Unknown W. Brackets committed 2023-09-24 17:31:25 -07:00
1 parent 46e704f879
commit 685d2acffe
3 files changed
+78 -19

No files matched your search

+18 -3
View File
@@ -406,12 +406,12 @@ IRNativeReg IRNativeRegCacheBase::FindFreeReg(MIPSLoc type, MIPSMap flags) const
bool IRNativeRegCacheBase::IsGPRClobbered(IRReg gpr) const {
_dbg_assert_(IsValidGPR(gpr));
return IsRegClobbered(MIPSLoc::REG, MIPSMap::INIT, gpr);
return IsRegClobbered(MIPSLoc::REG, gpr);
}
bool IRNativeRegCacheBase::IsFPRClobbered(IRReg fpr) const {
_dbg_assert_(IsValidFPR(fpr));
return IsRegClobbered(MIPSLoc::FREG, MIPSMap::INIT, fpr + 32);
return IsRegClobbered(MIPSLoc::FREG, fpr + 32);
}
IRUsage IRNativeRegCacheBase::GetNextRegUsage(const IRSituation &info, MIPSLoc type, IRReg r) const {
@@ -423,7 +423,7 @@ IRUsage IRNativeRegCacheBase::GetNextRegUsage(const IRSituation &info, MIPSLoc t
return IRUsage::UNKNOWN;
}
bool IRNativeRegCacheBase::IsRegClobbered(MIPSLoc type, MIPSMap flags, IRReg r) const {
bool IRNativeRegCacheBase::IsRegClobbered(MIPSLoc type, IRReg r) const {
static const int UNUSED_LOOKAHEAD_OPS = 30;
IRSituation info;
@@ -450,6 +450,21 @@ bool IRNativeRegCacheBase::IsRegClobbered(MIPSLoc type, MIPSMap flags, IRReg r)
return false;
}
bool IRNativeRegCacheBase::IsRegRead(MIPSLoc type, IRReg first) const {
static const int UNUSED_LOOKAHEAD_OPS = 30;
IRSituation info;
info.lookaheadCount = UNUSED_LOOKAHEAD_OPS;
// We look starting one ahead, unlike spilling.
info.currentIndex = irIndex_ + 1;
info.instructions = irBlock_->GetInstructions();
info.numInstructions = irBlock_->GetNumInstructions();
// Note: this intentionally doesn't look at the full reg, only the lane.
IRUsage usage = GetNextRegUsage(info, type, first);
return usage == IRUsage::READ;
}
IRNativeReg IRNativeRegCacheBase::FindBestToSpill(MIPSLoc type, MIPSMap flags, bool unusedOnly, bool *clobbered) const {
int allocCount = 0, base = 0;
const int *allocOrder = GetAllocationOrder(type, flags, allocCount, base);
+2 -1
View File
@@ -239,7 +239,8 @@ protected:
void SetSpillLockIRIndex(IRReg reg, int index);
int GetMipsRegOffset(IRReg r);
bool IsRegClobbered(MIPSLoc type, MIPSMap flags, IRReg r) const;
bool IsRegClobbered(MIPSLoc type, IRReg r) const;
bool IsRegRead(MIPSLoc type, IRReg r) const;
IRUsage GetNextRegUsage(const IRSituation &info, MIPSLoc type, IRReg r) const;
bool IsValidGPR(IRReg r) const;
+58 -15
View File
@@ -480,12 +480,52 @@ bool X64IRRegCache::TransferNativeReg(IRNativeReg nreg, IRNativeReg dest, MIPSLo
}
bool X64IRRegCache::TransferVecTo1(IRNativeReg nreg, IRNativeReg dest, IRReg first, int oldlanes) {
// Okay, start by storing if dirty.
// TODO: Consider moving the others to free regs if available? Likely will be wanted later.
IRReg oldfirst = nr[nreg].mipsReg;
if (nr[nreg].isDirty) {
// Is it worth preserving any of the old regs?
int numKept = 0;
for (int i = 0; i < oldlanes; ++i) {
// Skip whichever one this is extracting.
if (oldfirst + i == first)
continue;
// If 0 isn't being transfered, easy to keep in its original reg.
if (i == 0 && dest != nreg) {
numKept++;
continue;
}
IRNativeReg freeReg = FindFreeReg(MIPSLoc::FREG, MIPSMap::INIT);
if (freeReg != -1 && IsRegRead(MIPSLoc::FREG, oldfirst + i)) {
// If there's one free, use it. Don't modify nreg, though.
u8 shuf = VFPU_SWIZZLE(i, i, i, i);
if (i == 0) {
emit_->MOVAPS(FromNativeReg(freeReg), ::R(FromNativeReg(nreg)));
} else if (cpu_info.bAVX) {
emit_->VPERMILPS(128, FromNativeReg(freeReg), ::R(FromNativeReg(nreg)), shuf);
} else if (i == 2) {
emit_->MOVHLPS(FromNativeReg(freeReg), FromNativeReg(nreg));
} else {
emit_->MOVAPS(FromNativeReg(freeReg), ::R(FromNativeReg(nreg)));
emit_->SHUFPS(FromNativeReg(freeReg), ::R(FromNativeReg(freeReg)), shuf);
}
// Update accounting.
nr[freeReg].isDirty = nr[nreg].isDirty;
nr[freeReg].mipsReg = oldfirst + i;
mr[oldfirst + i].lane = -1;
mr[oldfirst + i].nReg = freeReg;
numKept++;
}
}
// Unless all other lanes were kept, store.
if (nr[nreg].isDirty && numKept < oldlanes - 1) {
StoreNativeReg(nreg, oldfirst, oldlanes);
nr[nreg].isDirty = false;
// Set false even for regs that were split out, since they were flushed too.
for (int i = 0; i < oldlanes; ++i) {
if (mr[oldfirst + i].nReg != -1)
nr[mr[oldfirst + i].nReg].isDirty = false;
}
}
// Next, shuffle the desired element into first place.
@@ -494,23 +534,24 @@ bool X64IRRegCache::TransferVecTo1(IRNativeReg nreg, IRNativeReg dest, IRReg fir
emit_->VPERMILPS(128, FromNativeReg(dest), ::R(FromNativeReg(nreg)), shuf);
} else if (mr[first].lane <= 0 && dest != nreg) {
emit_->MOVAPS(FromNativeReg(dest), ::R(FromNativeReg(nreg)));
} else if (mr[first].lane == 2) {
emit_->MOVHLPS(FromNativeReg(dest), FromNativeReg(nreg));
} else if (mr[first].lane > 0) {
if (mr[first].lane == 2) {
emit_->MOVHLPS(FromNativeReg(dest), FromNativeReg(nreg));
} else {
if (dest != nreg)
emit_->MOVAPS(FromNativeReg(dest), ::R(FromNativeReg(nreg)));
emit_->SHUFPS(FromNativeReg(dest), ::R(FromNativeReg(dest)), shuf);
}
if (dest != nreg)
emit_->MOVAPS(FromNativeReg(dest), ::R(FromNativeReg(nreg)));
emit_->SHUFPS(FromNativeReg(dest), ::R(FromNativeReg(dest)), shuf);
}
// Now update accounting.
for (int i = 0; i < oldlanes; ++i) {
auto &mreg = mr[oldfirst + i];
if (oldfirst + i == first) {
mreg.lane = 0;
mreg.lane = -1;
mreg.nReg = dest;
} else {
} else if (mreg.nReg == nreg && i == 0 && nreg != dest) {
// Still in the same register, but no longer a vec.
mreg.lane = -1;
} else if (mreg.nReg == nreg) {
// No longer in a register.
mreg.nReg = -1;
mreg.lane = -1;
@@ -520,8 +561,10 @@ bool X64IRRegCache::TransferVecTo1(IRNativeReg nreg, IRNativeReg dest, IRReg fir
if (dest != nreg) {
nr[dest].isDirty = nr[nreg].isDirty;
nr[nreg].mipsReg = -1;
nr[nreg].isDirty = false;
if (oldfirst == first) {
nr[nreg].mipsReg = -1;
nr[nreg].isDirty = false;
}
}
nr[dest].mipsReg = first;