summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2025-08-16 11:51:07 +0200
committerJosJuice <josjuice@gmail.com>2026-01-18 20:02:49 +0100
commitcaad84c636f30b47a30303ea1994bb61db63cc02 (patch)
tree58bb7d4a8f5a6f45423c4c6fc363435e96cc5ae8 /Source/Core
parent84261cfc2333e5ca94aedb79ef46768edf71d759 (diff)
JitArm64: Reduce register pressure for inaccurate FMA with accurate NaNs
If result_reg is set to a temporary register instead of VD because of accurate NaNs, there's no need to allocate a secondary temporary register because of inaccurate FMA.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp18
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64_Paired.cpp40
2 files changed, 33 insertions, 25 deletions
diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp
index e03cb50c2f..6fc3c23531 100644
--- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp
+++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_FloatingPoint.cpp
@@ -103,7 +103,6 @@ void JitArm64::fp_arith(UGeckoInstruction inst)
{
Arm64FPRCache::ScopedARM64Reg V0Q = ARM64Reg::INVALID_REG;
- Arm64FPRCache::ScopedARM64Reg V1Q = ARM64Reg::INVALID_REG;
ARM64Reg rounded_c_reg = VC;
if (round_c)
@@ -115,21 +114,22 @@ void JitArm64::fp_arith(UGeckoInstruction inst)
Force25BitPrecision(rounded_c_reg, VC);
}
+ ARM64Reg result_reg = VD;
ARM64Reg inaccurate_fma_reg = VD;
- if (fma && inaccurate_fma && VD == VB)
+ const bool preserve_d =
+ m_accurate_nans && (VD == VA || (use_b && VD == VB) || (use_c && VD == VC));
+ if (preserve_d)
{
if (V0Q == ARM64Reg::INVALID_REG)
V0Q = fpr.GetScopedReg();
+ result_reg = reg_encoder(V0Q);
inaccurate_fma_reg = reg_encoder(V0Q);
}
-
- ARM64Reg result_reg = VD;
- const bool preserve_d =
- m_accurate_nans && (VD == VA || (use_b && VD == VB) || (use_c && VD == VC));
- if (preserve_d)
+ else if (fma && inaccurate_fma && VD == VB)
{
- V1Q = fpr.GetScopedReg();
- result_reg = reg_encoder(V1Q);
+ if (V0Q == ARM64Reg::INVALID_REG)
+ V0Q = fpr.GetScopedReg();
+ inaccurate_fma_reg = reg_encoder(V0Q);
}
switch (op5)
diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Paired.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Paired.cpp
index e1f3f09662..1504b30044 100644
--- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Paired.cpp
+++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Paired.cpp
@@ -120,40 +120,48 @@ void JitArm64::ps_arith(UGeckoInstruction inst)
if (round_c)
{
ASSERT_MSG(DYNA_REC, !single, "Tried to apply 25-bit precision to single");
-
V0Q = fpr.GetScopedReg();
rounded_c_reg = reg_encoder(V0Q);
- Force25BitPrecision(rounded_c_reg, VC);
- }
-
- ARM64Reg inaccurate_fma_reg = VD;
- if (fma && inaccurate_fma && VD == VB)
- {
- if (V0Q == ARM64Reg::INVALID_REG)
- V0Q = fpr.GetScopedReg();
- inaccurate_fma_reg = reg_encoder(V0Q);
}
ARM64Reg result_reg = VD;
+ ARM64Reg inaccurate_fma_reg = VD;
const bool need_accurate_fma_reg =
fma && !inaccurate_fma && (msub || VD != VB) && (VD == VA || VD == rounded_c_reg);
const bool preserve_d =
m_accurate_nans && (VD == VA || (use_b && VD == VB) || (use_c && VD == VC));
if (need_accurate_fma_reg || preserve_d)
{
- V1Q = fpr.GetScopedReg();
- result_reg = reg_encoder(V1Q);
- }
+ if (V0Q == ARM64Reg::INVALID_REG)
+ V0Q = fpr.GetScopedReg();
+ result_reg = reg_encoder(V0Q);
+ inaccurate_fma_reg = reg_encoder(V0Q);
- if (m_accurate_nans)
+ if (need_accurate_fma_reg && round_c)
+ {
+ V1Q = fpr.GetScopedReg();
+ rounded_c_reg = reg_encoder(V1Q);
+ }
+ }
+ else if (fma && inaccurate_fma && VD == VB)
{
if (V0Q == ARM64Reg::INVALID_REG)
V0Q = fpr.GetScopedReg();
+ inaccurate_fma_reg = reg_encoder(V0Q);
+ }
+
+ if (m_accurate_nans)
+ {
+ if (V1Q == ARM64Reg::INVALID_REG)
+ V1Q = fpr.GetScopedReg();
if (duplicated_c || VD == result_reg)
V2Q = fpr.GetScopedReg();
}
+ if (round_c)
+ Force25BitPrecision(rounded_c_reg, VC);
+
switch (op5)
{
case 12: // ps_muls0: d = a * c.ps0
@@ -235,8 +243,8 @@ void JitArm64::ps_arith(UGeckoInstruction inst)
FixupBranch nan_fixup;
if (m_accurate_nans)
{
- const ARM64Reg nan_temp_reg = single ? EncodeRegToSingle(V0Q) : EncodeRegToDouble(V0Q);
- const ARM64Reg nan_temp_reg_paired = reg_encoder(V0Q);
+ const ARM64Reg nan_temp_reg = single ? EncodeRegToSingle(V1Q) : EncodeRegToDouble(V1Q);
+ const ARM64Reg nan_temp_reg_paired = reg_encoder(V1Q);
// Check if we need to handle NaNs