mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 05:19:56 +00:00
riscv: Spill registers more intelligently.
This commit is contained in:
parent
020706f545
commit
f870271011
@ -1539,6 +1539,8 @@ set(CoreExtra)
|
||||
set(CoreExtraLibs)
|
||||
|
||||
set(CoreExtra ${CoreExtra}
|
||||
Core/MIPS/IR/IRAnalysis.cpp
|
||||
Core/MIPS/IR/IRAnalysis.h
|
||||
Core/MIPS/IR/IRCompALU.cpp
|
||||
Core/MIPS/IR/IRCompBranch.cpp
|
||||
Core/MIPS/IR/IRCompFPU.cpp
|
||||
|
@ -580,6 +580,7 @@
|
||||
<ClCompile Include="KeyMapDefaults.cpp" />
|
||||
<ClCompile Include="MemFault.cpp" />
|
||||
<ClCompile Include="MIPS\fake\FakeJit.cpp" />
|
||||
<ClCompile Include="MIPS\IR\IRAnalysis.cpp" />
|
||||
<ClCompile Include="MIPS\IR\IRAsm.cpp" />
|
||||
<ClCompile Include="MIPS\IR\IRCompALU.cpp" />
|
||||
<ClCompile Include="MIPS\IR\IRCompBranch.cpp" />
|
||||
@ -1164,6 +1165,7 @@
|
||||
<ClInclude Include="KeyMapDefaults.h" />
|
||||
<ClInclude Include="MemFault.h" />
|
||||
<ClInclude Include="MIPS\fake\FakeJit.h" />
|
||||
<ClInclude Include="MIPS\IR\IRAnalysis.h" />
|
||||
<ClInclude Include="MIPS\IR\IRFrontend.h" />
|
||||
<ClInclude Include="MIPS\IR\IRInst.h" />
|
||||
<ClInclude Include="MIPS\IR\IRInterpreter.h" />
|
||||
|
@ -1237,6 +1237,9 @@
|
||||
<ClCompile Include="MIPS\RiscV\RiscVCompSystem.cpp">
|
||||
<Filter>MIPS\RiscV</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\IR\IRAnalysis.cpp">
|
||||
<Filter>MIPS\IR</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ELF\ElfReader.h">
|
||||
@ -1992,6 +1995,9 @@
|
||||
<ClInclude Include="MIPS\RiscV\RiscVRegCacheFPU.h">
|
||||
<Filter>MIPS\RiscV</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\IR\IRAnalysis.h">
|
||||
<Filter>MIPS\IR</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\LICENSE.TXT" />
|
||||
|
135
Core/MIPS/IR/IRAnalysis.cpp
Normal file
135
Core/MIPS/IR/IRAnalysis.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
// Copyright (c) 2016- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "Core/MIPS/IR/IRAnalysis.h"
|
||||
|
||||
static bool IRReadsFrom(const IRInst &inst, int reg, char type, bool directly = false) {
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
|
||||
if (m->types[1] == type && inst.src1 == reg) {
|
||||
return true;
|
||||
}
|
||||
if (m->types[2] == type && inst.src2 == reg) {
|
||||
return true;
|
||||
}
|
||||
if ((m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0 && m->types[0] == type && inst.src3 == reg) {
|
||||
return true;
|
||||
}
|
||||
if (!directly) {
|
||||
if (inst.op == IROp::Interpret || inst.op == IROp::CallReplacement || inst.op == IROp::Syscall || inst.op == IROp::Break)
|
||||
return true;
|
||||
if (inst.op == IROp::Breakpoint || inst.op == IROp::MemoryCheck)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IRReadsFromFPR(const IRInst &inst, int reg, bool directly) {
|
||||
if (IRReadsFrom(inst, reg, 'F', directly))
|
||||
return true;
|
||||
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
|
||||
// We also need to check V and 2. Indirect reads already checked, don't check again.
|
||||
if (m->types[1] == 'V' && reg >= inst.src1 && reg < inst.src1 + 4)
|
||||
return true;
|
||||
if (m->types[1] == '2' && reg >= inst.src1 && reg < inst.src1 + 2)
|
||||
return true;
|
||||
if (m->types[2] == 'V' && reg >= inst.src2 && reg < inst.src2 + 4)
|
||||
return true;
|
||||
if (m->types[2] == '2' && reg >= inst.src2 && reg < inst.src2 + 2)
|
||||
return true;
|
||||
if ((m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0) {
|
||||
if (m->types[0] == 'V' && reg >= inst.src3 && reg <= inst.src3 + 4)
|
||||
return true;
|
||||
if (m->types[0] == '2' && reg >= inst.src3 && reg <= inst.src3 + 2)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IRReadsFromGPR(const IRInst &inst, int reg, bool directly) {
|
||||
return IRReadsFrom(inst, reg, 'G', directly);
|
||||
}
|
||||
|
||||
int IRDestGPR(const IRInst &inst) {
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
|
||||
if ((m->flags & IRFLAG_SRC3) == 0 && m->types[0] == 'G') {
|
||||
return inst.dest;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool IRWritesToGPR(const IRInst &inst, int reg) {
|
||||
return IRDestGPR(inst) == reg;
|
||||
}
|
||||
|
||||
bool IRWritesToFPR(const IRInst &inst, int reg) {
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
|
||||
// Doesn't write to anything.
|
||||
if ((m->flags & IRFLAG_SRC3) != 0)
|
||||
return false;
|
||||
|
||||
if (m->types[0] == 'F' && reg == inst.dest)
|
||||
return true;
|
||||
if (m->types[0] == 'V' && reg >= inst.dest && reg < inst.dest + 4)
|
||||
return true;
|
||||
if (m->types[0] == '2' && reg >= inst.dest && reg < inst.dest + 2)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
IRUsage IRNextGPRUsage(int gpr, const IRSituation &info) {
|
||||
// Exclude any "special" regs from this logic for now.
|
||||
if (gpr >= 32)
|
||||
return IRUsage::UNKNOWN;
|
||||
|
||||
int count = std::min(info.numInstructions - info.currentIndex, info.lookaheadCount);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const IRInst inst = info.instructions[info.currentIndex + i];
|
||||
if (IRReadsFromGPR(inst, gpr))
|
||||
return IRUsage::READ;
|
||||
// We say WRITE when the current instruction writes. It's not useful for spilling.
|
||||
if (IRDestGPR(inst) == gpr)
|
||||
return i == 0 ? IRUsage::WRITE : IRUsage::CLOBBERED;
|
||||
}
|
||||
|
||||
return IRUsage::UNUSED;
|
||||
}
|
||||
|
||||
IRUsage IRNextFPRUsage(int fpr, const IRSituation &info) {
|
||||
// Let's only pay attention to standard FP regs and temps.
|
||||
// See MIPS.h for these offsets.
|
||||
if (fpr < 0 || (fpr >= 160 && fpr < 192) || fpr >= 208)
|
||||
return IRUsage::UNKNOWN;
|
||||
|
||||
int count = std::min(info.numInstructions - info.currentIndex, info.lookaheadCount);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const IRInst inst = info.instructions[info.currentIndex + i];
|
||||
|
||||
if (IRReadsFromFPR(inst, fpr))
|
||||
return IRUsage::READ;
|
||||
// We say WRITE when the current instruction writes. It's not useful for spilling.
|
||||
if (IRWritesToFPR(inst, fpr)) {
|
||||
return i == 0 ? IRUsage::WRITE : IRUsage::CLOBBERED;
|
||||
}
|
||||
}
|
||||
|
||||
return IRUsage::UNUSED;
|
||||
}
|
44
Core/MIPS/IR/IRAnalysis.h
Normal file
44
Core/MIPS/IR/IRAnalysis.h
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2016- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Core/MIPS/IR/IRInst.h"
|
||||
|
||||
bool IRReadsFromFPR(const IRInst &inst, int reg, bool directly = false);
|
||||
bool IRReadsFromGPR(const IRInst &inst, int reg, bool directly = false);
|
||||
bool IRWritesToGPR(const IRInst &inst, int reg);
|
||||
bool IRWritesToFPR(const IRInst &inst, int reg);
|
||||
int IRDestGPR(const IRInst &inst);
|
||||
|
||||
struct IRSituation {
|
||||
int lookaheadCount;
|
||||
int currentIndex;
|
||||
const IRInst *instructions;
|
||||
int numInstructions;
|
||||
};
|
||||
|
||||
enum class IRUsage {
|
||||
UNKNOWN,
|
||||
UNUSED,
|
||||
READ,
|
||||
WRITE,
|
||||
CLOBBERED,
|
||||
};
|
||||
|
||||
IRUsage IRNextGPRUsage(int gpr, const IRSituation &info);
|
||||
IRUsage IRNextFPRUsage(int fpr, const IRSituation &info);
|
@ -1,6 +1,5 @@
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Core/MIPS/IR/IRInst.h"
|
||||
#include "Core/MIPS/IR/IRPassSimplify.h"
|
||||
#include "Core/MIPS/MIPSDebugInterface.h"
|
||||
|
||||
// Legend
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include "Core/MIPS/MIPSTables.h"
|
||||
#include "Core/MIPS/IR/IRRegCache.h"
|
||||
#include "Core/MIPS/IR/IRJit.h"
|
||||
#include "Core/MIPS/IR/IRPassSimplify.h"
|
||||
#include "Core/MIPS/IR/IRInterpreter.h"
|
||||
#include "Core/MIPS/JitCommon/JitCommon.h"
|
||||
#include "Core/Reporting.h"
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "Common/Data/Convert/SmallDataConvert.h"
|
||||
#include "Common/Log.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/MIPS/IR/IRAnalysis.h"
|
||||
#include "Core/MIPS/IR/IRInterpreter.h"
|
||||
#include "Core/MIPS/IR/IRPassSimplify.h"
|
||||
#include "Core/MIPS/IR/IRRegCache.h"
|
||||
@ -803,27 +804,6 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts
|
||||
return logBlocks;
|
||||
}
|
||||
|
||||
bool IRReadsFromGPR(const IRInst &inst, int reg, bool directly = false) {
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
|
||||
if (m->types[1] == 'G' && inst.src1 == reg) {
|
||||
return true;
|
||||
}
|
||||
if (m->types[2] == 'G' && inst.src2 == reg) {
|
||||
return true;
|
||||
}
|
||||
if ((m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0 && m->types[0] == 'G' && inst.src3 == reg) {
|
||||
return true;
|
||||
}
|
||||
if (!directly) {
|
||||
if (inst.op == IROp::Interpret || inst.op == IROp::CallReplacement || inst.op == IROp::Syscall || inst.op == IROp::Break)
|
||||
return true;
|
||||
if (inst.op == IROp::Breakpoint || inst.op == IROp::MemoryCheck)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
IRInst IRReplaceSrcGPR(const IRInst &inst, int fromReg, int toReg) {
|
||||
IRInst newInst = inst;
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
@ -840,15 +820,6 @@ IRInst IRReplaceSrcGPR(const IRInst &inst, int fromReg, int toReg) {
|
||||
return newInst;
|
||||
}
|
||||
|
||||
int IRDestGPR(const IRInst &inst) {
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
|
||||
if ((m->flags & IRFLAG_SRC3) == 0 && m->types[0] == 'G') {
|
||||
return inst.dest;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
IRInst IRReplaceDestGPR(const IRInst &inst, int fromReg, int toReg) {
|
||||
IRInst newInst = inst;
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
|
@ -813,7 +813,7 @@ namespace MIPSAnalyst {
|
||||
break;
|
||||
}
|
||||
|
||||
if (reg > 32) {
|
||||
if (reg >= 32) {
|
||||
return USAGE_UNKNOWN;
|
||||
}
|
||||
|
||||
|
@ -111,19 +111,20 @@ bool RiscVJit::CompileTargetBlock(IRBlock *block, int block_num, bool preload) {
|
||||
|
||||
// TODO: Block linking, checked entries and such.
|
||||
|
||||
gpr.Start();
|
||||
fpr.Start();
|
||||
gpr.Start(block);
|
||||
fpr.Start(block);
|
||||
|
||||
for (int i = 0; i < block->GetNumInstructions(); ++i) {
|
||||
const IRInst &inst = block->GetInstructions()[i];
|
||||
gpr.SetIRIndex(i);
|
||||
fpr.SetIRIndex(i);
|
||||
|
||||
CompileIRInst(inst);
|
||||
|
||||
if (jo.Disabled(JitDisable::REGALLOC_GPR)) {
|
||||
if (jo.Disabled(JitDisable::REGALLOC_GPR))
|
||||
gpr.FlushAll();
|
||||
}
|
||||
if (jo.Disabled(JitDisable::REGALLOC_FPR)) {
|
||||
if (jo.Disabled(JitDisable::REGALLOC_FPR))
|
||||
fpr.FlushAll();
|
||||
}
|
||||
|
||||
// Safety check, in case we get a bunch of really large jit ops without a lot of branching.
|
||||
if (GetSpaceLeft() < 0x800) {
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "Common/CPUDetect.h"
|
||||
#include "Core/MIPS/IR/IRInst.h"
|
||||
#include "Core/MIPS/IR/IRAnalysis.h"
|
||||
#include "Core/MIPS/RiscV/RiscVRegCache.h"
|
||||
#include "Core/MIPS/JitCommon/JitState.h"
|
||||
#include "Core/Reporting.h"
|
||||
@ -36,7 +37,7 @@ void RiscVRegCache::Init(RiscVEmitter *emitter) {
|
||||
emit_ = emitter;
|
||||
}
|
||||
|
||||
void RiscVRegCache::Start() {
|
||||
void RiscVRegCache::Start(MIPSComp::IRBlock *irBlock) {
|
||||
if (!initialReady_) {
|
||||
SetupInitialRegs();
|
||||
initialReady_ = true;
|
||||
@ -56,6 +57,9 @@ void RiscVRegCache::Start() {
|
||||
mr[statics[i].mr].isStatic = true;
|
||||
mr[statics[i].mr].spillLock = true;
|
||||
}
|
||||
|
||||
irBlock_ = irBlock;
|
||||
irIndex_ = 0;
|
||||
}
|
||||
|
||||
void RiscVRegCache::SetupInitialRegs() {
|
||||
@ -362,8 +366,6 @@ allocate:
|
||||
}
|
||||
|
||||
// Still nothing. Let's spill a reg and goto 10.
|
||||
// TODO: Use age or something to choose which register to spill?
|
||||
// TODO: Spill dirty regs first? or opposite?
|
||||
bool clobbered;
|
||||
RiscVReg bestToSpill = FindBestToSpill(true, &clobbered);
|
||||
if (bestToSpill == INVALID_REG) {
|
||||
@ -392,6 +394,12 @@ RiscVReg RiscVRegCache::FindBestToSpill(bool unusedOnly, bool *clobbered) {
|
||||
|
||||
static const int UNUSED_LOOKAHEAD_OPS = 30;
|
||||
|
||||
IRSituation info;
|
||||
info.lookaheadCount = UNUSED_LOOKAHEAD_OPS;
|
||||
info.currentIndex = irIndex_;
|
||||
info.instructions = irBlock_->GetInstructions();
|
||||
info.numInstructions = irBlock_->GetNumInstructions();
|
||||
|
||||
*clobbered = false;
|
||||
for (int i = 0; i < allocCount; i++) {
|
||||
RiscVReg reg = allocOrder[i];
|
||||
@ -401,16 +409,24 @@ RiscVReg RiscVRegCache::FindBestToSpill(bool unusedOnly, bool *clobbered) {
|
||||
continue;
|
||||
|
||||
// As it's in alloc-order, we know it's not static so we don't need to check for that.
|
||||
IRUsage usage = IRNextGPRUsage(ar[reg].mipsReg, info);
|
||||
|
||||
// TODO: Look for clobbering in the IRInst array with index?
|
||||
|
||||
// Not awesome. A used reg. Let's try to avoid spilling.
|
||||
// TODO: Actually check if we'd be spilling.
|
||||
if (unusedOnly) {
|
||||
continue;
|
||||
// Awesome, a clobbered reg. Let's use it.
|
||||
if (usage == IRUsage::CLOBBERED) {
|
||||
// TODO: Check HI/LO clobber together if we combine.
|
||||
bool canClobber = true;
|
||||
if (canClobber) {
|
||||
*clobbered = true;
|
||||
return reg;
|
||||
}
|
||||
}
|
||||
|
||||
return reg;
|
||||
// Not awesome. A used reg. Let's try to avoid spilling.
|
||||
if (!unusedOnly || usage == IRUsage::UNUSED) {
|
||||
// TODO: Use age or something to choose which register to spill?
|
||||
// TODO: Spill dirty regs first? or opposite?
|
||||
return reg;
|
||||
}
|
||||
}
|
||||
|
||||
return INVALID_REG;
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "Common/RiscVEmitter.h"
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Core/MIPS/IR/IRJit.h"
|
||||
|
||||
namespace RiscVJitConstants {
|
||||
|
||||
@ -101,8 +102,10 @@ public:
|
||||
~RiscVRegCache() {}
|
||||
|
||||
void Init(RiscVGen::RiscVEmitter *emitter);
|
||||
// TODO: Maybe pass in IR block and start PC for logging/debugging?
|
||||
void Start();
|
||||
void Start(MIPSComp::IRBlock *irBlock);
|
||||
void SetIRIndex(int index) {
|
||||
irIndex_ = index;
|
||||
}
|
||||
|
||||
// Protect the arm register containing a MIPS register from spilling, to ensure that
|
||||
// it's being kept allocated.
|
||||
@ -176,6 +179,8 @@ private:
|
||||
MIPSState *mips_;
|
||||
RiscVGen::RiscVEmitter *emit_ = nullptr;
|
||||
MIPSComp::JitOptions *jo_;
|
||||
MIPSComp::IRBlock *irBlock_ = nullptr;
|
||||
int irIndex_ = 0;
|
||||
|
||||
enum {
|
||||
NUM_RVREG = 32, // 31 actual registers, plus the zero/sp register which is not mappable.
|
||||
|
@ -20,6 +20,8 @@
|
||||
#endif
|
||||
|
||||
#include "Common/CPUDetect.h"
|
||||
#include "Core/MIPS/IR/IRInst.h"
|
||||
#include "Core/MIPS/IR/IRAnalysis.h"
|
||||
#include "Core/MIPS/RiscV/RiscVRegCacheFPU.h"
|
||||
#include "Core/MIPS/JitCommon/JitState.h"
|
||||
#include "Core/Reporting.h"
|
||||
@ -34,7 +36,7 @@ void RiscVRegCacheFPU::Init(RiscVEmitter *emitter) {
|
||||
emit_ = emitter;
|
||||
}
|
||||
|
||||
void RiscVRegCacheFPU::Start() {
|
||||
void RiscVRegCacheFPU::Start(MIPSComp::IRBlock *irBlock) {
|
||||
if (!initialReady_) {
|
||||
SetupInitialRegs();
|
||||
initialReady_ = true;
|
||||
@ -43,6 +45,9 @@ void RiscVRegCacheFPU::Start() {
|
||||
memcpy(ar, arInitial_, sizeof(ar));
|
||||
memcpy(mr, mrInitial_, sizeof(mr));
|
||||
pendingFlush_ = false;
|
||||
|
||||
irBlock_ = irBlock;
|
||||
irIndex_ = 0;
|
||||
}
|
||||
|
||||
void RiscVRegCacheFPU::SetupInitialRegs() {
|
||||
@ -130,8 +135,6 @@ allocate:
|
||||
}
|
||||
|
||||
// Still nothing. Let's spill a reg and goto 10.
|
||||
// TODO: Use age or something to choose which register to spill?
|
||||
// TODO: Spill dirty regs first? or opposite?
|
||||
bool clobbered;
|
||||
RiscVReg bestToSpill = FindBestToSpill(true, &clobbered);
|
||||
if (bestToSpill == INVALID_REG) {
|
||||
@ -160,21 +163,33 @@ RiscVReg RiscVRegCacheFPU::FindBestToSpill(bool unusedOnly, bool *clobbered) {
|
||||
|
||||
static const int UNUSED_LOOKAHEAD_OPS = 30;
|
||||
|
||||
IRSituation info;
|
||||
info.lookaheadCount = UNUSED_LOOKAHEAD_OPS;
|
||||
info.currentIndex = irIndex_;
|
||||
info.instructions = irBlock_->GetInstructions();
|
||||
info.numInstructions = irBlock_->GetNumInstructions();
|
||||
|
||||
*clobbered = false;
|
||||
for (int i = 0; i < allocCount; i++) {
|
||||
RiscVReg reg = allocOrder[i];
|
||||
if (ar[reg - F0].mipsReg != IRREG_INVALID && mr[ar[reg - F0].mipsReg].spillLock)
|
||||
continue;
|
||||
|
||||
// TODO: Look for clobbering in the IRInst array with index?
|
||||
// As it's in alloc-order, we know it's not static so we don't need to check for that.
|
||||
IRUsage usage = IRNextFPRUsage(ar[reg - F0].mipsReg, info);
|
||||
|
||||
// Not awesome. A used reg. Let's try to avoid spilling.
|
||||
// TODO: Actually check if we'd be spilling.
|
||||
if (unusedOnly) {
|
||||
continue;
|
||||
// Awesome, a clobbered reg. Let's use it.
|
||||
if (usage == IRUsage::CLOBBERED) {
|
||||
*clobbered = true;
|
||||
return reg;
|
||||
}
|
||||
|
||||
return reg;
|
||||
// Not awesome. A used reg. Let's try to avoid spilling.
|
||||
if (!unusedOnly || usage == IRUsage::UNUSED) {
|
||||
// TODO: Use age or something to choose which register to spill?
|
||||
// TODO: Spill dirty regs first? or opposite?
|
||||
return reg;
|
||||
}
|
||||
}
|
||||
|
||||
return INVALID_REG;
|
||||
|
@ -46,8 +46,10 @@ public:
|
||||
~RiscVRegCacheFPU() {}
|
||||
|
||||
void Init(RiscVGen::RiscVEmitter *emitter);
|
||||
// TODO: Maybe pass in IR block and start PC for logging/debugging?
|
||||
void Start();
|
||||
void Start(MIPSComp::IRBlock *irBlock);
|
||||
void SetIRIndex(int index) {
|
||||
irIndex_ = index;
|
||||
}
|
||||
|
||||
// Protect the RISC-V register containing a MIPS register from spilling, to ensure that
|
||||
// it's being kept allocated.
|
||||
@ -89,6 +91,8 @@ private:
|
||||
MIPSState *mips_;
|
||||
RiscVGen::RiscVEmitter *emit_ = nullptr;
|
||||
MIPSComp::JitOptions *jo_;
|
||||
MIPSComp::IRBlock *irBlock_ = nullptr;
|
||||
int irIndex_ = 0;
|
||||
|
||||
enum {
|
||||
// On RiscV, each of the 32 registers are full 128-bit. No sharing of components!
|
||||
|
@ -302,6 +302,7 @@
|
||||
<ClInclude Include="..\..\Core\MIPS\IR\IRInst.h" />
|
||||
<ClInclude Include="..\..\Core\MIPS\IR\IRInterpreter.h" />
|
||||
<ClInclude Include="..\..\Core\MIPS\IR\IRJit.h" />
|
||||
<ClInclude Include="..\..\Core\MIPS\IR\IRAnalysis.h" />
|
||||
<ClInclude Include="..\..\Core\MIPS\IR\IRPassSimplify.h" />
|
||||
<ClInclude Include="..\..\Core\MIPS\IR\IRRegCache.h" />
|
||||
<ClInclude Include="..\..\Core\MIPS\JitCommon\JitBlockCache.h" />
|
||||
@ -561,6 +562,7 @@
|
||||
<ClCompile Include="..\..\Core\MIPS\IR\IRInst.cpp" />
|
||||
<ClCompile Include="..\..\Core\MIPS\IR\IRInterpreter.cpp" />
|
||||
<ClCompile Include="..\..\Core\MIPS\IR\IRJit.cpp" />
|
||||
<ClCompile Include="..\..\Core\MIPS\IR\IRAnalysis.cpp" />
|
||||
<ClCompile Include="..\..\Core\MIPS\IR\IRPassSimplify.cpp" />
|
||||
<ClCompile Include="..\..\Core\MIPS\IR\IRRegCache.cpp" />
|
||||
<ClCompile Include="..\..\Core\MIPS\JitCommon\JitBlockCache.cpp" />
|
||||
|
@ -645,6 +645,9 @@
|
||||
<ClCompile Include="..\..\Core\MIPS\IR\IRJit.cpp">
|
||||
<Filter>MIPS\IR</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Core\MIPS\IR\IRAnalysis.cpp">
|
||||
<Filter>MIPS\IR</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Core\MIPS\IR\IRPassSimplify.cpp">
|
||||
<Filter>MIPS\IR</Filter>
|
||||
</ClCompile>
|
||||
@ -1667,6 +1670,9 @@
|
||||
<ClInclude Include="..\..\Core\MIPS\IR\IRJit.h">
|
||||
<Filter>MIPS\IR</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\Core\MIPS\IR\IRAnalysis.h">
|
||||
<Filter>MIPS\IR</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\Core\MIPS\IR\IRPassSimplify.h">
|
||||
<Filter>MIPS\IR</Filter>
|
||||
</ClInclude>
|
||||
|
@ -390,6 +390,7 @@ EXEC_AND_LIB_FILES := \
|
||||
$(SRC)/Core/MIPS/MIPSVFPUFallbacks.cpp.arm \
|
||||
$(SRC)/Core/MIPS/MIPSCodeUtils.cpp.arm \
|
||||
$(SRC)/Core/MIPS/MIPSDebugInterface.cpp \
|
||||
$(SRC)/Core/MIPS/IR/IRAnalysis.cpp \
|
||||
$(SRC)/Core/MIPS/IR/IRFrontend.cpp \
|
||||
$(SRC)/Core/MIPS/IR/IRJit.cpp \
|
||||
$(SRC)/Core/MIPS/IR/IRCompALU.cpp \
|
||||
|
@ -671,6 +671,7 @@ SOURCES_CXX += \
|
||||
$(COREDIR)/MIPS/JitCommon/JitCommon.cpp \
|
||||
$(COREDIR)/MIPS/JitCommon/JitState.cpp \
|
||||
$(COREDIR)/MIPS/JitCommon/JitBlockCache.cpp \
|
||||
$(COREDIR)/MIPS/IR/IRAnalysis.cpp \
|
||||
$(COREDIR)/MIPS/IR/IRCompALU.cpp \
|
||||
$(COREDIR)/MIPS/IR/IRCompBranch.cpp \
|
||||
$(COREDIR)/MIPS/IR/IRCompFPU.cpp \
|
||||
|
Loading…
Reference in New Issue
Block a user