Merge pull request #9481 from Sintendo/jit64boolx
Jit64: boolX constant optimizations
This commit is contained in:
commit
dafe2c785a
|
@ -668,6 +668,152 @@ void Jit64::boolX(UGeckoInstruction inst)
|
||||||
else if (inst.SUBOP10 == 284) // eqvx
|
else if (inst.SUBOP10 == 284) // eqvx
|
||||||
gpr.SetImmediate32(a, ~(rs_offset ^ rb_offset));
|
gpr.SetImmediate32(a, ~(rs_offset ^ rb_offset));
|
||||||
}
|
}
|
||||||
|
else if (gpr.IsImm(s) || gpr.IsImm(b))
|
||||||
|
{
|
||||||
|
const auto [i, j] = gpr.IsImm(s) ? std::pair(s, b) : std::pair(b, s);
|
||||||
|
u32 imm = gpr.Imm32(i);
|
||||||
|
|
||||||
|
bool complement_b = (inst.SUBOP10 == 60 /* andcx */) || (inst.SUBOP10 == 412 /* orcx */);
|
||||||
|
const bool final_not = (inst.SUBOP10 == 476 /* nandx */) || (inst.SUBOP10 == 124 /* norx */);
|
||||||
|
const bool is_and = (inst.SUBOP10 == 28 /* andx */) || (inst.SUBOP10 == 60 /* andcx */) ||
|
||||||
|
(inst.SUBOP10 == 476 /* nandx */);
|
||||||
|
const bool is_or = (inst.SUBOP10 == 444 /* orx */) || (inst.SUBOP10 == 412 /* orcx */) ||
|
||||||
|
(inst.SUBOP10 == 124 /* norx */);
|
||||||
|
const bool is_xor = (inst.SUBOP10 == 316 /* xorx */) || (inst.SUBOP10 == 284 /* eqvx */);
|
||||||
|
|
||||||
|
// Precompute complement when possible
|
||||||
|
if (complement_b && gpr.IsImm(b) || (inst.SUBOP10 == 284 /* eqvx */))
|
||||||
|
{
|
||||||
|
imm = ~imm;
|
||||||
|
complement_b = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_xor)
|
||||||
|
{
|
||||||
|
RCOpArg Rj = gpr.Use(j, RCMode::Read);
|
||||||
|
RCX64Reg Ra = gpr.Bind(a, RCMode::Write);
|
||||||
|
RegCache::Realize(Rj, Ra);
|
||||||
|
if (imm == 0)
|
||||||
|
{
|
||||||
|
if (a != j)
|
||||||
|
MOV(32, Ra, Rj);
|
||||||
|
needs_test = true;
|
||||||
|
}
|
||||||
|
else if (imm == 0xFFFFFFFF && !inst.Rc)
|
||||||
|
{
|
||||||
|
if (a != j)
|
||||||
|
MOV(32, Ra, Rj);
|
||||||
|
NOT(32, Ra);
|
||||||
|
}
|
||||||
|
else if (a == j)
|
||||||
|
XOR(32, Ra, Imm32(imm));
|
||||||
|
else if (s32(imm) >= -128 && s32(imm) <= 127)
|
||||||
|
{
|
||||||
|
MOV(32, Ra, Rj);
|
||||||
|
XOR(32, Ra, Imm32(imm));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MOV(32, Ra, Imm32(imm));
|
||||||
|
XOR(32, Ra, Rj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (is_and)
|
||||||
|
{
|
||||||
|
if (imm == 0)
|
||||||
|
gpr.SetImmediate32(a, final_not ? 0xFFFFFFFF : 0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RCOpArg Rj = gpr.Use(j, RCMode::Read);
|
||||||
|
RCX64Reg Ra = gpr.Bind(a, RCMode::Write);
|
||||||
|
RegCache::Realize(Rj, Ra);
|
||||||
|
|
||||||
|
if (imm == 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
if (a != j)
|
||||||
|
MOV(32, Ra, Rj);
|
||||||
|
if (final_not || complement_b)
|
||||||
|
NOT(32, Ra);
|
||||||
|
needs_test = true;
|
||||||
|
}
|
||||||
|
else if (complement_b)
|
||||||
|
{
|
||||||
|
if (a != j)
|
||||||
|
MOV(32, Ra, Rj);
|
||||||
|
NOT(32, Ra);
|
||||||
|
AND(32, Ra, Imm32(imm));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (a == j)
|
||||||
|
AND(32, Ra, Imm32(imm));
|
||||||
|
else if (s32(imm) >= -128 && s32(imm) <= 127)
|
||||||
|
{
|
||||||
|
MOV(32, Ra, Rj);
|
||||||
|
AND(32, Ra, Imm32(imm));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MOV(32, Ra, Imm32(imm));
|
||||||
|
AND(32, Ra, Rj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (final_not)
|
||||||
|
{
|
||||||
|
NOT(32, Ra);
|
||||||
|
needs_test = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (is_or)
|
||||||
|
{
|
||||||
|
RCOpArg Rj = gpr.Use(j, RCMode::Read);
|
||||||
|
RCX64Reg Ra = gpr.Bind(a, RCMode::Write);
|
||||||
|
RegCache::Realize(Rj, Ra);
|
||||||
|
|
||||||
|
if (imm == 0)
|
||||||
|
{
|
||||||
|
if (a != j)
|
||||||
|
MOV(32, Ra, Rj);
|
||||||
|
if (final_not || complement_b)
|
||||||
|
NOT(32, Ra);
|
||||||
|
needs_test = true;
|
||||||
|
}
|
||||||
|
else if (complement_b)
|
||||||
|
{
|
||||||
|
if (a != j)
|
||||||
|
MOV(32, Ra, Rj);
|
||||||
|
NOT(32, Ra);
|
||||||
|
OR(32, Ra, Imm32(imm));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (a == j)
|
||||||
|
OR(32, Ra, Imm32(imm));
|
||||||
|
else if (s32(imm) >= -128 && s32(imm) <= 127)
|
||||||
|
{
|
||||||
|
MOV(32, Ra, Rj);
|
||||||
|
OR(32, Ra, Imm32(imm));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MOV(32, Ra, Imm32(imm));
|
||||||
|
OR(32, Ra, Rj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (final_not)
|
||||||
|
{
|
||||||
|
NOT(32, Ra);
|
||||||
|
needs_test = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PanicAlertFmt("WTF!");
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (s == b)
|
else if (s == b)
|
||||||
{
|
{
|
||||||
if ((inst.SUBOP10 == 28 /* andx */) || (inst.SUBOP10 == 444 /* orx */))
|
if ((inst.SUBOP10 == 28 /* andx */) || (inst.SUBOP10 == 444 /* orx */))
|
||||||
|
@ -736,7 +882,7 @@ void Jit64::boolX(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
else if (inst.SUBOP10 == 60) // andcx
|
else if (inst.SUBOP10 == 60) // andcx
|
||||||
{
|
{
|
||||||
if (cpu_info.bBMI1 && Rb.IsSimpleReg() && !Rs.IsImm())
|
if (cpu_info.bBMI1 && Rb.IsSimpleReg())
|
||||||
{
|
{
|
||||||
ANDN(32, Ra, Rb.GetSimpleReg(), Rs);
|
ANDN(32, Ra, Rb.GetSimpleReg(), Rs);
|
||||||
}
|
}
|
||||||
|
@ -811,7 +957,7 @@ void Jit64::boolX(UGeckoInstruction inst)
|
||||||
}
|
}
|
||||||
else if (inst.SUBOP10 == 60) // andcx
|
else if (inst.SUBOP10 == 60) // andcx
|
||||||
{
|
{
|
||||||
if (cpu_info.bBMI1 && Rb.IsSimpleReg() && !Rs.IsImm())
|
if (cpu_info.bBMI1 && Rb.IsSimpleReg())
|
||||||
{
|
{
|
||||||
ANDN(32, Ra, Rb.GetSimpleReg(), Rs);
|
ANDN(32, Ra, Rb.GetSimpleReg(), Rs);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue