From 14641b06fc001e4ecd828b6b3e6d66422b2da8e4 Mon Sep 17 00:00:00 2001 From: Sintendo <3380580+Sintendo@users.noreply.github.com> Date: Sat, 28 Dec 2024 23:07:33 +0100 Subject: [PATCH] JitArm64_Integer: addzex - Optimize ConstantFalse and ConstantTrue When the input register and carry flags are known, we can always precompute the result. We still materialize the immediate when the condition register needs to be updated, but this seems to be a general problem. I might look into that one day, but for now this'll do. - ConstantFalse Before: 0x52800119 mov w25, #0x8 ; =8 0x2a1903fa mov w26, w25 After: N/A - ConstantTrue Before: 0x52800119 mov w25, #0x8 ; =8 0x1100073a add w26, w25, #0x1 After: N/A --- .../PowerPC/JitArm64/JitArm64_Integer.cpp | 97 ++++++++++++------- 1 file changed, 62 insertions(+), 35 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp index a6820fdfd2..c3ebc252e4 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp @@ -10,6 +10,7 @@ #include "Common/BitUtils.h" #include "Common/CommonTypes.h" #include "Common/MathUtil.h" +#include "Common/Unreachable.h" #include "Core/Core.h" #include "Core/CoreTiming.h" @@ -1128,47 +1129,73 @@ void JitArm64::addzex(UGeckoInstruction inst) int a = inst.RA, d = inst.RD; - switch (js.carryFlag) + if (gpr.IsImm(a) && HasConstantCarry()) { - case CarryFlag::InPPCState: - { - const bool allocate_reg = d == a; - gpr.BindToRegister(d, allocate_reg); + const u32 imm = gpr.GetImm(a); + const bool is_all_ones = imm == 0xFFFFFFFF; + switch (js.carryFlag) { - auto WA = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(gpr.R(d)); - LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); - CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), WA); - } - - ComputeCarry(); - break; - } - case CarryFlag::InHostCarry: - { - gpr.BindToRegister(d, d == a); - CARRY_IF_NEEDED(ADC, ADCS, gpr.R(d), gpr.R(a), ARM64Reg::WZR); - ComputeCarry(); - break; - } - case CarryFlag::ConstantTrue: - { - gpr.BindToRegister(d, d == a); - CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), 1); - ComputeCarry(); - break; - } - case CarryFlag::ConstantFalse: - { - if (d != a) + case CarryFlag::ConstantTrue: { - gpr.BindToRegister(d, false); - MOV(gpr.R(d), gpr.R(a)); + gpr.SetImmediate(d, imm + 1); + ComputeCarry(is_all_ones); + break; + } + case CarryFlag::ConstantFalse: + { + gpr.SetImmediate(d, imm); + ComputeCarry(false); + break; + } + default: + Common::Unreachable(); } - - ComputeCarry(false); - break; } + else + { + switch (js.carryFlag) + { + case CarryFlag::InPPCState: + { + const bool allocate_reg = d == a; + gpr.BindToRegister(d, allocate_reg); + + { + auto WA = allocate_reg ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(gpr.R(d)); + LDRB(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(xer_ca)); + CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), WA); + } + + ComputeCarry(); + break; + } + case CarryFlag::InHostCarry: + { + gpr.BindToRegister(d, d == a); + CARRY_IF_NEEDED(ADC, ADCS, gpr.R(d), gpr.R(a), ARM64Reg::WZR); + ComputeCarry(); + break; + } + case CarryFlag::ConstantTrue: + { + gpr.BindToRegister(d, d == a); + CARRY_IF_NEEDED(ADD, ADDS, gpr.R(d), gpr.R(a), 1); + ComputeCarry(); + break; + } + case CarryFlag::ConstantFalse: + { + if (d != a) + { + gpr.BindToRegister(d, false); + MOV(gpr.R(d), gpr.R(a)); + } + + ComputeCarry(false); + break; + } + } } if (inst.Rc)