JitRegCache: Add revertable binds

This commit is contained in:
MerryMage 2018-10-15 21:00:52 +01:00
parent 16f8b7413d
commit 590ec866b0
3 changed files with 85 additions and 7 deletions

View File

@ -41,6 +41,8 @@ public:
{ {
if (!away) if (!away)
{ {
ASSERT(!revertable);
if (location.IsImm()) if (location.IsImm())
return LocationType::SpeculativeImmediate; return LocationType::SpeculativeImmediate;
@ -63,6 +65,7 @@ public:
void SetFlushed() void SetFlushed()
{ {
ASSERT(!revertable);
away = false; away = false;
location = default_location; location = default_location;
} }
@ -73,6 +76,24 @@ public:
location = Gen::Imm32(imm32); location = Gen::Imm32(imm32);
} }
bool IsRevertable() const { return revertable; }
void SetRevertable()
{
ASSERT(IsBound());
revertable = true;
}
void SetRevert()
{
ASSERT(revertable);
revertable = false;
SetFlushed();
}
void SetCommit()
{
ASSERT(revertable);
revertable = false;
}
bool IsLocked() const { return locked > 0; } bool IsLocked() const { return locked > 0; }
void Lock() { locked++; } void Lock() { locked++; }
void Unlock() void Unlock()
@ -86,6 +107,7 @@ private:
Gen::OpArg default_location{}; Gen::OpArg default_location{};
Gen::OpArg location{}; Gen::OpArg location{};
bool away = false; // value not in source register bool away = false; // value not in source register
bool revertable = false;
size_t locked = 0; size_t locked = 0;
}; };
@ -139,6 +161,7 @@ public:
bool ShouldLoad() const { return read; } bool ShouldLoad() const { return read; }
bool ShouldDirty() const { return write; } bool ShouldDirty() const { return write; }
bool ShouldKillImmediate() const { return kill_imm; } bool ShouldKillImmediate() const { return kill_imm; }
bool ShouldBeRevertable() const { return revertable; }
void Realized() { realized = true; } void Realized() { realized = true; }
void RealizedBound() void RealizedBound()
@ -147,16 +170,17 @@ public:
bind = true; bind = true;
} }
void AddUse(RCMode mode) { AddConstraint(false, mode, false); } void AddUse(RCMode mode) { AddConstraint(false, mode, false, false); }
void AddUseNoImm(RCMode mode) { AddConstraint(false, mode, true); } void AddUseNoImm(RCMode mode) { AddConstraint(false, mode, true, false); }
void AddBind(RCMode mode) { AddConstraint(true, mode, false); } void AddBind(RCMode mode) { AddConstraint(true, mode, false, false); }
void AddRevertableBind(RCMode mode) { AddConstraint(true, mode, false, true); }
private: private:
void AddConstraint(bool should_bind, RCMode mode, bool should_kill_imm) void AddConstraint(bool should_bind, RCMode mode, bool should_kill_imm, bool should_revertable)
{ {
if (realized) if (realized)
{ {
ASSERT(IsCompatible(should_bind, mode, should_kill_imm)); ASSERT(IsCompatible(should_bind, mode, should_kill_imm, should_revertable));
return; return;
} }
@ -166,6 +190,9 @@ private:
if (should_kill_imm) if (should_kill_imm)
kill_imm = true; kill_imm = true;
if (should_revertable)
revertable = true;
switch (mode) switch (mode)
{ {
case RCMode::Read: case RCMode::Read:
@ -181,12 +208,14 @@ private:
} }
} }
bool IsCompatible(bool should_bind, RCMode mode, bool should_kill_imm) bool IsCompatible(bool should_bind, RCMode mode, bool should_kill_imm, bool should_revertable)
{ {
if (should_bind && !bind) if (should_bind && !bind)
return false; return false;
if (should_kill_imm && !kill_imm) if (should_kill_imm && !kill_imm)
return false; return false;
if (should_revertable && !revertable)
return false;
switch (mode) switch (mode)
{ {
@ -204,4 +233,5 @@ private:
bool write = false; bool write = false;
bool read = false; bool read = false;
bool kill_imm = false; bool kill_imm = false;
bool revertable = false;
}; };

View File

@ -328,6 +328,7 @@ void RegCache::Flush(FlushMode mode, BitSet32 regsToFlush)
{ {
ASSERT_MSG(DYNA_REC, !m_regs[i].IsLocked(), "Someone forgot to unlock PPC reg %u (X64 reg %i).", ASSERT_MSG(DYNA_REC, !m_regs[i].IsLocked(), "Someone forgot to unlock PPC reg %u (X64 reg %i).",
i, RX(i)); i, RX(i));
ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Register transaction is in progress!");
switch (m_regs[i].GetLocationType()) switch (m_regs[i].GetLocationType())
{ {
@ -373,7 +374,7 @@ bool RegCache::SanityCheck() const
break; break;
case PPCCachedReg::LocationType::Bound: case PPCCachedReg::LocationType::Bound:
{ {
if (m_regs[i].IsLocked()) if (m_regs[i].IsLocked() || m_regs[i].IsRevertable())
return false; return false;
Gen::X64Reg xr = m_regs[i].Location().GetSimpleReg(); Gen::X64Reg xr = m_regs[i].Location().GetSimpleReg();
@ -413,6 +414,7 @@ void RegCache::BindToRegister(preg_t i, bool doLoad, bool makeDirty)
ASSERT_MSG(DYNA_REC, !m_xregs[xr].IsDirty(), "Xreg %i already dirty", xr); ASSERT_MSG(DYNA_REC, !m_xregs[xr].IsDirty(), "Xreg %i already dirty", xr);
ASSERT_MSG(DYNA_REC, !m_xregs[xr].IsLocked(), "GetFreeXReg returned locked register"); ASSERT_MSG(DYNA_REC, !m_xregs[xr].IsLocked(), "GetFreeXReg returned locked register");
ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Invalid transaction state");
m_xregs[xr].SetBoundTo(i, makeDirty || m_regs[i].IsAway()); m_xregs[xr].SetBoundTo(i, makeDirty || m_regs[i].IsAway());
@ -441,6 +443,9 @@ void RegCache::BindToRegister(preg_t i, bool doLoad, bool makeDirty)
void RegCache::StoreFromRegister(preg_t i, FlushMode mode) void RegCache::StoreFromRegister(preg_t i, FlushMode mode)
{ {
// When a transaction is in progress, allowing the store would overwrite the old value.
ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Register transaction is in progress!");
bool doStore = false; bool doStore = false;
switch (m_regs[i].GetLocationType()) switch (m_regs[i].GetLocationType())
@ -611,6 +616,18 @@ RCX64Reg RegCache::Bind(preg_t preg, RCMode mode)
return RCX64Reg{this, preg}; return RCX64Reg{this, preg};
} }
RCX64Reg RegCache::BindOrImm(preg_t preg, RCMode mode)
{
m_constraints[preg].AddBindOrImm(mode);
return RCX64Reg{this, preg};
}
RCX64Reg RegCache::RevertableBind(preg_t preg, RCMode mode)
{
m_constraints[preg].AddRevertableBind(mode);
return RCX64Reg{this, preg};
}
RCX64Reg RegCache::Scratch(X64Reg xr) RCX64Reg RegCache::Scratch(X64Reg xr)
{ {
FlushX(xr); FlushX(xr);
@ -622,6 +639,26 @@ RCForkGuard RegCache::Fork()
return RCForkGuard{*this}; return RCForkGuard{*this};
} }
void RegCache::Revert()
{
ASSERT(IsAllUnlocked());
for (auto& reg : m_regs)
{
if (reg.IsRevertable())
reg.SetRevert();
}
}
void RegCache::Commit()
{
ASSERT(IsAllUnlocked());
for (auto& reg : m_regs)
{
if (reg.IsRevertable())
reg.SetCommit();
}
}
bool RegCache::IsAllUnlocked() const bool RegCache::IsAllUnlocked() const
{ {
return std::none_of(m_regs.begin(), m_regs.end(), [](const auto& r){ return r.IsLocked(); }) && return std::none_of(m_regs.begin(), m_regs.end(), [](const auto& r){ return r.IsLocked(); }) &&
@ -673,6 +710,14 @@ void RegCache::Realize(preg_t preg)
m_constraints[preg].RealizedBound(); m_constraints[preg].RealizedBound();
}; };
if (m_constraints[preg].ShouldBeRevertable())
{
StoreFromRegister(preg, FlushMode::MaintainState);
do_bind();
m_regs[preg].SetRevertable();
return;
}
if (m_constraints[preg].ShouldBind()) if (m_constraints[preg].ShouldBind())
{ {
do_bind(); do_bind();

View File

@ -235,9 +235,12 @@ public:
RCOpArg Use(preg_t preg, RCMode mode); RCOpArg Use(preg_t preg, RCMode mode);
RCOpArg UseNoImm(preg_t preg, RCMode mode); RCOpArg UseNoImm(preg_t preg, RCMode mode);
RCX64Reg Bind(preg_t preg, RCMode mode); RCX64Reg Bind(preg_t preg, RCMode mode);
RCX64Reg RevertableBind(preg_t preg, RCMode mode);
RCX64Reg Scratch(Gen::X64Reg xr); RCX64Reg Scratch(Gen::X64Reg xr);
RCForkGuard Fork(); RCForkGuard Fork();
void Revert();
void Commit();
bool IsAllUnlocked() const; bool IsAllUnlocked() const;