Merge pull request #9667 from Sintendo/jit64divwx2

Jit64: Minor divwx optimizations
This commit is contained in:
Mai M 2021-05-20 10:22:54 -04:00 committed by GitHub
commit 539c2cb00e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 81 additions and 37 deletions

View File

@ -1390,8 +1390,18 @@ void Jit64::divwx(UGeckoInstruction inst)
// Check for divisor == 0 // Check for divisor == 0
TEST(32, Rb, Rb); TEST(32, Rb, Rb);
FixupBranch normal_path; FixupBranch done;
if (d == b && (dividend & 0x80000000) == 0 && !inst.OE)
{
// Divisor is 0, skip to the end
// No need to explicitly set destination to 0 due to overlapping registers
done = J_CC(CC_Z);
// Otherwise, proceed to normal path
}
else
{
FixupBranch normal_path;
if (dividend == 0x80000000) if (dividend == 0x80000000)
{ {
// Divisor is 0, proceed to overflow case // Divisor is 0, proceed to overflow case
@ -1412,15 +1422,16 @@ void Jit64::divwx(UGeckoInstruction inst)
// Set Rd to all ones or all zeroes // Set Rd to all ones or all zeroes
if (dividend & 0x80000000) if (dividend & 0x80000000)
MOV(32, Rd, Imm32(0xFFFFFFFF)); MOV(32, Rd, Imm32(0xFFFFFFFF));
else else if (d != b)
XOR(32, Rd, Rd); XOR(32, Rd, Rd);
if (inst.OE) if (inst.OE)
GenerateConstantOverflow(true); GenerateConstantOverflow(true);
const FixupBranch done = J(); done = J();
SetJumpTarget(normal_path); SetJumpTarget(normal_path);
}
MOV(32, eax, Imm32(dividend)); MOV(32, eax, Imm32(dividend));
CDQ(); CDQ();
@ -1479,12 +1490,21 @@ void Jit64::divwx(UGeckoInstruction inst)
else if (divisor == 2 || divisor == -2) else if (divisor == 2 || divisor == -2)
{ {
X64Reg tmp = RSCRATCH; X64Reg tmp = RSCRATCH;
if (Ra.IsSimpleReg() && Ra.GetSimpleReg() != Rd) if (!Ra.IsSimpleReg())
tmp = Ra.GetSimpleReg(); {
else
MOV(32, R(tmp), Ra); MOV(32, R(tmp), Ra);
MOV(32, Rd, R(tmp)); MOV(32, Rd, R(tmp));
}
else if (d == a)
{
MOV(32, R(tmp), Ra);
}
else
{
MOV(32, Rd, Ra);
tmp = Ra.GetSimpleReg();
}
SHR(32, Rd, Imm8(31)); SHR(32, Rd, Imm8(31));
ADD(32, Rd, R(tmp)); ADD(32, Rd, R(tmp));
SAR(32, Rd, Imm8(1)); SAR(32, Rd, Imm8(1));
@ -1499,15 +1519,39 @@ void Jit64::divwx(UGeckoInstruction inst)
{ {
const u32 abs_val = static_cast<u32>(std::abs(static_cast<s64>(divisor))); const u32 abs_val = static_cast<u32>(std::abs(static_cast<s64>(divisor)));
X64Reg tmp = RSCRATCH; X64Reg dividend, sum, src;
if (Ra.IsSimpleReg() && Ra.GetSimpleReg() != Rd) CCFlags cond = CC_NS;
tmp = Ra.GetSimpleReg();
else
MOV(32, R(tmp), Ra);
TEST(32, R(tmp), R(tmp)); if (!Ra.IsSimpleReg())
LEA(32, Rd, MDisp(tmp, abs_val - 1)); {
CMOVcc(32, Rd, R(tmp), CC_NS); dividend = RSCRATCH;
sum = Rd;
src = RSCRATCH;
// Load dividend from memory
MOV(32, R(dividend), Ra);
}
else if (d == a)
{
// Rd holds the dividend, while RSCRATCH holds the sum
// This is opposite of the other cases
dividend = Rd;
sum = RSCRATCH;
src = RSCRATCH;
// Negate condition to compensate the swapped values
cond = CC_S;
}
else
{
// Use dividend from register directly
dividend = Ra.GetSimpleReg();
sum = Rd;
src = dividend;
}
TEST(32, R(dividend), R(dividend));
LEA(32, sum, MDisp(dividend, abs_val - 1));
CMOVcc(32, Rd, R(src), cond);
SAR(32, Rd, Imm8(IntLog2(abs_val))); SAR(32, Rd, Imm8(IntLog2(abs_val)));
if (divisor < 0) if (divisor < 0)