summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2025-02-15 00:30:34 -0500
committerGitHub <noreply@github.com>2025-02-15 00:30:34 -0500
commitf9accfd4d65ab46e44271f948a05ae4b95ea2e62 (patch)
treeb386eef82b2658232e334af8e4645c39489dc838
parentac2026dd6eaf0d6728d023e0cc036d9ace29ab52 (diff)
parent755c00326559904aee338d47a06409ec5b03b55e (diff)
Merge pull request #13324 from Sintendo/jitarm64-cmp-imm
JitArm64_Integer: cmp/cmpl optimizations
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp59
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.h2
2 files changed, 55 insertions, 6 deletions
diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp
index 16cf25fdef..58fab5cfea 100644
--- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp
+++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp
@@ -652,17 +652,58 @@ void JitArm64::cmp(UGeckoInstruction inst)
SXTW(CR, gpr.R(b));
MVN(CR, CR);
}
- else if (gpr.IsImm(b) && !gpr.GetImm(b))
+ else if (gpr.IsImm(b) && (gpr.GetImm(b) & 0xFFF) == gpr.GetImm(b))
{
SXTW(CR, gpr.R(a));
+ if (const u32 imm = gpr.GetImm(b); imm != 0)
+ SUB(CR, CR, imm);
+ }
+ else if (gpr.IsImm(b) && (gpr.GetImm(b) & 0xFFF000) == gpr.GetImm(b))
+ {
+ SXTW(CR, gpr.R(a));
+ SUB(CR, CR, gpr.GetImm(b) >> 12, true);
+ }
+ else if (gpr.IsImm(b) && (((~gpr.GetImm(b) + 1) & 0xFFF) == (~gpr.GetImm(b) + 1)))
+ {
+ SXTW(CR, gpr.R(a));
+ ADD(CR, CR, ~gpr.GetImm(b) + 1);
+ }
+ else if (gpr.IsImm(b) && (((~gpr.GetImm(b) + 1) & 0xFFF000) == (~gpr.GetImm(b) + 1)))
+ {
+ SXTW(CR, gpr.R(a));
+ ADD(CR, CR, (~gpr.GetImm(b) + 1) >> 12, true);
}
else
{
+ // If we're dealing with immediates, check their most significant bit to
+ // see if we can skip sign extension.
+ const auto should_sign_extend = [&](u32 reg) -> bool {
+ return !gpr.IsImm(reg) || (gpr.GetImm(reg) & (1U << 31));
+ };
+ bool sign_extend_a = should_sign_extend(a);
+ bool sign_extend_b = should_sign_extend(b);
+
ARM64Reg RA = gpr.R(a);
ARM64Reg RB = gpr.R(b);
- SXTW(CR, RA);
- SUB(CR, CR, RB, ArithOption(RB, ExtendSpecifier::SXTW));
+ if (sign_extend_a)
+ {
+ SXTW(CR, RA);
+ RA = CR;
+ }
+ else
+ {
+ RA = EncodeRegTo64(RA);
+ }
+
+ auto opt = ArithOption(RB, ExtendSpecifier::SXTW);
+ if (!sign_extend_b)
+ {
+ opt = ArithOption(CR, ShiftType::LSL, 0);
+ RB = EncodeRegTo64(RB);
+ }
+
+ SUB(CR, RA, RB, opt);
}
}
@@ -687,9 +728,17 @@ void JitArm64::cmpl(UGeckoInstruction inst)
{
NEG(CR, EncodeRegTo64(gpr.R(b)));
}
- else if (gpr.IsImm(b) && !gpr.GetImm(b))
+ else if (gpr.IsImm(b) && (gpr.GetImm(b) & 0xFFF) == gpr.GetImm(b))
{
- MOV(EncodeRegTo32(CR), gpr.R(a));
+ const u32 imm = gpr.GetImm(b);
+ if (imm == 0)
+ MOV(EncodeRegTo32(CR), gpr.R(a));
+ else
+ SUB(CR, EncodeRegTo64(gpr.R(a)), imm);
+ }
+ else if (gpr.IsImm(b) && (gpr.GetImm(b) & 0xFFF000) == gpr.GetImm(b))
+ {
+ SUB(CR, EncodeRegTo64(gpr.R(a)), gpr.GetImm(b) >> 12, true);
}
else
{
diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.h b/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.h
index b98e170531..5164745cd8 100644
--- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.h
+++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.h
@@ -345,7 +345,7 @@ public:
// Gets the immediate that a register is set to. Only valid for guest GPRs.
u32 GetImm(size_t preg) const { return GetGuestGPROpArg(preg).GetImm(); }
- bool IsImm(size_t preg, u32 imm) { return IsImm(preg) && GetImm(preg) == imm; }
+ bool IsImm(size_t preg, u32 imm) const { return IsImm(preg) && GetImm(preg) == imm; }
// Binds a guest GPR to a host register, optionally loading its value.
//