x86jit: Avoid pointerify if clobbered.

For x86, it's not worth it for one.
This commit is contained in:
Unknown W. Brackets 2023-09-01 22:34:22 -07:00
parent b370a89ef2
commit 9bac755491
3 changed files with 61 additions and 14 deletions

View File

@ -404,6 +404,52 @@ IRNativeReg IRNativeRegCacheBase::FindFreeReg(MIPSLoc type, MIPSMap flags) const
return -1;
}
bool IRNativeRegCacheBase::IsGPRClobbered(IRReg gpr) const {
_dbg_assert_(IsValidGPR(gpr));
return IsRegClobbered(MIPSLoc::REG, MIPSMap::INIT, gpr);
}
bool IRNativeRegCacheBase::IsFPRClobbered(IRReg fpr) const {
_dbg_assert_(IsValidFPR(fpr));
return IsRegClobbered(MIPSLoc::FREG, MIPSMap::INIT, fpr + 32);
}
IRUsage IRNativeRegCacheBase::GetNextRegUsage(const IRSituation &info, MIPSLoc type, IRReg r) const {
if (type == MIPSLoc::REG)
return IRNextGPRUsage(r, info);
else if (type == MIPSLoc::FREG || type == MIPSLoc::VREG)
return IRNextFPRUsage(r - 32, info);
_assert_msg_(false, "Unknown spill allocation type");
return IRUsage::UNKNOWN;
}
bool IRNativeRegCacheBase::IsRegClobbered(MIPSLoc type, MIPSMap flags, IRReg r) const {
static const int UNUSED_LOOKAHEAD_OPS = 30;
IRSituation info;
info.lookaheadCount = UNUSED_LOOKAHEAD_OPS;
// We look starting one ahead, unlike spilling. We want to know if it clobbers later.
info.currentIndex = irIndex_ + 1;
info.instructions = irBlock_->GetInstructions();
info.numInstructions = irBlock_->GetNumInstructions();
// Make sure we're on the first one if this is multi-lane.
IRReg first = r;
if (mr[r].lane != -1)
first -= mr[r].lane;
IRUsage usage = GetNextRegUsage(info, type, first);
if (usage == IRUsage::CLOBBERED) {
// If multiple mips regs use this native reg (i.e. vector, HI/LO), check each.
bool canClobber = true;
for (IRReg m = first + 1; mr[m].nReg == mr[first].nReg && m < IRREG_INVALID && canClobber; ++m)
canClobber = GetNextRegUsage(info, type, m) == IRUsage::CLOBBERED;
return canClobber;
}
return false;
}
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);
@ -416,15 +462,6 @@ IRNativeReg IRNativeRegCacheBase::FindBestToSpill(MIPSLoc type, MIPSMap flags, b
info.instructions = irBlock_->GetInstructions();
info.numInstructions = irBlock_->GetNumInstructions();
auto getUsage = [type, &info](IRReg mipsReg) {
if (type == MIPSLoc::REG)
return IRNextGPRUsage(mipsReg, info);
else if (type == MIPSLoc::FREG || type == MIPSLoc::VREG)
return IRNextFPRUsage(mipsReg - 32, info);
_assert_msg_(false, "Unknown spill allocation type");
return IRUsage::UNKNOWN;
};
*clobbered = false;
for (int i = 0; i < allocCount; i++) {
IRNativeReg nreg = IRNativeReg(allocOrder[i] - base);
@ -435,7 +472,7 @@ IRNativeReg IRNativeRegCacheBase::FindBestToSpill(MIPSLoc type, MIPSMap flags, b
// As it's in alloc-order, we know it's not static so we don't need to check for that.
IRReg mipsReg = nr[nreg].mipsReg;
IRUsage usage = getUsage(mipsReg);
IRUsage usage = GetNextRegUsage(info, type, mipsReg);
// Awesome, a clobbered reg. Let's use it?
if (usage == IRUsage::CLOBBERED) {
@ -443,7 +480,7 @@ IRNativeReg IRNativeRegCacheBase::FindBestToSpill(MIPSLoc type, MIPSMap flags, b
// Note: mipsReg points to the lowest numbered IRReg.
bool canClobber = true;
for (IRReg m = mipsReg + 1; mr[m].nReg == nreg && m < IRREG_INVALID && canClobber; ++m)
canClobber = getUsage(m) == IRUsage::CLOBBERED;
canClobber = GetNextRegUsage(info, type, m) == IRUsage::CLOBBERED;
// Okay, if all can be clobbered, we're good to go.
if (canClobber) {

View File

@ -22,6 +22,7 @@
#include "Common/CommonTypes.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/IR/IRAnalysis.h"
#include "Core/MIPS/IR/IRInst.h"
@ -183,6 +184,9 @@ public:
void MarkGPRDirty(IRReg gpr, bool andNormalized32 = false);
void MarkGPRAsPointerDirty(IRReg gpr);
bool IsGPRClobbered(IRReg gpr) const;
bool IsFPRClobbered(IRReg gpr) const;
struct Mapping {
char type = '?';
IRReg reg = IRREG_INVALID;
@ -234,6 +238,9 @@ protected:
void SetSpillLockIRIndex(IRReg reg, int index);
int GetMipsRegOffset(IRReg r);
bool IsRegClobbered(MIPSLoc type, MIPSMap flags, IRReg r) const;
IRUsage GetNextRegUsage(const IRSituation &info, MIPSLoc type, IRReg r) const;
bool IsValidGPR(IRReg r) const;
bool IsValidGPRNoZero(IRReg r) const;
bool IsValidFPR(IRReg r) const;

View File

@ -39,7 +39,11 @@ using namespace X64IRJitConstants;
Gen::OpArg X64JitBackend::PrepareSrc1Address(IRInst inst) {
const IRMeta *m = GetIRMeta(inst.op);
bool src1IsPointer = regs_.IsGPRMappedAsPointer(inst.src1);
bool readsFromSrc1 = inst.src1 == inst.src3 && (m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0;
// If it's about to be clobbered, don't waste time pointerifying. Use displacement.
bool clobbersSrc1 = !readsFromSrc1 && regs_.IsGPRClobbered(inst.src1);
OpArg addrArg;
if (inst.src1 == MIPS_REG_ZERO) {
@ -51,7 +55,7 @@ Gen::OpArg X64JitBackend::PrepareSrc1Address(IRInst inst) {
#else
addrArg = M(Memory::base + inst.constant);
#endif
} else if ((jo.cachePointers || regs_.IsGPRMappedAsPointer(inst.src1)) && !readsFromSrc1) {
} else if ((jo.cachePointers || src1IsPointer) && !readsFromSrc1 && (!clobbersSrc1 || src1IsPointer)) {
X64Reg src1 = regs_.MapGPRAsPointer(inst.src1);
addrArg = MDisp(src1, (int)inst.constant);
} else {
@ -59,8 +63,7 @@ Gen::OpArg X64JitBackend::PrepareSrc1Address(IRInst inst) {
#ifdef MASKED_PSP_MEMORY
LEA(PTRBITS, SCRATCH1, MDisp(regs_.RX(inst.src1), (int)inst.constant));
AND(PTRBITS, R(SCRATCH1), Imm32(Memory::MEMVIEW32_MASK));
ADD(PTRBITS, R(SCRATCH1), ImmPtr(Memory::base));
addrArg = MatR(SCRATCH1);
addrArg = MDisp(SCRATCH1, (intptr_t)Memory::base);
#else
#if PPSSPP_ARCH(AMD64)
addrArg = MComplex(MEMBASEREG, regs_.RX(inst.src1), SCALE_1, (int)inst.constant);