From c7544719e2722dbb3df3881e4f65b7ee7ca945f7 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Wed, 10 Jun 2015 14:23:43 +0200 Subject: [PATCH 1/2] Interpreter: optimize NaN checks NaNs always propagate, so we can get away with only checking for NaN inputs in the rare case that the result is NaN (as already done in Jit64::HandleNaNs()). --- .../PowerPC/Interpreter/Interpreter_FPUtils.h | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index 795bab7b0e..90990b69d4 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -83,11 +83,11 @@ inline double Force25Bit(double d) inline double NI_mul(double a, double b) { - if (a != a) return a; - if (b != b) return b; double t = a * b; if (t != t) { + if (a != a) return a; + if (b != b) return b; SetFPException(FPSCR_VXIMZ); return PPC_NAN; } @@ -96,11 +96,11 @@ inline double NI_mul(double a, double b) inline double NI_add(double a, double b) { - if (a != a) return a; - if (b != b) return b; double t = a + b; if (t != t) { + if (a != a) return a; + if (b != b) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; } @@ -109,31 +109,35 @@ inline double NI_add(double a, double b) inline double NI_sub(double a, double b) { - if (a != a) return a; - if (b != b) return b; double t = a - b; if (t != t) { + if (a != a) return a; + if (b != b) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; } return t; } +// FMA instructions on PowerPC are weird: +// They calculate (a * c) + b, but the order in which +// inputs are checked for NaN is still a, b, c. inline double NI_madd(double a, double c, double b, bool negate = false) { - if (a != a) return a; - if (b != b) return b; - if (c != c) return c; double t = a * c; if (t != t) { + if (a != a) return a; + if (b != b) return b; // ! + if (c != c) return c; SetFPException(FPSCR_VXIMZ); return PPC_NAN; } t = t + b; if (t != t) { + if (b != b) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; } @@ -142,12 +146,12 @@ inline double NI_madd(double a, double c, double b, bool negate = false) inline double NI_msub(double a, double c, double b, bool negate = false) { - if (a != a) return a; - if (b != b) return b; - if (c != c) return c; double t = a * c; if (t != t) { + if (a != a) return a; + if (b != b) return b; // ! + if (c != c) return c; SetFPException(FPSCR_VXIMZ); return PPC_NAN; } @@ -155,6 +159,7 @@ inline double NI_msub(double a, double c, double b, bool negate = false) t = t - b; if (t != t) { + if (b != b) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; } From d32914787178353eaeeff6f9c419abdd28a1528e Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Wed, 10 Jun 2015 14:31:08 +0200 Subject: [PATCH 2/2] Interpreter: use std::isnan(x) instead of x != x --- .../PowerPC/Interpreter/Interpreter_FPUtils.h | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index 90990b69d4..5392cc7ee0 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include "Common/CPUDetect.h" @@ -84,10 +85,10 @@ inline double Force25Bit(double d) inline double NI_mul(double a, double b) { double t = a * b; - if (t != t) + if (std::isnan(t)) { - if (a != a) return a; - if (b != b) return b; + if (std::isnan(a)) return a; + if (std::isnan(b)) return b; SetFPException(FPSCR_VXIMZ); return PPC_NAN; } @@ -97,10 +98,10 @@ inline double NI_mul(double a, double b) inline double NI_add(double a, double b) { double t = a + b; - if (t != t) + if (std::isnan(t)) { - if (a != a) return a; - if (b != b) return b; + if (std::isnan(a)) return a; + if (std::isnan(b)) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; } @@ -110,10 +111,10 @@ inline double NI_add(double a, double b) inline double NI_sub(double a, double b) { double t = a - b; - if (t != t) + if (std::isnan(t)) { - if (a != a) return a; - if (b != b) return b; + if (std::isnan(a)) return a; + if (std::isnan(b)) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; } @@ -126,18 +127,18 @@ inline double NI_sub(double a, double b) inline double NI_madd(double a, double c, double b, bool negate = false) { double t = a * c; - if (t != t) + if (std::isnan(t)) { - if (a != a) return a; - if (b != b) return b; // ! - if (c != c) return c; + if (std::isnan(a)) return a; + if (std::isnan(b)) return b; // ! + if (std::isnan(c)) return c; SetFPException(FPSCR_VXIMZ); return PPC_NAN; } - t = t + b; - if (t != t) + t += b; + if (std::isnan(t)) { - if (b != b) return b; + if (std::isnan(b)) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; } @@ -147,19 +148,19 @@ inline double NI_madd(double a, double c, double b, bool negate = false) inline double NI_msub(double a, double c, double b, bool negate = false) { double t = a * c; - if (t != t) + if (std::isnan(t)) { - if (a != a) return a; - if (b != b) return b; // ! - if (c != c) return c; + if (std::isnan(a)) return a; + if (std::isnan(b)) return b; // ! + if (std::isnan(c)) return c; SetFPException(FPSCR_VXIMZ); return PPC_NAN; } - t = t - b; - if (t != t) + t -= b; + if (std::isnan(t)) { - if (b != b) return b; + if (std::isnan(b)) return b; SetFPException(FPSCR_VXISI); return PPC_NAN; }