mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-12-16 04:09:39 +00:00
Jit: Update constant propagation during instruction
This commit makes the JIT set/clear the individual registers of ConstantPropagation immediately instead of at the end of the instruction. This is needed to prevent Jit64::ComputeRC, which reads from a register written to earlier during the same instruction, from reading back stale register values from ConstantPropagation in the next commit.
This commit is contained in:
parent
502b48a690
commit
4114a0b506
@ -370,6 +370,9 @@ void Jit64::FallBackToInterpreter(UGeckoInstruction inst)
|
|||||||
gpr.Reset(js.op->regsOut);
|
gpr.Reset(js.op->regsOut);
|
||||||
fpr.Reset(js.op->GetFregsOut());
|
fpr.Reset(js.op->GetFregsOut());
|
||||||
|
|
||||||
|
// We must also update constant propagation
|
||||||
|
m_constant_propagation.ClearGPRs(js.op->regsOut);
|
||||||
|
|
||||||
if (js.op->opinfo->flags & FL_SET_MSR)
|
if (js.op->opinfo->flags & FL_SET_MSR)
|
||||||
EmitUpdateMembase();
|
EmitUpdateMembase();
|
||||||
|
|
||||||
@ -1133,8 +1136,6 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CompileInstruction(op);
|
CompileInstruction(op);
|
||||||
|
|
||||||
m_constant_propagation.ClearGPRs(op.regsOut);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_constant_propagation.Apply(constant_propagation_result);
|
m_constant_propagation.Apply(constant_propagation_result);
|
||||||
|
|||||||
@ -84,6 +84,8 @@ public:
|
|||||||
|
|
||||||
void FlushRegistersBeforeSlowAccess();
|
void FlushRegistersBeforeSlowAccess();
|
||||||
|
|
||||||
|
JitCommon::ConstantPropagation& GetConstantPropagation() { return m_constant_propagation; }
|
||||||
|
|
||||||
JitBlockCache* GetBlockCache() override { return &blocks; }
|
JitBlockCache* GetBlockCache() override { return &blocks; }
|
||||||
void Trace();
|
void Trace();
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,11 @@ void FPURegCache::LoadRegister(preg_t preg, X64Reg new_loc)
|
|||||||
m_emitter->MOVAPD(new_loc, m_regs[preg].Location().value());
|
m_emitter->MOVAPD(new_loc, m_regs[preg].Location().value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FPURegCache::DiscardImm(preg_t preg)
|
||||||
|
{
|
||||||
|
// FPURegCache doesn't support immediates, so no need to do anything
|
||||||
|
}
|
||||||
|
|
||||||
std::span<const X64Reg> FPURegCache::GetAllocationOrder() const
|
std::span<const X64Reg> FPURegCache::GetAllocationOrder() const
|
||||||
{
|
{
|
||||||
static constexpr X64Reg allocation_order[] = {XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12,
|
static constexpr X64Reg allocation_order[] = {XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12,
|
||||||
|
|||||||
@ -16,6 +16,7 @@ protected:
|
|||||||
Gen::OpArg GetDefaultLocation(preg_t preg) const override;
|
Gen::OpArg GetDefaultLocation(preg_t preg) const override;
|
||||||
void StoreRegister(preg_t preg, const Gen::OpArg& newLoc) override;
|
void StoreRegister(preg_t preg, const Gen::OpArg& newLoc) override;
|
||||||
void LoadRegister(preg_t preg, Gen::X64Reg newLoc) override;
|
void LoadRegister(preg_t preg, Gen::X64Reg newLoc) override;
|
||||||
|
void DiscardImm(preg_t preg) override;
|
||||||
std::span<const Gen::X64Reg> GetAllocationOrder() const override;
|
std::span<const Gen::X64Reg> GetAllocationOrder() const override;
|
||||||
BitSet32 GetRegUtilization() const override;
|
BitSet32 GetRegUtilization() const override;
|
||||||
BitSet32 CountRegsIn(preg_t preg, u32 lookahead) const override;
|
BitSet32 CountRegsIn(preg_t preg, u32 lookahead) const override;
|
||||||
|
|||||||
@ -25,6 +25,11 @@ void GPRRegCache::LoadRegister(preg_t preg, X64Reg new_loc)
|
|||||||
m_emitter->MOV(32, ::Gen::R(new_loc), m_regs[preg].Location().value());
|
m_emitter->MOV(32, ::Gen::R(new_loc), m_regs[preg].Location().value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPRRegCache::DiscardImm(preg_t preg)
|
||||||
|
{
|
||||||
|
m_jit.GetConstantPropagation().ClearGPR(preg);
|
||||||
|
}
|
||||||
|
|
||||||
OpArg GPRRegCache::GetDefaultLocation(preg_t preg) const
|
OpArg GPRRegCache::GetDefaultLocation(preg_t preg) const
|
||||||
{
|
{
|
||||||
return PPCSTATE_GPR(preg);
|
return PPCSTATE_GPR(preg);
|
||||||
@ -50,6 +55,7 @@ void GPRRegCache::SetImmediate32(preg_t preg, u32 imm_value, bool dirty)
|
|||||||
// processing speculative constants.
|
// processing speculative constants.
|
||||||
DiscardRegContentsIfCached(preg);
|
DiscardRegContentsIfCached(preg);
|
||||||
m_regs[preg].SetToImm32(imm_value, dirty);
|
m_regs[preg].SetToImm32(imm_value, dirty);
|
||||||
|
m_jit.GetConstantPropagation().SetGPR(preg, imm_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
BitSet32 GPRRegCache::GetRegUtilization() const
|
BitSet32 GPRRegCache::GetRegUtilization() const
|
||||||
|
|||||||
@ -17,6 +17,7 @@ protected:
|
|||||||
Gen::OpArg GetDefaultLocation(preg_t preg) const override;
|
Gen::OpArg GetDefaultLocation(preg_t preg) const override;
|
||||||
void StoreRegister(preg_t preg, const Gen::OpArg& new_loc) override;
|
void StoreRegister(preg_t preg, const Gen::OpArg& new_loc) override;
|
||||||
void LoadRegister(preg_t preg, Gen::X64Reg new_loc) override;
|
void LoadRegister(preg_t preg, Gen::X64Reg new_loc) override;
|
||||||
|
void DiscardImm(preg_t preg) override;
|
||||||
std::span<const Gen::X64Reg> GetAllocationOrder() const override;
|
std::span<const Gen::X64Reg> GetAllocationOrder() const override;
|
||||||
BitSet32 GetRegUtilization() const override;
|
BitSet32 GetRegUtilization() const override;
|
||||||
BitSet32 CountRegsIn(preg_t preg, u32 lookahead) const override;
|
BitSet32 CountRegsIn(preg_t preg, u32 lookahead) const override;
|
||||||
|
|||||||
@ -536,6 +536,9 @@ void RegCache::BindToRegister(preg_t i, bool doLoad, bool makeDirty)
|
|||||||
m_xregs[RX(i)].MakeDirty();
|
m_xregs[RX(i)].MakeDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (makeDirty)
|
||||||
|
DiscardImm(i);
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, !m_xregs[RX(i)].IsLocked(),
|
ASSERT_MSG(DYNA_REC, !m_xregs[RX(i)].IsLocked(),
|
||||||
"WTF, this reg ({} -> {}) should have been flushed", i, Common::ToUnderlying(RX(i)));
|
"WTF, this reg ({} -> {}) should have been flushed", i, Common::ToUnderlying(RX(i)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -193,6 +193,7 @@ protected:
|
|||||||
virtual Gen::OpArg GetDefaultLocation(preg_t preg) const = 0;
|
virtual Gen::OpArg GetDefaultLocation(preg_t preg) const = 0;
|
||||||
virtual void StoreRegister(preg_t preg, const Gen::OpArg& new_loc) = 0;
|
virtual void StoreRegister(preg_t preg, const Gen::OpArg& new_loc) = 0;
|
||||||
virtual void LoadRegister(preg_t preg, Gen::X64Reg new_loc) = 0;
|
virtual void LoadRegister(preg_t preg, Gen::X64Reg new_loc) = 0;
|
||||||
|
virtual void DiscardImm(preg_t preg) = 0;
|
||||||
|
|
||||||
virtual std::span<const Gen::X64Reg> GetAllocationOrder() const = 0;
|
virtual std::span<const Gen::X64Reg> GetAllocationOrder() const = 0;
|
||||||
|
|
||||||
|
|||||||
@ -279,6 +279,9 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
|
|||||||
fpr.ResetRegisters(js.op->GetFregsOut());
|
fpr.ResetRegisters(js.op->GetFregsOut());
|
||||||
gpr.ResetCRRegisters(js.op->crOut);
|
gpr.ResetCRRegisters(js.op->crOut);
|
||||||
|
|
||||||
|
// We must also update constant propagation
|
||||||
|
m_constant_propagation.ClearGPRs(js.op->regsOut);
|
||||||
|
|
||||||
if (js.op->opinfo->flags & FL_SET_MSR)
|
if (js.op->opinfo->flags & FL_SET_MSR)
|
||||||
EmitUpdateMembase();
|
EmitUpdateMembase();
|
||||||
|
|
||||||
@ -1354,12 +1357,8 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
|||||||
m_constant_propagation.EvaluateInstruction(op.inst, opinfo->flags);
|
m_constant_propagation.EvaluateInstruction(op.inst, opinfo->flags);
|
||||||
|
|
||||||
if (!constant_propagation_result.instruction_fully_executed)
|
if (!constant_propagation_result.instruction_fully_executed)
|
||||||
{
|
|
||||||
CompileInstruction(op);
|
CompileInstruction(op);
|
||||||
|
|
||||||
m_constant_propagation.ClearGPRs(op.regsOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_constant_propagation.Apply(constant_propagation_result);
|
m_constant_propagation.Apply(constant_propagation_result);
|
||||||
|
|
||||||
if (constant_propagation_result.gpr >= 0)
|
if (constant_propagation_result.gpr >= 0)
|
||||||
|
|||||||
@ -36,6 +36,8 @@ public:
|
|||||||
void Init() override;
|
void Init() override;
|
||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
|
|
||||||
|
JitCommon::ConstantPropagation& GetConstantPropagation() { return m_constant_propagation; }
|
||||||
|
|
||||||
JitBaseBlockCache* GetBlockCache() override { return &blocks; }
|
JitBaseBlockCache* GetBlockCache() override { return &blocks; }
|
||||||
bool IsInCodeSpace(const u8* ptr) const { return IsInSpace(ptr); }
|
bool IsInCodeSpace(const u8* ptr) const { return IsInSpace(ptr); }
|
||||||
bool HandleFault(uintptr_t access_address, SContext* ctx) override;
|
bool HandleFault(uintptr_t access_address, SContext* ctx) override;
|
||||||
|
|||||||
@ -381,6 +381,7 @@ void Arm64GPRCache::SetImmediateInternal(size_t index, u32 imm, bool dirty)
|
|||||||
UnlockRegister(EncodeRegTo32(reg.GetReg()));
|
UnlockRegister(EncodeRegTo32(reg.GetReg()));
|
||||||
reg.LoadToImm(imm);
|
reg.LoadToImm(imm);
|
||||||
reg.SetDirty(dirty);
|
reg.SetDirty(dirty);
|
||||||
|
m_jit->GetConstantPropagation().SetGPR(index - GUEST_GPR_OFFSET, imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arm64GPRCache::BindForWrite(size_t index, bool will_read, bool will_write)
|
void Arm64GPRCache::BindForWrite(size_t index, bool will_read, bool will_write)
|
||||||
@ -388,6 +389,7 @@ void Arm64GPRCache::BindForWrite(size_t index, bool will_read, bool will_write)
|
|||||||
GuestRegInfo guest_reg = GetGuestByIndex(index);
|
GuestRegInfo guest_reg = GetGuestByIndex(index);
|
||||||
OpArg& reg = guest_reg.reg;
|
OpArg& reg = guest_reg.reg;
|
||||||
const size_t bitsize = guest_reg.bitsize;
|
const size_t bitsize = guest_reg.bitsize;
|
||||||
|
const bool is_gpr = index >= GUEST_GPR_OFFSET && index < GUEST_GPR_OFFSET + GUEST_GPR_COUNT;
|
||||||
|
|
||||||
reg.ResetLastUsed();
|
reg.ResetLastUsed();
|
||||||
|
|
||||||
@ -414,12 +416,13 @@ void Arm64GPRCache::BindForWrite(size_t index, bool will_read, bool will_write)
|
|||||||
m_emit->MOVI2R(host_reg, reg.GetImm());
|
m_emit->MOVI2R(host_reg, reg.GetImm());
|
||||||
}
|
}
|
||||||
reg.Load(host_reg);
|
reg.Load(host_reg);
|
||||||
if (will_write)
|
|
||||||
reg.SetDirty(true);
|
|
||||||
}
|
}
|
||||||
else if (will_write)
|
|
||||||
|
if (will_write)
|
||||||
{
|
{
|
||||||
reg.SetDirty(true);
|
reg.SetDirty(true);
|
||||||
|
if (is_gpr)
|
||||||
|
m_jit->GetConstantPropagation().ClearGPR(index - GUEST_GPR_OFFSET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user