Merge pull request #19193 from hrydgard/ir-interpreter-opts

IRInterpreter: Enable some optimizations that accidentally were only enabled on non-ARM64.
This commit is contained in:
Henrik Rydgård 2024-05-26 14:52:50 +02:00 committed by GitHub
commit 84d9e30c0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 53 additions and 21 deletions

View File

@ -44,6 +44,7 @@ Arm64JitBackend::Arm64JitBackend(JitOptions &jitopt, IRBlockCache &blocks)
if (((intptr_t)Memory::base & 0x00000000FFFFFFFFUL) != 0) { if (((intptr_t)Memory::base & 0x00000000FFFFFFFFUL) != 0) {
jo.enablePointerify = false; jo.enablePointerify = false;
} }
jo.optimizeForInterpreter = false;
#ifdef MASKED_PSP_MEMORY #ifdef MASKED_PSP_MEMORY
jo.enablePointerify = false; jo.enablePointerify = false;
#endif #endif

View File

@ -277,7 +277,7 @@ void IRFrontend::DoJit(u32 em_address, std::vector<IRInst> &instructions, u32 &m
IRWriter simplified; IRWriter simplified;
IRWriter *code = &ir; IRWriter *code = &ir;
if (!js.hadBreakpoints) { if (!js.hadBreakpoints) {
static const IRPassFunc passes[] = { std::vector<IRPassFunc> passes{
&ApplyMemoryValidation, &ApplyMemoryValidation,
&RemoveLoadStoreLeftRight, &RemoveLoadStoreLeftRight,
&OptimizeFPMoves, &OptimizeFPMoves,
@ -288,7 +288,12 @@ void IRFrontend::DoJit(u32 em_address, std::vector<IRInst> &instructions, u32 &m
// &MergeLoadStore, // &MergeLoadStore,
// &ThreeOpToTwoOp, // &ThreeOpToTwoOp,
}; };
if (IRApplyPasses(passes, ARRAY_SIZE(passes), ir, simplified, opts))
if (opts.optimizeForInterpreter) {
// Add special passes here.
// passes.push_back(&ReorderLoadStore);
}
if (IRApplyPasses(passes.data(), passes.size(), ir, simplified, opts))
logBlocks = 1; logBlocks = 1;
code = &simplified; code = &simplified;
//if (ir.GetInstructions().size() >= 24) //if (ir.GetInstructions().size() >= 24)

View File

@ -405,6 +405,7 @@ struct IROptions {
bool unalignedLoadStoreVec4; bool unalignedLoadStoreVec4;
bool preferVec4; bool preferVec4;
bool preferVec4Dot; bool preferVec4Dot;
bool optimizeForInterpreter;
}; };
const IRMeta *GetIRMeta(IROp op); const IRMeta *GetIRMeta(IROp op);

View File

@ -48,6 +48,8 @@ IRJit::IRJit(MIPSState *mipsState) : frontend_(mipsState->HasDefaultPrefix()), m
// blTrampolines_ = kernelMemory.Alloc(size, true, "trampoline"); // blTrampolines_ = kernelMemory.Alloc(size, true, "trampoline");
InitIR(); InitIR();
jo.optimizeForInterpreter = true;
IROptions opts{}; IROptions opts{};
opts.disableFlags = g_Config.uJitDisableFlags; opts.disableFlags = g_Config.uJitDisableFlags;
#if PPSSPP_ARCH(RISCV64) #if PPSSPP_ARCH(RISCV64)
@ -55,7 +57,7 @@ IRJit::IRJit(MIPSState *mipsState) : frontend_(mipsState->HasDefaultPrefix()), m
opts.unalignedLoadStore = false; opts.unalignedLoadStore = false;
opts.unalignedLoadStoreVec4 = true; opts.unalignedLoadStoreVec4 = true;
opts.preferVec4 = cpu_info.RiscV_V; opts.preferVec4 = cpu_info.RiscV_V;
#elif PPSSPP_ARCH(ARM) #elif PPSSPP_ARCH(ARM) || PPSSPP_ARCH(ARM64)
opts.unalignedLoadStore = (opts.disableFlags & (uint32_t)JitDisable::LSU_UNALIGNED) == 0; opts.unalignedLoadStore = (opts.disableFlags & (uint32_t)JitDisable::LSU_UNALIGNED) == 0;
opts.unalignedLoadStoreVec4 = true; opts.unalignedLoadStoreVec4 = true;
opts.preferVec4 = cpu_info.bASIMD || cpu_info.bNEON; opts.preferVec4 = cpu_info.bASIMD || cpu_info.bNEON;
@ -65,6 +67,7 @@ IRJit::IRJit(MIPSState *mipsState) : frontend_(mipsState->HasDefaultPrefix()), m
opts.unalignedLoadStoreVec4 = false; opts.unalignedLoadStoreVec4 = false;
opts.preferVec4 = true; opts.preferVec4 = true;
#endif #endif
opts.optimizeForInterpreter = jo.optimizeForInterpreter;
frontend_.SetOptions(opts); frontend_.SetOptions(opts);
} }
@ -143,7 +146,7 @@ bool IRJit::CompileBlock(u32 em_address, std::vector<IRInst> &instructions, u32
IRBlock *b = blocks_.GetBlock(block_num); IRBlock *b = blocks_.GetBlock(block_num);
b->SetInstructions(instructions); b->SetInstructions(instructions);
b->SetOriginalSize(mipsBytes); b->SetOriginalAddrSize(em_address, mipsBytes);
if (preload) { if (preload) {
// Hash, then only update page stats, don't link yet. // Hash, then only update page stats, don't link yet.
// TODO: Should we always hash? Then we can reuse blocks. // TODO: Should we always hash? Then we can reuse blocks.

View File

@ -69,7 +69,8 @@ public:
bool HasOriginalFirstOp() const; bool HasOriginalFirstOp() const;
bool RestoreOriginalFirstOp(int number); bool RestoreOriginalFirstOp(int number);
bool IsValid() const { return origAddr_ != 0 && origFirstOpcode_.encoding != 0x68FFFFFF; } bool IsValid() const { return origAddr_ != 0 && origFirstOpcode_.encoding != 0x68FFFFFF; }
void SetOriginalSize(u32 size) { void SetOriginalAddrSize(u32 address, u32 size) {
origAddr_ = address;
origSize_ = size; origSize_ = size;
} }
void SetTargetOffset(int offset) { void SetTargetOffset(int offset) {
@ -114,25 +115,28 @@ public:
IRBlockCache() {} IRBlockCache() {}
void Clear(); void Clear();
std::vector<int> FindInvalidatedBlockNumbers(u32 address, u32 length); std::vector<int> FindInvalidatedBlockNumbers(u32 address, u32 length);
void FinalizeBlock(int i, bool preload = false); void FinalizeBlock(int blockNum, bool preload = false);
int GetNumBlocks() const override { return (int)blocks_.size(); } int GetNumBlocks() const override { return (int)blocks_.size(); }
int AllocateBlock(int emAddr) { int AllocateBlock(int emAddr) {
blocks_.push_back(IRBlock(emAddr)); blocks_.push_back(IRBlock(emAddr));
return (int)blocks_.size() - 1; return (int)blocks_.size() - 1;
} }
IRBlock *GetBlock(int i) { IRBlock *GetBlock(int blockNum) {
if (i >= 0 && i < (int)blocks_.size()) { if (blockNum >= 0 && blockNum < (int)blocks_.size()) {
return &blocks_[i]; return &blocks_[blockNum];
} else { } else {
return nullptr; return nullptr;
} }
} }
IRBlock *GetBlockUnchecked(int i) { bool IsValidBlock(int blockNum) const override {
return &blocks_[i]; return blockNum < (int)blocks_.size() && blocks_[blockNum].IsValid();
} }
const IRBlock *GetBlock(int i) const { IRBlock *GetBlockUnchecked(int blockNum) {
if (i >= 0 && i < (int)blocks_.size()) { return &blocks_[blockNum];
return &blocks_[i]; }
const IRBlock *GetBlock(int blockNum) const {
if (blockNum >= 0 && blockNum < (int)blocks_.size()) {
return &blocks_[blockNum];
} else { } else {
return nullptr; return nullptr;
} }

View File

@ -714,6 +714,10 @@ void IRNativeBlockCacheDebugInterface::Init(const IRNativeBackend *backend) {
backend_ = backend; backend_ = backend;
} }
bool IRNativeBlockCacheDebugInterface::IsValidBlock(int blockNum) const {
return irBlocks_.IsValidBlock(blockNum);
}
int IRNativeBlockCacheDebugInterface::GetNumBlocks() const { int IRNativeBlockCacheDebugInterface::GetNumBlocks() const {
return irBlocks_.GetNumBlocks(); return irBlocks_.GetNumBlocks();
} }

View File

@ -162,10 +162,11 @@ class IRNativeBlockCacheDebugInterface : public JitBlockCacheDebugInterface {
public: public:
IRNativeBlockCacheDebugInterface(const MIPSComp::IRBlockCache &irBlocks); IRNativeBlockCacheDebugInterface(const MIPSComp::IRBlockCache &irBlocks);
void Init(const IRNativeBackend *backend); void Init(const IRNativeBackend *backend);
int GetNumBlocks() const; int GetNumBlocks() const override;
int GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly = true) const; int GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly = true) const override;
JitBlockDebugInfo GetBlockDebugInfo(int blockNum) const; JitBlockDebugInfo GetBlockDebugInfo(int blockNum) const override;
void ComputeStats(BlockCacheStats &bcStats) const; void ComputeStats(BlockCacheStats &bcStats) const override;
bool IsValidBlock(int blockNum) const override;
private: private:
void GetBlockCodeRange(int blockNum, int *startOffset, int *size) const; void GetBlockCodeRange(int blockNum, int *startOffset, int *size) const;

View File

@ -109,6 +109,7 @@ public:
virtual int GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly = true) const = 0; virtual int GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly = true) const = 0;
virtual JitBlockDebugInfo GetBlockDebugInfo(int blockNum) const = 0; virtual JitBlockDebugInfo GetBlockDebugInfo(int blockNum) const = 0;
virtual void ComputeStats(BlockCacheStats &bcStats) const = 0; virtual void ComputeStats(BlockCacheStats &bcStats) const = 0;
virtual bool IsValidBlock(int blockNum) const = 0;
virtual ~JitBlockCacheDebugInterface() {} virtual ~JitBlockCacheDebugInterface() {}
}; };
@ -164,6 +165,7 @@ public:
void RestoreSavedEmuHackOps(const std::vector<u32> &saved); void RestoreSavedEmuHackOps(const std::vector<u32> &saved);
int GetNumBlocks() const override { return num_blocks_; } int GetNumBlocks() const override { return num_blocks_; }
bool IsValidBlock(int blockNum) const override { return blockNum < num_blocks_ && !blocks_[blockNum].invalid; }
static int GetBlockExitSize(); static int GetBlockExitSize();

View File

@ -237,6 +237,8 @@ namespace MIPSComp {
// ARM64 and RV64 // ARM64 and RV64
bool useStaticAlloc; bool useStaticAlloc;
bool enablePointerify; bool enablePointerify;
// IR Interpreter
bool optimizeForInterpreter;
// Common // Common
bool enableBlocklink; bool enableBlocklink;
@ -245,6 +247,4 @@ namespace MIPSComp {
bool continueJumps; bool continueJumps;
int continueMaxInstructions; int continueMaxInstructions;
}; };
} }

View File

@ -39,6 +39,7 @@ RiscVJitBackend::RiscVJitBackend(JitOptions &jitopt, IRBlockCache &blocks)
if (((intptr_t)Memory::base & 0x00000000FFFFFFFFUL) != 0) { if (((intptr_t)Memory::base & 0x00000000FFFFFFFFUL) != 0) {
jo.enablePointerify = false; jo.enablePointerify = false;
} }
jo.optimizeForInterpreter = false;
// Since we store the offset, this is as big as it can be. // Since we store the offset, this is as big as it can be.
// We could shift off one bit to double it, would need to change RiscVAsm. // We could shift off one bit to double it, would need to change RiscVAsm.

View File

@ -41,6 +41,7 @@ X64JitBackend::X64JitBackend(JitOptions &jitopt, IRBlockCache &blocks)
if (((intptr_t)Memory::base & 0x00000000FFFFFFFFUL) != 0) { if (((intptr_t)Memory::base & 0x00000000FFFFFFFFUL) != 0) {
jo.enablePointerify = false; jo.enablePointerify = false;
} }
jo.optimizeForInterpreter = false;
// Since we store the offset, this is as big as it can be. // Since we store the offset, this is as big as it can be.
AllocCodeSpace(1024 * 1024 * 16); AllocCodeSpace(1024 * 1024 * 16);

View File

@ -1060,6 +1060,9 @@ void JitCompareScreen::UpdateDisasm() {
} }
JitBlockCacheDebugInterface *blockCacheDebug = MIPSComp::jit->GetBlockCacheDebugInterface(); JitBlockCacheDebugInterface *blockCacheDebug = MIPSComp::jit->GetBlockCacheDebugInterface();
if (!blockCacheDebug->IsValidBlock(currentBlock_)) {
return;
}
char temp[256]; char temp[256];
snprintf(temp, sizeof(temp), "%i/%i", currentBlock_, blockCacheDebug->GetNumBlocks()); snprintf(temp, sizeof(temp), "%i/%i", currentBlock_, blockCacheDebug->GetNumBlocks());
@ -1205,7 +1208,13 @@ UI::EventReturn JitCompareScreen::OnRandomBlock(UI::EventParams &e) {
int numBlocks = blockCache->GetNumBlocks(); int numBlocks = blockCache->GetNumBlocks();
if (numBlocks > 0) { if (numBlocks > 0) {
currentBlock_ = rand() % numBlocks; int tries = 100;
while (tries-- > 0) {
currentBlock_ = rand() % numBlocks;
if (blockCache->IsValidBlock(currentBlock_)) {
break;
}
}
} }
UpdateDisasm(); UpdateDisasm();
return UI::EVENT_DONE; return UI::EVENT_DONE;