Jit64: slwx - Optimize shift by constant

More efficient code can be generated if the shift amount is known at
compile time. Similar optimizations were present in JitArm64 already,
but were missing in Jit64.

- By using an 8-bit immediate we can eliminate the need for ECX as a
  scratch register, thereby reducing register pressure and occasionally
  eliminating a spill.

Before:
B9 18 00 00 00       mov         ecx,18h
41 8B F7             mov         esi,r15d
48 D3 E6             shl         rsi,cl
8B F6                mov         esi,esi

After:
41 8B CF             mov         ecx,r15d
C1 E1 18             shl         ecx,18h

- PowerPC has strange shift amount masking behavior which is emulated
  using 64-bit shifts, even though we only care about a 32-bit result.
  If the shift amount is known, we can handle this special case
  separately, and use 32-bit shift instructions otherwise. We also no
  longer need to clear the upper 32 bits of the register.

Before:
BE F8 FF FF FF       mov         esi,0FFFFFFF8h
8B CE                mov         ecx,esi
41 8B F4             mov         esi,r12d
48 D3 E6             shl         rsi,cl
8B F6                mov         esi,esi

After:
Nothing, register is set to constant zero.

- A shift by zero becomes a simple MOV.

Before:
BE 00 00 00 00       mov         esi,0
8B CE                mov         ecx,esi
41 8B F3             mov         esi,r11d
48 D3 E6             shl         rsi,cl
8B F6                mov         esi,esi

After:
41 8B FB             mov         edi,r11d
This commit is contained in:
Sintendo 2020-11-16 23:54:54 +01:00
parent 17db359979
commit 17dc870847

View file

@ -1849,6 +1849,30 @@ void Jit64::slwx(UGeckoInstruction inst)
if (inst.Rc)
ComputeRC(a);
}
else if (gpr.IsImm(b))
{
u32 amount = gpr.Imm32(b);
if (amount & 0x20)
{
gpr.SetImmediate32(a, 0);
}
else
{
RCX64Reg Ra = gpr.Bind(a, RCMode::Write);
RCOpArg Rs = gpr.Use(s, RCMode::Read);
RegCache::Realize(Ra, Rs);
if (a != s)
MOV(32, Ra, Rs);
amount &= 0x1f;
if (amount != 0)
SHL(32, Ra, Imm8(amount));
}
if (inst.Rc)
ComputeRC(a);
}
else
{
RCX64Reg ecx = gpr.Scratch(ECX); // no register choice