diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index 03d8e2af7a..ce53909f8d 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -327,14 +327,6 @@ void Jit64::reg_imm(UGeckoInstruction inst) case 24: // ori case 25: // oris { - // check for nop - if (a == s && inst.UIMM == 0) - { - // Make the nop visible in the generated code. not much use but interesting if we see one. - NOP(); - return; - } - const u32 immediate = inst.OPCD == 24 ? inst.UIMM : inst.UIMM << 16; regimmop(a, s, true, immediate, Or, &XEmitter::OR); break; @@ -348,13 +340,6 @@ void Jit64::reg_imm(UGeckoInstruction inst) case 26: // xori case 27: // xoris { - if (s == a && inst.UIMM == 0) - { - // Make the nop visible in the generated code. - NOP(); - return; - } - const u32 immediate = inst.OPCD == 26 ? inst.UIMM : inst.UIMM << 16; regimmop(a, s, true, immediate, Xor, &XEmitter::XOR, false); break; diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index 40833f1814..85189cd31c 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -370,7 +370,7 @@ protected: void LoadCarry(); void FlushCarry(); - void reg_imm(u32 d, u32 a, u32 value, u32 (*do_op)(u32, u32), + void reg_imm(u32 d, u32 a, u32 value, void (ARM64XEmitter::*op)(Arm64Gen::ARM64Reg, Arm64Gen::ARM64Reg, u64, Arm64Gen::ARM64Reg), bool Rc = false); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index d1e41a80f6..05815710f1 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -159,41 +159,17 @@ void JitArm64::FlushCarry() js.carryFlag = CarryFlag::InPPCState; } -void JitArm64::reg_imm(u32 d, u32 a, u32 value, u32 (*do_op)(u32, u32), +void JitArm64::reg_imm(u32 d, u32 a, u32 value, void (ARM64XEmitter::*op)(ARM64Reg, ARM64Reg, u64, ARM64Reg), bool Rc) { - if (gpr.IsImm(a)) + gpr.BindToRegister(d, d == a); { - gpr.SetImmediate(d, do_op(gpr.GetImm(a), value)); - if (Rc) - ComputeRC0(gpr.GetImm(d)); + auto WA = gpr.GetScopedReg(); + (this->*op)(gpr.R(d), gpr.R(a), value, WA); } - else - { - gpr.BindToRegister(d, d == a); - { - auto WA = gpr.GetScopedReg(); - (this->*op)(gpr.R(d), gpr.R(a), value, WA); - } - if (Rc) - ComputeRC0(gpr.R(d)); - } -} - -static constexpr u32 BitOR(u32 a, u32 b) -{ - return a | b; -} - -static constexpr u32 BitAND(u32 a, u32 b) -{ - return a & b; -} - -static constexpr u32 BitXOR(u32 a, u32 b) -{ - return a ^ b; + if (Rc) + ComputeRC0(gpr.R(d)); } void JitArm64::arith_imm(UGeckoInstruction inst) @@ -207,34 +183,21 @@ void JitArm64::arith_imm(UGeckoInstruction inst) case 24: // ori case 25: // oris { - // check for nop - if (a == s && inst.UIMM == 0) - { - // NOP - return; - } - const u32 immediate = inst.OPCD == 24 ? inst.UIMM : inst.UIMM << 16; - reg_imm(a, s, immediate, BitOR, &ARM64XEmitter::ORRI2R); + reg_imm(a, s, immediate, &ARM64XEmitter::ORRI2R); break; } case 28: // andi - reg_imm(a, s, inst.UIMM, BitAND, &ARM64XEmitter::ANDI2R, true); + reg_imm(a, s, inst.UIMM, &ARM64XEmitter::ANDI2R, true); break; case 29: // andis - reg_imm(a, s, inst.UIMM << 16, BitAND, &ARM64XEmitter::ANDI2R, true); + reg_imm(a, s, inst.UIMM << 16, &ARM64XEmitter::ANDI2R, true); break; case 26: // xori case 27: // xoris { - if (a == s && inst.UIMM == 0) - { - // NOP - return; - } - const u32 immediate = inst.OPCD == 26 ? inst.UIMM : inst.UIMM << 16; - reg_imm(a, s, immediate, BitXOR, &ARM64XEmitter::EORI2R); + reg_imm(a, s, immediate, &ARM64XEmitter::EORI2R); break; } } diff --git a/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.cpp b/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.cpp index b4afeed5b7..1b09f42c80 100644 --- a/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.cpp @@ -5,9 +5,52 @@ namespace JitCommon { +static constexpr u32 BitOR(u32 a, u32 b) +{ + return a | b; +} + +static constexpr u32 BitAND(u32 a, u32 b) +{ + return a & b; +} + +static constexpr u32 BitXOR(u32 a, u32 b) +{ + return a ^ b; +} + ConstantPropagationResult ConstantPropagation::EvaluateInstruction(UGeckoInstruction inst) const { - return {}; + switch (inst.OPCD) + { + case 24: // ori + case 25: // oris + return EvaluateBitwiseImm(inst, BitOR); + case 26: // xori + case 27: // xoris + return EvaluateBitwiseImm(inst, BitXOR); + case 28: // andi + case 29: // andis + return EvaluateBitwiseImm(inst, BitAND); + default: + return {}; + } +} + +ConstantPropagationResult ConstantPropagation::EvaluateBitwiseImm(UGeckoInstruction inst, + u32 (*do_op)(u32, u32)) const +{ + const bool is_and = do_op == &BitAND; + const u32 immediate = inst.OPCD & 1 ? inst.UIMM << 16 : inst.UIMM; + + if (inst.UIMM == 0 && !is_and && inst.RA == inst.RS) + return DO_NOTHING; + + if (!HasGPR(inst.RS)) + return {}; + + return ConstantPropagationResult(inst.RA, do_op(m_gpr_values[inst.RS], immediate), is_and); } void ConstantPropagation::Apply(ConstantPropagationResult result) diff --git a/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.h b/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.h index 2a24b9e710..176ee3d513 100644 --- a/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.h +++ b/Source/Core/Core/PowerPC/JitCommon/ConstantPropagation.h @@ -77,6 +77,15 @@ public: void Clear() { m_gpr_values_known = BitSet32{}; } private: + ConstantPropagationResult EvaluateBitwiseImm(UGeckoInstruction inst, + u32 (*do_op)(u32, u32)) const; + + static constexpr ConstantPropagationResult DO_NOTHING = [] { + ConstantPropagationResult result; + result.instruction_fully_executed = true; + return result; + }(); + static constexpr size_t GPR_COUNT = 32; std::array m_gpr_values;