JitArm64_Integer: cmp - Skip sign extension if possible

While we cannot always avoid materializing immediates, we can still
inspect the most significant bit and potentially skip sign extension.
This can sometimes save an instruction.

Before:
0x5280003a   mov    w26, #0x1                 ; =1
0x93407f5b   sxtw   x27, w26
0xcb38c37b   sub    x27, x27, w24, sxtw

After:
0x5280003a   mov    w26, #0x1                 ; =1
0xcb38c35b   sub    x27, x26, w24, sxtw

Before:
0x52a20018   mov    w24, #0x10000000          ; =268435456
0x93407f79   sxtw   x25, w27
0xcb38c339   sub    x25, x25, w24, sxtw

After:
0x52a20018   mov    w24, #0x10000000          ; =268435456
0x93407f79   sxtw   x25, w27
0xcb180339   sub    x25, x25, x24
This commit is contained in:
Sintendo 2025-02-01 18:18:32 +01:00
parent 075c35602f
commit c5870ed0c7

View File

@ -675,11 +675,35 @@ void JitArm64::cmp(UGeckoInstruction inst)
}
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);
}
}