Jit: Move boolX to ConstantPropagation

This commit is contained in:
JosJuice 2023-08-23 15:22:34 +02:00
parent 0b81bd8412
commit 8a5cbe696f
4 changed files with 162 additions and 81 deletions

View File

@ -680,29 +680,7 @@ void Jit64::boolX(UGeckoInstruction inst)
bool needs_test = false;
DEBUG_ASSERT_MSG(DYNA_REC, inst.OPCD == 31, "Invalid boolX");
if (gpr.IsImm(s, b))
{
const u32 rs_offset = gpr.Imm32(s);
const u32 rb_offset = gpr.Imm32(b);
if (inst.SUBOP10 == 28) // andx
gpr.SetImmediate32(a, rs_offset & rb_offset);
else if (inst.SUBOP10 == 476) // nandx
gpr.SetImmediate32(a, ~(rs_offset & rb_offset));
else if (inst.SUBOP10 == 60) // andcx
gpr.SetImmediate32(a, rs_offset & (~rb_offset));
else if (inst.SUBOP10 == 444) // orx
gpr.SetImmediate32(a, rs_offset | rb_offset);
else if (inst.SUBOP10 == 124) // norx
gpr.SetImmediate32(a, ~(rs_offset | rb_offset));
else if (inst.SUBOP10 == 412) // orcx
gpr.SetImmediate32(a, rs_offset | (~rb_offset));
else if (inst.SUBOP10 == 316) // xorx
gpr.SetImmediate32(a, rs_offset ^ rb_offset);
else if (inst.SUBOP10 == 284) // eqvx
gpr.SetImmediate32(a, ~(rs_offset ^ rb_offset));
}
else if (gpr.IsImm(s) || gpr.IsImm(b))
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);
@ -756,53 +734,46 @@ void Jit64::boolX(UGeckoInstruction inst)
}
else if (is_and)
{
if (imm == 0)
RCOpArg Rj = gpr.Use(j, RCMode::Read);
RCX64Reg Ra = gpr.Bind(a, RCMode::Write);
RegCache::Realize(Rj, Ra);
if (imm == 0xFFFFFFFF)
{
gpr.SetImmediate32(a, final_not ? 0xFFFFFFFF : 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);
AND(32, Ra, Imm32(imm));
}
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)
{
if (a != j)
MOV(32, Ra, Rj);
if (final_not || complement_b)
NOT(32, Ra);
needs_test = true;
AND(32, Ra, Imm32(imm));
}
else if (complement_b)
else if (s32(imm) >= -128 && s32(imm) <= 127)
{
if (a != j)
MOV(32, Ra, Rj);
NOT(32, Ra);
MOV(32, Ra, Rj);
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);
}
MOV(32, Ra, Imm32(imm));
AND(32, Ra, Rj);
}
if (final_not)
{
NOT(32, Ra);
needs_test = true;
}
if (final_not)
{
NOT(32, Ra);
needs_test = true;
}
}
}

View File

@ -235,29 +235,7 @@ void JitArm64::boolX(UGeckoInstruction inst)
JITDISABLE(bJITIntegerOff);
int a = inst.RA, s = inst.RS, b = inst.RB;
if (gpr.IsImm(s) && gpr.IsImm(b))
{
if (inst.SUBOP10 == 28) // andx
gpr.SetImmediate(a, (u32)gpr.GetImm(s) & (u32)gpr.GetImm(b));
else if (inst.SUBOP10 == 476) // nandx
gpr.SetImmediate(a, ~((u32)gpr.GetImm(s) & (u32)gpr.GetImm(b)));
else if (inst.SUBOP10 == 60) // andcx
gpr.SetImmediate(a, (u32)gpr.GetImm(s) & (~(u32)gpr.GetImm(b)));
else if (inst.SUBOP10 == 444) // orx
gpr.SetImmediate(a, (u32)gpr.GetImm(s) | (u32)gpr.GetImm(b));
else if (inst.SUBOP10 == 124) // norx
gpr.SetImmediate(a, ~((u32)gpr.GetImm(s) | (u32)gpr.GetImm(b)));
else if (inst.SUBOP10 == 412) // orcx
gpr.SetImmediate(a, (u32)gpr.GetImm(s) | (~(u32)gpr.GetImm(b)));
else if (inst.SUBOP10 == 316) // xorx
gpr.SetImmediate(a, (u32)gpr.GetImm(s) ^ (u32)gpr.GetImm(b));
else if (inst.SUBOP10 == 284) // eqvx
gpr.SetImmediate(a, ~((u32)gpr.GetImm(s) ^ (u32)gpr.GetImm(b)));
if (inst.Rc)
ComputeRC0(gpr.GetImm(a));
}
else if (s == b)
if (s == b)
{
if ((inst.SUBOP10 == 28 /* andx */) || (inst.SUBOP10 == 444 /* orx */))
{

View File

@ -36,6 +36,8 @@ ConstantPropagationResult ConstantPropagation::EvaluateInstruction(UGeckoInstruc
case 28: // andi
case 29: // andis
return EvaluateBitwiseImm(inst, BitAND);
case 31:
return EvaluateTable31(inst);
default:
return {};
}
@ -69,6 +71,132 @@ ConstantPropagationResult ConstantPropagation::EvaluateBitwiseImm(UGeckoInstruct
return ConstantPropagationResult(inst.RA, do_op(m_gpr_values[inst.RS], immediate), is_and);
}
ConstantPropagationResult ConstantPropagation::EvaluateTable31(UGeckoInstruction inst) const
{
const bool has_s = HasGPR(inst.RS);
const bool has_b = HasGPR(inst.RB);
if (!has_s || !has_b)
{
if (has_s)
return EvaluateTable31OneRegisterKnown(inst, GetGPR(inst.RS), false);
else if (has_b)
return EvaluateTable31OneRegisterKnown(inst, GetGPR(inst.RB), true);
else if (inst.RS == inst.RB)
return EvaluateTable31IdenticalRegisters(inst);
else
return {};
}
u32 a;
const u32 s = GetGPR(inst.RS);
const u32 b = GetGPR(inst.RB);
switch (inst.SUBOP10)
{
case 28: // andx
a = s & b;
break;
case 60: // andcx
a = s & (~b);
break;
case 124: // norx
a = ~(s | b);
break;
case 284: // eqvx
a = ~(s ^ b);
break;
case 316: // xorx
a = s ^ b;
break;
case 412: // orcx
a = s | (~b);
break;
case 444: // orx
a = s | b;
break;
case 476: // nandx
a = ~(s & b);
break;
default:
return {};
}
return ConstantPropagationResult(inst.RA, a, inst.Rc);
}
ConstantPropagationResult
ConstantPropagation::EvaluateTable31OneRegisterKnown(UGeckoInstruction inst, u32 value,
bool known_reg_is_b) const
{
u32 a;
switch (inst.SUBOP10)
{
case 60: // andcx
if (known_reg_is_b)
value = ~value;
[[fallthrough]];
case 28: // andx
if (value == 0)
a = 0;
else
return {};
break;
case 124: // norx
if (value == 0xFFFFFFFF)
a = 0;
else
return {};
break;
case 412: // orcx
if (known_reg_is_b)
value = ~value;
[[fallthrough]];
case 444: // orx
if (value == 0xFFFFFFFF)
a = 0xFFFFFFFF;
else
return {};
break;
case 476: // nandx
if (value == 0)
a = 0xFFFFFFFF;
else
return {};
break;
default:
return {};
}
return ConstantPropagationResult(inst.RA, a, inst.Rc);
}
ConstantPropagationResult
ConstantPropagation::EvaluateTable31IdenticalRegisters(UGeckoInstruction inst) const
{
u32 a;
switch (inst.SUBOP10)
{
case 60: // andcx
a = 0;
break;
case 284: // eqvx
a = 0xFFFFFFFF;
break;
case 316: // xorx
a = 0;
break;
case 412: // orcx
a = 0xFFFFFFFF;
break;
default:
return {};
}
return ConstantPropagationResult(inst.RA, a, inst.Rc);
}
void ConstantPropagation::Apply(ConstantPropagationResult result)
{
if (result.gpr >= 0)

View File

@ -80,6 +80,10 @@ private:
ConstantPropagationResult EvaluateAddImm(UGeckoInstruction inst) const;
ConstantPropagationResult EvaluateBitwiseImm(UGeckoInstruction inst,
u32 (*do_op)(u32, u32)) const;
ConstantPropagationResult EvaluateTable31(UGeckoInstruction inst) const;
ConstantPropagationResult EvaluateTable31OneRegisterKnown(UGeckoInstruction inst, u32 value,
bool known_reg_is_b) const;
ConstantPropagationResult EvaluateTable31IdenticalRegisters(UGeckoInstruction inst) const;
static constexpr ConstantPropagationResult DO_NOTHING = [] {
ConstantPropagationResult result;