Stay inside block when it's branch target is itself.

This commit is contained in:
Jean-Philip Desjardins 2022-11-30 17:25:50 -05:00
parent e2683a6246
commit 930e90a9a2
8 changed files with 67 additions and 20 deletions

View file

@ -194,7 +194,23 @@ void CBasicBlock::CompileRange(CMipsJitter* jitter)
return; return;
} }
bool loopsOnItself = [&]() {
if(m_begin == m_end)
{
return false;
}
uint32 branchInstAddr = m_end - 4;
uint32 inst = m_context.m_pMemoryMap->GetInstruction(branchInstAddr);
if(m_context.m_pArch->IsInstructionBranch(&m_context, branchInstAddr, inst) != MIPS_BRANCH_NORMAL)
{
return false;
}
uint32 target = m_context.m_pArch->GetInstructionEffectiveAddress(&m_context, branchInstAddr, inst);
return target == m_begin;
}();
CompileProlog(jitter); CompileProlog(jitter);
jitter->MarkFirstBlockLabel();
for(uint32 address = m_begin; address <= m_end; address += 4) for(uint32 address = m_begin; address <= m_end; address += 4)
{ {
@ -206,8 +222,8 @@ void CBasicBlock::CompileRange(CMipsJitter* jitter)
assert(jitter->IsStackEmpty()); assert(jitter->IsStackEmpty());
} }
jitter->MarkFinalBlockLabel(); jitter->MarkLastBlockLabel();
CompileEpilog(jitter); CompileEpilog(jitter, loopsOnItself);
} }
void CBasicBlock::CompileProlog(CMipsJitter* jitter) void CBasicBlock::CompileProlog(CMipsJitter* jitter)
@ -228,7 +244,7 @@ void CBasicBlock::CompileProlog(CMipsJitter* jitter)
#endif #endif
} }
void CBasicBlock::CompileEpilog(CMipsJitter* jitter) void CBasicBlock::CompileEpilog(CMipsJitter* jitter, bool loopsOnItself)
{ {
//Update cycle quota //Update cycle quota
jitter->PushRel(offsetof(CMIPS, m_State.cycleQuota)); jitter->PushRel(offsetof(CMIPS, m_State.cycleQuota));
@ -258,15 +274,28 @@ void CBasicBlock::CompileEpilog(CMipsJitter* jitter)
jitter->PushCst(MIPS_INVALID_PC); jitter->PushCst(MIPS_INVALID_PC);
jitter->PullRel(offsetof(CMIPS, m_State.nDelayedJumpAddr)); jitter->PullRel(offsetof(CMIPS, m_State.nDelayedJumpAddr));
#if !defined(AOT_BUILD_CACHE) && !defined(__EMSCRIPTEN__) if(loopsOnItself)
jitter->PushRel(offsetof(CMIPS, m_State.nHasException));
jitter->PushCst(0);
jitter->BeginIf(Jitter::CONDITION_EQ);
{ {
jitter->JumpToDynamic(reinterpret_cast<void*>(&NextBlockTrampoline)); jitter->PushRel(offsetof(CMIPS, m_State.nHasException));
jitter->PushCst(0);
jitter->BeginIf(Jitter::CONDITION_EQ);
{
jitter->Goto(jitter->GetFirstBlockLabel());
}
jitter->EndIf();
} }
jitter->EndIf(); else
{
#if !defined(AOT_BUILD_CACHE) && !defined(__EMSCRIPTEN__)
jitter->PushRel(offsetof(CMIPS, m_State.nHasException));
jitter->PushCst(0);
jitter->BeginIf(Jitter::CONDITION_EQ);
{
jitter->JumpToDynamic(reinterpret_cast<void*>(&NextBlockTrampoline));
}
jitter->EndIf();
#endif #endif
}
} }
jitter->Else(); jitter->Else();
{ {

View file

@ -102,7 +102,7 @@ protected:
CMIPS& m_context; CMIPS& m_context;
virtual void CompileProlog(CMipsJitter*); virtual void CompileProlog(CMipsJitter*);
virtual void CompileEpilog(CMipsJitter*); virtual void CompileEpilog(CMipsJitter*, bool);
private: private:
void HandleExternalFunctionReference(uintptr_t, uint32, Jitter::CCodeGen::SYMBOL_REF_TYPE); void HandleExternalFunctionReference(uintptr_t, uint32, Jitter::CCodeGen::SYMBOL_REF_TYPE);

View file

@ -180,7 +180,7 @@ void CMIPSInstructionFactory::BranchLikely(Jitter::CONDITION condition)
} }
m_codeGen->Else(); m_codeGen->Else();
{ {
m_codeGen->Goto(m_codeGen->GetFinalBlockLabel()); m_codeGen->Goto(m_codeGen->GetLastBlockLabel());
} }
m_codeGen->EndIf(); m_codeGen->EndIf();
} }

View file

@ -4,6 +4,7 @@
CMipsJitter::CMipsJitter(Jitter::CCodeGen* codeGen) CMipsJitter::CMipsJitter(Jitter::CCodeGen* codeGen)
: CJitter(codeGen) : CJitter(codeGen)
, m_firstBlockLabel(-1)
, m_lastBlockLabel(-1) , m_lastBlockLabel(-1)
{ {
for(unsigned int i = 0; i < 4; i++) for(unsigned int i = 0; i < 4; i++)
@ -17,6 +18,7 @@ CMipsJitter::CMipsJitter(Jitter::CCodeGen* codeGen)
void CMipsJitter::Begin() void CMipsJitter::Begin()
{ {
CJitter::Begin(); CJitter::Begin();
m_firstBlockLabel = -1;
m_lastBlockLabel = -1; m_lastBlockLabel = -1;
} }
@ -63,7 +65,13 @@ void CMipsJitter::PushRel64(size_t offset)
} }
} }
Jitter::CJitter::LABEL CMipsJitter::GetFinalBlockLabel() Jitter::CJitter::LABEL CMipsJitter::GetFirstBlockLabel()
{
assert(m_firstBlockLabel != -1);
return m_firstBlockLabel;
}
Jitter::CJitter::LABEL CMipsJitter::GetLastBlockLabel()
{ {
if(m_lastBlockLabel == -1) if(m_lastBlockLabel == -1)
{ {
@ -72,7 +80,13 @@ Jitter::CJitter::LABEL CMipsJitter::GetFinalBlockLabel()
return m_lastBlockLabel; return m_lastBlockLabel;
} }
void CMipsJitter::MarkFinalBlockLabel() void CMipsJitter::MarkFirstBlockLabel()
{
m_firstBlockLabel = CreateLabel();
MarkLabel(m_firstBlockLabel);
}
void CMipsJitter::MarkLastBlockLabel()
{ {
if(m_lastBlockLabel != -1) if(m_lastBlockLabel != -1)
{ {

View file

@ -15,8 +15,11 @@ public:
void SetVariableAsConstant(size_t, uint32); void SetVariableAsConstant(size_t, uint32);
LABEL GetFinalBlockLabel(); LABEL GetFirstBlockLabel();
void MarkFinalBlockLabel(); LABEL GetLastBlockLabel();
void MarkFirstBlockLabel();
void MarkLastBlockLabel();
private: private:
struct VARIABLESTATUS struct VARIABLESTATUS
@ -31,5 +34,6 @@ private:
void SetVariableStatus(size_t, const VARIABLESTATUS&); void SetVariableStatus(size_t, const VARIABLESTATUS&);
VariableStatusMap m_variableStatus; VariableStatusMap m_variableStatus;
LABEL m_lastBlockLabel; LABEL m_firstBlockLabel = -1;
LABEL m_lastBlockLabel = -1;
}; };

View file

@ -1,6 +1,6 @@
#include "EeBasicBlock.h" #include "EeBasicBlock.h"
void CEeBasicBlock::CompileEpilog(CMipsJitter* jitter) void CEeBasicBlock::CompileEpilog(CMipsJitter* jitter, bool loopsOnItself)
{ {
if(IsIdleLoopBlock()) if(IsIdleLoopBlock())
{ {
@ -8,7 +8,7 @@ void CEeBasicBlock::CompileEpilog(CMipsJitter* jitter)
jitter->PullRel(offsetof(CMIPS, m_State.nHasException)); jitter->PullRel(offsetof(CMIPS, m_State.nHasException));
} }
CBasicBlock::CompileEpilog(jitter); CBasicBlock::CompileEpilog(jitter, loopsOnItself);
} }
bool CEeBasicBlock::IsIdleLoopBlock() const bool CEeBasicBlock::IsIdleLoopBlock() const

View file

@ -8,7 +8,7 @@ public:
using CBasicBlock::CBasicBlock; using CBasicBlock::CBasicBlock;
protected: protected:
void CompileEpilog(CMipsJitter*) override; void CompileEpilog(CMipsJitter*, bool) override;
private: private:
bool IsIdleLoopBlock() const; bool IsIdleLoopBlock() const;

View file

@ -217,7 +217,7 @@ void CVuBasicBlock::CompileRange(CMipsJitter* jitter)
jitter->PullRel(offsetof(CMIPS, m_State.pipeTime)); jitter->PullRel(offsetof(CMIPS, m_State.pipeTime));
} }
CompileEpilog(jitter); CompileEpilog(jitter, false);
} }
bool CVuBasicBlock::IsConditionalBranch(uint32 opcodeLo) bool CVuBasicBlock::IsConditionalBranch(uint32 opcodeLo)