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;
}
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);
jitter->MarkFirstBlockLabel();
for(uint32 address = m_begin; address <= m_end; address += 4)
{
@ -206,8 +222,8 @@ void CBasicBlock::CompileRange(CMipsJitter* jitter)
assert(jitter->IsStackEmpty());
}
jitter->MarkFinalBlockLabel();
CompileEpilog(jitter);
jitter->MarkLastBlockLabel();
CompileEpilog(jitter, loopsOnItself);
}
void CBasicBlock::CompileProlog(CMipsJitter* jitter)
@ -228,7 +244,7 @@ void CBasicBlock::CompileProlog(CMipsJitter* jitter)
#endif
}
void CBasicBlock::CompileEpilog(CMipsJitter* jitter)
void CBasicBlock::CompileEpilog(CMipsJitter* jitter, bool loopsOnItself)
{
//Update cycle quota
jitter->PushRel(offsetof(CMIPS, m_State.cycleQuota));
@ -258,15 +274,28 @@ void CBasicBlock::CompileEpilog(CMipsJitter* jitter)
jitter->PushCst(MIPS_INVALID_PC);
jitter->PullRel(offsetof(CMIPS, m_State.nDelayedJumpAddr));
#if !defined(AOT_BUILD_CACHE) && !defined(__EMSCRIPTEN__)
jitter->PushRel(offsetof(CMIPS, m_State.nHasException));
jitter->PushCst(0);
jitter->BeginIf(Jitter::CONDITION_EQ);
if(loopsOnItself)
{
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
}
}
jitter->Else();
{

View file

@ -102,7 +102,7 @@ protected:
CMIPS& m_context;
virtual void CompileProlog(CMipsJitter*);
virtual void CompileEpilog(CMipsJitter*);
virtual void CompileEpilog(CMipsJitter*, bool);
private:
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->Goto(m_codeGen->GetFinalBlockLabel());
m_codeGen->Goto(m_codeGen->GetLastBlockLabel());
}
m_codeGen->EndIf();
}

View file

@ -4,6 +4,7 @@
CMipsJitter::CMipsJitter(Jitter::CCodeGen* codeGen)
: CJitter(codeGen)
, m_firstBlockLabel(-1)
, m_lastBlockLabel(-1)
{
for(unsigned int i = 0; i < 4; i++)
@ -17,6 +18,7 @@ CMipsJitter::CMipsJitter(Jitter::CCodeGen* codeGen)
void CMipsJitter::Begin()
{
CJitter::Begin();
m_firstBlockLabel = -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)
{
@ -72,7 +80,13 @@ Jitter::CJitter::LABEL CMipsJitter::GetFinalBlockLabel()
return m_lastBlockLabel;
}
void CMipsJitter::MarkFinalBlockLabel()
void CMipsJitter::MarkFirstBlockLabel()
{
m_firstBlockLabel = CreateLabel();
MarkLabel(m_firstBlockLabel);
}
void CMipsJitter::MarkLastBlockLabel()
{
if(m_lastBlockLabel != -1)
{

View file

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

View file

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

View file

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

View file

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