On 5/23/23 16:33, Richard Henderson wrote:


The tests are poorly ordered, testing many unlikely things before the most likely thing (normal).  A better ordering would be

     if (likely(tp##_is_normal(arg))) {
     } else if (tp##_is_zero(arg)) {
     } else if (tp##_is_zero_or_denormal(arg)) {
     } else if (tp##_is_infinity(arg)) {
     } else {
         // nan case
     }

Secondly, we compute the classify bitmask, and then deconstruct the mask again in set_fprf_from_class.  Since we don't use the classify bitmask for anything else, better would be to compute the fprf value directly in the if-ladder.

So something like this:

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index a66e16c2128c..daed97ca178e 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -141,62 +141,30 @@ static inline int ppc_float64_get_unbiased_exp(float64 f)
     return ((f >> 52) & 0x7FF) - 1023;
 }
-/* Classify a floating-point number. */
-enum {
-    is_normal   = 1,
-    is_zero     = 2,
-    is_denormal = 4,
-    is_inf      = 8,
-    is_qnan     = 16,
-    is_snan     = 32,
-    is_neg      = 64,
-};
-
-#define COMPUTE_CLASS(tp)                                      \
-static int tp##_classify(tp arg)                               \
-{                                                              \
-    int ret = tp##_is_neg(arg) * is_neg;                       \
-    if (unlikely(tp##_is_any_nan(arg))) {                      \
-        float_status dummy = { };  /* snan_bit_is_one = 0 */   \
-        ret |= (tp##_is_signaling_nan(arg, &dummy)             \
-                ? is_snan : is_qnan);                          \
-    } else if (unlikely(tp##_is_infinity(arg))) {              \
-        ret |= is_inf;                                         \
-    } else if (tp##_is_zero(arg)) {                            \
-        ret |= is_zero;                                        \
-    } else if (tp##_is_zero_or_denormal(arg)) {                \
-        ret |= is_denormal;                                    \
-    } else {                                                   \
-        ret |= is_normal;                                      \
-    }                                                          \
-    return ret;                                                \
-}
-
-COMPUTE_CLASS(float16)
-COMPUTE_CLASS(float32)
-COMPUTE_CLASS(float64)
-COMPUTE_CLASS(float128)
-
-static void set_fprf_from_class(CPUPPCState *env, int class)
+static void set_fprf(CPUPPCState *env, uint8_t ret)
 {
-    static const uint8_t fprf[6][2] = {
-        { 0x04, 0x08 },  /* normalized */
-        { 0x02, 0x12 },  /* zero */
-        { 0x14, 0x18 },  /* denormalized */
-        { 0x05, 0x09 },  /* infinity */
-        { 0x11, 0x11 },  /* qnan */
-        { 0x00, 0x00 },  /* snan -- flags are undefined */
-    };
-    bool isneg = class & is_neg;
-
     env->fpscr &= ~FP_FPRF;
-    env->fpscr |= fprf[ctz32(class)][isneg] << FPSCR_FPRF;
+    env->fpscr |= ret << FPSCR_FPRF;
 }
-#define COMPUTE_FPRF(tp) \
-void helper_compute_fprf_##tp(CPUPPCState *env, tp arg) \
-{                                                       \
-    set_fprf_from_class(env, tp##_classify(arg));       \
+#define COMPUTE_FPRF(tp)                                       \
+void helper_compute_fprf_##tp(CPUPPCState *env, tp arg)        \
+{                                                              \
+    int ret;                                                   \
+    if (tp##_is_normal(arg)) {                                 \
+        ret = 0x0408;                                          \
+    } else if (tp##_is_zero(arg)) {                            \
+        ret = 0x0212;                                          \
+    } else if (tp##_is_zero_or_denormal(arg)) {                \
+        ret = 0x1418;                                          \
+    } else if (unlikely(tp##_is_infinity(arg))) {              \
+        ret = 0x0509;                                          \
+    } else {                                                   \
+        float_status dummy = { };  /* snan_bit_is_one = 0 */   \
+        ret = (tp##_is_signaling_nan(arg, &dummy)              \
+               ? 0x0000 : 0x1111);                             \
+    }                                                          \
+    set_fprf(env, tp##_is_neg(arg) ? (uint8_t)ret : ret >> 8); \
 }
COMPUTE_FPRF(float16)


Not tested beyond compilation, but if Zoltan reports that it helps
I can write a commit message and submit it.

Paolo


Reply via email to