From d877cfa4e2c3baf3cb8b8449d1608e1c2f05208c Mon Sep 17 00:00:00 2001
From: Sintendo <3380580+Sintendo@users.noreply.github.com>
Date: Wed, 26 Jun 2024 00:07:20 +0200
Subject: [PATCH] JitArm64_Integer: Optimize subfic for zero

When the immediate value is zero, we can do a negation. On ARM64 the NEG
/NEGS instructions are just an alias for SUB/SUBS with a hardcoded WZR.

Before:
```
ldr    w22, [x29, #0x28]
mov    w21, #0x0                 ; =0
subs   w22, w21, w22
```

After:
```
ldr    w22, [x29, #0x28]
negs   w22, w22
```
---
 .../Core/PowerPC/JitArm64/JitArm64_Integer.cpp     | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp
index 7e5817ac0c..f3d263379c 100644
--- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp
+++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Integer.cpp
@@ -1392,13 +1392,19 @@ void JitArm64::subfic(UGeckoInstruction inst)
   }
   else
   {
-    const bool allocate_reg = d == a;
-    gpr.BindToRegister(d, allocate_reg);
+    const bool will_read = d == a;
+    const bool is_zero = imm == 0;
+    const bool allocate_reg = will_read && !is_zero;
+    gpr.BindToRegister(d, will_read);
 
     // d = imm - a
     ARM64Reg RD = gpr.R(d);
-    ARM64Reg WA = allocate_reg ? gpr.GetReg() : RD;
-    MOVI2R(WA, imm);
+    ARM64Reg WA = ARM64Reg::WZR;
+    if (!is_zero)
+    {
+      WA = will_read ? gpr.GetReg() : RD;
+      MOVI2R(WA, imm);
+    }
     CARRY_IF_NEEDED(SUB, SUBS, RD, WA, gpr.R(a));
 
     if (allocate_reg)