diff mbox series

[RFC,14/15] softfloat: Use float_cmask for addsub_floats

Message ID 20201021045149.1582203-15-richard.henderson@linaro.org
State New
Headers show
Series [RFC,01/15] qemu/int128: Add int128_or | expand

Commit Message

Richard Henderson Oct. 21, 2020, 4:51 a.m. UTC
Testing more than one class at a time is better done with masks.
Sort a few case combinations before the NaN check, which should
be assumed to be least probable.  Share the pick_nan call between
the add and subtract cases.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 fpu/softfloat-parts.c.inc | 70 +++++++++++++++++++++------------------
 1 file changed, 37 insertions(+), 33 deletions(-)
diff mbox series

Patch

diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 49bde45521..d2b6454903 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -247,13 +247,13 @@  static PARTS_TYPE
 FUNC(addsub_floats)(PARTS_TYPE a, PARTS_TYPE b,
                     bool subtract, float_status *s)
 {
-    bool a_sign = a.sign;
     bool b_sign = b.sign ^ subtract;
+    int ab_mask = float_cmask(a.cls) | float_cmask(b.cls);
 
-    if (a_sign != b_sign) {
+    if (a.sign != b_sign) {
         /* Subtraction */
 
-        if (a.cls == float_class_normal && b.cls == float_class_normal) {
+        if (likely(ab_mask == float_cmask_normal)) {
             if (a.exp > b.exp || (a.exp == b.exp && GEU(a.frac, b.frac))) {
                 b.frac = SHR_JAM(b.frac, a.exp - b.exp);
                 a.frac = SUB(a.frac, b.frac);
@@ -261,7 +261,7 @@  FUNC(addsub_floats)(PARTS_TYPE a, PARTS_TYPE b,
                 a.frac = SHR_JAM(a.frac, b.exp - a.exp);
                 a.frac = SUB(b.frac, a.frac);
                 a.exp = b.exp;
-                a_sign ^= 1;
+                a.sign ^= 1;
             }
 
             if (EQ0(a.frac)) {
@@ -270,35 +270,37 @@  FUNC(addsub_floats)(PARTS_TYPE a, PARTS_TYPE b,
             } else {
                 int shift = CLZ(a.frac) - 1;
                 a.frac = SHL(a.frac, shift);
-                a.exp = a.exp - shift;
-                a.sign = a_sign;
+                a.exp -= shift;
             }
             return a;
         }
-        if (is_nan(a.cls) || is_nan(b.cls)) {
-            return FUNC(pick_nan)(a, b, s);
-        }
-        if (a.cls == float_class_inf) {
-            if (b.cls == float_class_inf) {
-                float_raise(float_flag_invalid, s);
-                return FUNC(parts_default_nan)(s);
-            }
-            return a;
-        }
-        if (a.cls == float_class_zero && b.cls == float_class_zero) {
+
+        /* 0 - 0 */
+        if (ab_mask == float_cmask_zero) {
             a.sign = s->float_rounding_mode == float_round_down;
             return a;
         }
-        if (a.cls == float_class_zero || b.cls == float_class_inf) {
-            b.sign = a_sign ^ 1;
-            return b;
+
+        /* Inf - Inf */
+        if (unlikely(ab_mask == float_cmask_inf)) {
+            float_raise(float_flag_invalid, s);
+            return FUNC(parts_default_nan)(s);
         }
-        if (b.cls == float_class_zero) {
-            return a;
+
+        if (!(ab_mask & float_cmask_anynan)) {
+            if (a.cls == float_class_inf || b.cls == float_class_zero) {
+                return a;
+            }
+            if (b.cls == float_class_inf || a.cls == float_class_zero) {
+                b.sign = a.sign ^ 1;
+                return b;
+            }
+            g_assert_not_reached();
         }
     } else {
         /* Addition */
-        if (a.cls == float_class_normal && b.cls == float_class_normal) {
+
+        if (likely(ab_mask == float_cmask_normal)) {
             if (a.exp > b.exp) {
                 b.frac = SHR_JAM(b.frac, a.exp - b.exp);
             } else if (a.exp < b.exp) {
@@ -312,16 +314,18 @@  FUNC(addsub_floats)(PARTS_TYPE a, PARTS_TYPE b,
             }
             return a;
         }
-        if (is_nan(a.cls) || is_nan(b.cls)) {
-            return FUNC(pick_nan)(a, b, s);
-        }
-        if (a.cls == float_class_inf || b.cls == float_class_zero) {
-            return a;
-        }
-        if (b.cls == float_class_inf || a.cls == float_class_zero) {
-            b.sign = b_sign;
-            return b;
+
+        if (!(ab_mask & float_cmask_anynan)) {
+            if (a.cls == float_class_inf || b.cls == float_class_zero) {
+                return a;
+            }
+            if (b.cls == float_class_inf || a.cls == float_class_zero) {
+                b.sign = b_sign;
+                return b;
+            }
+            g_assert_not_reached();
         }
     }
-    g_assert_not_reached();
+
+    return FUNC(pick_nan)(a, b, s);
 }