From 17dc870847ba65a5c8aceeafd21fe7623d042c42 Mon Sep 17 00:00:00 2001 From: Sintendo Date: Mon, 16 Nov 2020 23:54:54 +0100 Subject: [PATCH] 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 --- .../Core/Core/PowerPC/Jit64/Jit_Integer.cpp | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index 4166d8626b..fb632a42fd 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -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