x86jit: Automatically flush incompatible regs.

This commit is contained in:
Unknown W. Brackets 2023-08-21 21:16:54 -07:00
parent 55654f52b2
commit 07fa1ed573
5 changed files with 34 additions and 11 deletions

View file

@ -434,6 +434,19 @@ IRNativeReg IRNativeRegCacheBase::FindBestToSpill(MIPSLoc type, MIPSMap flags, b
return -1;
}
bool IRNativeRegCacheBase::IsNativeRegCompatible(IRNativeReg nreg, MIPSLoc type, MIPSMap flags) {
int allocCount = 0, base = 0;
const int *allocOrder = GetAllocationOrder(type, flags, allocCount, base);
for (int i = 0; i < allocCount; i++) {
IRNativeReg allocReg = IRNativeReg(allocOrder[i] - base);
if (allocReg == nreg)
return true;
}
return false;
}
void IRNativeRegCacheBase::DiscardNativeReg(IRNativeReg nreg) {
_assert_msg_(nreg >= 0 && nreg < config_.totalNativeRegs, "DiscardNativeReg on invalid register %d", nreg);
if (nr[nreg].mipsReg != IRREG_INVALID) {
@ -828,18 +841,24 @@ IRNativeReg IRNativeRegCacheBase::MapNativeReg(MIPSLoc type, IRReg first, int la
case MIPSLoc::REG_IMM:
case MIPSLoc::REG_AS_PTR:
case MIPSLoc::REG:
if (type != MIPSLoc::REG)
if (type != MIPSLoc::REG) {
nreg = AllocateReg(type, flags);
} else if (!IsNativeRegCompatible(nreg, type, flags)) {
// If it's not compatible, we'll need to reallocate.
// TODO: Could do a transfer and avoid memory flush.
FlushNativeReg(nreg);
nreg = AllocateReg(type, flags);
}
break;
case MIPSLoc::FREG:
if (type != MIPSLoc::FREG)
nreg = AllocateReg(type, flags);
break;
case MIPSLoc::VREG:
if (type != MIPSLoc::VREG)
if (type != mr[first].loc) {
nreg = AllocateReg(type, flags);
} else if (!IsNativeRegCompatible(nreg, type, flags)) {
FlushNativeReg(nreg);
nreg = AllocateReg(type, flags);
}
break;
case MIPSLoc::IMM:

View file

@ -201,6 +201,7 @@ protected:
IRNativeReg AllocateReg(MIPSLoc type, MIPSMap flags);
IRNativeReg FindFreeReg(MIPSLoc type, MIPSMap flags) const;
IRNativeReg FindBestToSpill(MIPSLoc type, MIPSMap flags, bool unusedOnly, bool *clobbered) const;
virtual bool IsNativeRegCompatible(IRNativeReg nreg, MIPSLoc type, MIPSMap flags);
virtual void DiscardNativeReg(IRNativeReg nreg);
virtual void FlushNativeReg(IRNativeReg nreg);
virtual void DiscardReg(IRReg mreg);

View file

@ -300,6 +300,13 @@ void RiscVRegCache::AdjustNativeRegAsPtr(IRNativeReg nreg, bool state) {
}
}
bool RiscVRegCache::IsNativeRegCompatible(IRNativeReg nreg, MIPSLoc type, MIPSMap flags) {
// No special flags except VREG, skip the check for a little speed.
if (type != MIPSLoc::VREG)
return true;
return IRNativeRegCacheBase::IsNativeRegCompatible(nreg, type, flags);
}
void RiscVRegCache::LoadNativeReg(IRNativeReg nreg, IRReg first, int lanes) {
RiscVReg r = (RiscVReg)(X0 + nreg);
_dbg_assert_(r > X0);

View file

@ -76,6 +76,7 @@ protected:
const int *GetAllocationOrder(MIPSLoc type, MIPSMap flags, int &count, int &base) const override;
void AdjustNativeRegAsPtr(IRNativeReg nreg, bool state) override;
bool IsNativeRegCompatible(IRNativeReg nreg, MIPSLoc type, MIPSMap flags) override;
void LoadNativeReg(IRNativeReg nreg, IRReg first, int lanes) override;
void StoreNativeReg(IRNativeReg nreg, IRReg first, int lanes) override;
void SetNativeRegValue(IRNativeReg nreg, uint32_t imm) override;

View file

@ -172,11 +172,6 @@ X64Reg X64IRRegCache::MapWithFPRTemp(IRInst &inst) {
X64Reg X64IRRegCache::MapGPR(IRReg mipsReg, MIPSMap mapFlags) {
_dbg_assert_(IsValidGPR(mipsReg));
if ((mapFlags & X64Map::LOW_SUBREG) == X64Map::LOW_SUBREG && IsGPRMapped(mipsReg) && !HasLowSubregister(RX(mipsReg))) {
// Unfortunate. For now, let's flush it. We'll realloc a better one.
FlushNativeReg(mr[mipsReg].nReg);
}
// Okay, not mapped, so we need to allocate an RV register.
IRNativeReg nreg = MapNativeReg(MIPSLoc::REG, mipsReg, 1, mapFlags);
return FromNativeReg(nreg);