diff --git a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp index 964d048b64..b5f784793d 100644 --- a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp @@ -8481,7 +8481,7 @@ public: const bool a_notnan = a_known.isKnownNeverNaN() || llvm::cast(ci->getOperand(3))->getZExtValue() != 0; const bool b_notnan = b_known.isKnownNeverNaN() || llvm::cast(ci->getOperand(4))->getZExtValue() != 0; - + if (g_cfg.core.spu_xfloat_accuracy == xfloat_accuracy::approximate) { if (a.value == b.value || (a_notnan && b_notnan)) @@ -8491,22 +8491,28 @@ public: if (a_notnan) { - const auto ma = sext(fcmp_uno(a != fsplat(0.))); - const auto cb = bitcast(bitcast(b) & ma); - return fma32x4(a, eval(cb), c, a_known, b_known); + const auto normal_fma = fma32x4(a, b, c, a_known, b_known); + return eval(select(fcmp_uno(a != fsplat(0.)), normal_fma, c)); } else if (b_notnan) { - const auto mb = sext(fcmp_uno(b != fsplat(0.))); - const auto ca = bitcast(bitcast(a) & mb); - return fma32x4(eval(ca), b, c, a_known, b_known); + const auto normal_fma = fma32x4(a, b, c, a_known, b_known); + return eval(select(fcmp_uno(b != fsplat(0.)), normal_fma, c)); } - const auto ma = sext(fcmp_uno(a != fsplat(0.))); - const auto mb = sext(fcmp_uno(b != fsplat(0.))); - const auto ca = bitcast(bitcast(a) & mb); - const auto cb = bitcast(bitcast(b) & ma); - return fma32x4(eval(ca), eval(cb), c, a_known, b_known); + // Same number of operations well preventing a serial predicate chain pessimization + if (m_use_avx512) + { + // 0/denormals -> +0, else 1st operand + const auto ca = vfixupimmps(a, b, splat(0x00000800u), 0, 0xff); + const auto cb = vfixupimmps(b, a, splat(0x00000800u), 0, 0xff); + return fma32x4(ca, cb, c, a_known, b_known); + } + + const auto normal_fma = fma32x4(a, b, c, a_known, b_known); + const auto a_cmp = fcmp_uno(a != fsplat(0.)); + const auto b_cmp = fcmp_uno(b != fsplat(0.)); + return eval(select(a_cmp & b_cmp, normal_fma, c)); } else {