Jit64: subfx - Optimize more constant a cases

Consider the case where d and a refer to the same PowerPC register,
which is known to hold an immediate value by the RegCache. We place a
ReadWrite constraint on this register and bind it to an x86 register.
The RegCache then allocates a new register, initializes it with the
immediate, and returns a RCX64Reg for both d and a.

At this point information about the immediate value becomes unreachable.
In the case of subfx, this generates suboptimal code:

Before 1:
BF 1E 00 00 00       mov         edi,1Eh       <- done by RegCache
8B C7                mov         eax,edi
8B FE                mov         edi,esi
2B F8                sub         edi,eax

Before 2:
BE 00 AC 3F 80       mov         esi,803FAC00h <- done by RegCache
8B C6                mov         eax,esi
8B 75 EC             mov         esi,dword ptr [rbp-14h]
2B F0                sub         esi,eax

The solution is to explicitly handle the constant a case before having
the RegCache allocate registers for us.

After 1:
8D 7E E2             lea         edi,[rsi-1Eh]

After 2:
8B 75 EC             mov         esi,dword ptr [rbp-14h]
81 EE 00 AC 3F 80    sub         esi,803FAC00h
This commit is contained in:
Sintendo 2021-01-04 23:02:22 +01:00
parent e957ed0809
commit b805223108
1 changed files with 25 additions and 4 deletions

View File

@ -948,6 +948,31 @@ void Jit64::subfx(UGeckoInstruction inst)
if (inst.OE)
GenerateConstantOverflow((s64)i - (s64)j);
}
else if (gpr.IsImm(a))
{
s32 j = gpr.SImm32(a);
RCOpArg Rb = gpr.Use(b, RCMode::Read);
RCX64Reg Rd = gpr.Bind(d, RCMode::Write);
RegCache::Realize(Rb, Rd);
if (d == b)
{
SUB(32, Rd, Imm32(j));
if (inst.OE)
GenerateOverflow();
}
else if (Rb.IsSimpleReg() && !inst.OE)
{
LEA(32, Rd, MDisp(Rb.GetSimpleReg(), -j));
}
else
{
MOV(32, Rd, Rb);
SUB(32, Rd, Imm32(j));
if (inst.OE)
GenerateOverflow();
}
}
else
{
RCOpArg Ra = gpr.Use(a, RCMode::Read);
@ -965,10 +990,6 @@ void Jit64::subfx(UGeckoInstruction inst)
MOV(32, Rd, Rb);
SUB(32, Rd, R(RSCRATCH));
}
else if (Rb.IsSimpleReg() && Ra.IsImm() && !inst.OE)
{
LEA(32, Rd, MDisp(Rb.GetSimpleReg(), -Ra.SImm32()));
}
else
{
MOV(32, Rd, Rb);