mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-26 23:10:38 +00:00
x86jit: Avoid pointerify if clobbered.
For x86, it's not worth it for one.
This commit is contained in:
parent
b370a89ef2
commit
9bac755491
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user