Explorar el Código

Fix interp/fast-jit float min/max issues (#1733)

Wenyong Huang hace 3 años
padre
commit
440bbea81e

+ 32 - 32
core/iwasm/fast-jit/fe/jit_emit_numberic.c

@@ -1527,47 +1527,47 @@ jit_compile_op_f64_math(JitCompContext *cc, FloatMath math_op)
 }
 
 static float32
-local_minf(float32 f1, float32 f2)
+f32_min(float32 a, float32 b)
 {
-    if (isnan(f1))
-        return f1;
-    if (isnan(f2))
-        return f2;
-
-    return fminf(f1, f2);
+    if (isnan(a) || isnan(b))
+        return NAN;
+    else if (a == 0 && a == b)
+        return signbit(a) ? a : b;
+    else
+        return a > b ? b : a;
 }
 
-static float64
-local_min(float64 f1, float64 f2)
+static float32
+f32_max(float32 a, float32 b)
 {
-    if (isnan(f1))
-        return f1;
-    if (isnan(f2))
-        return f2;
-
-    return fmin(f1, f2);
+    if (isnan(a) || isnan(b))
+        return NAN;
+    else if (a == 0 && a == b)
+        return signbit(a) ? b : a;
+    else
+        return a > b ? a : b;
 }
 
-static float32
-local_maxf(float32 f1, float32 f2)
+static float64
+f64_min(float64 a, float64 b)
 {
-    if (isnan(f1))
-        return f1;
-    if (isnan(f2))
-        return f2;
-
-    return fmaxf(f1, f2);
+    if (isnan(a) || isnan(b))
+        return NAN;
+    else if (a == 0 && a == b)
+        return signbit(a) ? a : b;
+    else
+        return a > b ? b : a;
 }
 
 static float64
-local_max(float64 f1, float64 f2)
+f64_max(float64 a, float64 b)
 {
-    if (isnan(f1))
-        return f1;
-    if (isnan(f2))
-        return f2;
-
-    return fmax(f1, f2);
+    if (isnan(a) || isnan(b))
+        return NAN;
+    else if (a == 0 && a == b)
+        return signbit(a) ? b : a;
+    else
+        return a > b ? a : b;
 }
 
 static bool
@@ -1579,9 +1579,9 @@ compile_op_float_min_max(JitCompContext *cc, FloatArithmetic arith_op,
 
     res = is_f32 ? jit_cc_new_reg_F32(cc) : jit_cc_new_reg_F64(cc);
     if (arith_op == FLOAT_MIN)
-        func = is_f32 ? (void *)local_minf : (void *)local_min;
+        func = is_f32 ? (void *)f32_min : (void *)f64_min;
     else
-        func = is_f32 ? (void *)local_maxf : (void *)local_max;
+        func = is_f32 ? (void *)f32_max : (void *)f64_max;
 
     args[0] = lhs;
     args[1] = rhs;

+ 40 - 34
core/iwasm/interpreter/wasm_interp_classic.c

@@ -106,22 +106,48 @@ rotr64(uint64 n, uint64 c)
     return (n >> c) | (n << ((0 - c) & mask));
 }
 
-static inline double
-wa_fmax(double a, double b)
+static inline float32
+f32_min(float32 a, float32 b)
 {
-    double c = fmax(a, b);
-    if (c == 0 && a == b)
+    if (isnan(a) || isnan(b))
+        return NAN;
+    else if (a == 0 && a == b)
+        return signbit(a) ? a : b;
+    else
+        return a > b ? b : a;
+}
+
+static inline float32
+f32_max(float32 a, float32 b)
+{
+    if (isnan(a) || isnan(b))
+        return NAN;
+    else if (a == 0 && a == b)
         return signbit(a) ? b : a;
-    return c;
+    else
+        return a > b ? a : b;
 }
 
-static inline double
-wa_fmin(double a, double b)
+static inline float64
+f64_min(float64 a, float64 b)
 {
-    double c = fmin(a, b);
-    if (c == 0 && a == b)
+    if (isnan(a) || isnan(b))
+        return NAN;
+    else if (a == 0 && a == b)
         return signbit(a) ? a : b;
-    return c;
+    else
+        return a > b ? b : a;
+}
+
+static inline float64
+f64_max(float64 a, float64 b)
+{
+    if (isnan(a) || isnan(b))
+        return NAN;
+    else if (a == 0 && a == b)
+        return signbit(a) ? b : a;
+    else
+        return a > b ? a : b;
 }
 
 static inline uint32
@@ -2660,12 +2686,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 b = POP_F32();
                 a = POP_F32();
 
-                if (isnan(a))
-                    PUSH_F32(a);
-                else if (isnan(b))
-                    PUSH_F32(b);
-                else
-                    PUSH_F32(wa_fmin(a, b));
+                PUSH_F32(f32_min(a, b));
                 HANDLE_OP_END();
             }
 
@@ -2676,12 +2697,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 b = POP_F32();
                 a = POP_F32();
 
-                if (isnan(a))
-                    PUSH_F32(a);
-                else if (isnan(b))
-                    PUSH_F32(b);
-                else
-                    PUSH_F32(wa_fmax(a, b));
+                PUSH_F32(f32_max(a, b));
                 HANDLE_OP_END();
             }
 
@@ -2774,12 +2790,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 b = POP_F64();
                 a = POP_F64();
 
-                if (isnan(a))
-                    PUSH_F64(a);
-                else if (isnan(b))
-                    PUSH_F64(b);
-                else
-                    PUSH_F64(wa_fmin(a, b));
+                PUSH_F64(f64_min(a, b));
                 HANDLE_OP_END();
             }
 
@@ -2790,12 +2801,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 b = POP_F64();
                 a = POP_F64();
 
-                if (isnan(a))
-                    PUSH_F64(a);
-                else if (isnan(b))
-                    PUSH_F64(b);
-                else
-                    PUSH_F64(wa_fmax(a, b));
+                PUSH_F64(f64_max(a, b));
                 HANDLE_OP_END();
             }
 

+ 40 - 36
core/iwasm/interpreter/wasm_interp_fast.c

@@ -97,22 +97,48 @@ rotr64(uint64 n, uint64 c)
     return (n >> c) | (n << ((0 - c) & mask));
 }
 
-static inline double
-wa_fmax(double a, double b)
+static inline float32
+f32_min(float32 a, float32 b)
 {
-    double c = fmax(a, b);
-    if (c == 0 && a == b)
+    if (isnan(a) || isnan(b))
+        return NAN;
+    else if (a == 0 && a == b)
+        return signbit(a) ? a : b;
+    else
+        return a > b ? b : a;
+}
+
+static inline float32
+f32_max(float32 a, float32 b)
+{
+    if (isnan(a) || isnan(b))
+        return NAN;
+    else if (a == 0 && a == b)
         return signbit(a) ? b : a;
-    return c;
+    else
+        return a > b ? a : b;
 }
 
-static inline double
-wa_fmin(double a, double b)
+static inline float64
+f64_min(float64 a, float64 b)
 {
-    double c = fmin(a, b);
-    if (c == 0 && a == b)
+    if (isnan(a) || isnan(b))
+        return NAN;
+    else if (a == 0 && a == b)
         return signbit(a) ? a : b;
-    return c;
+    else
+        return a > b ? b : a;
+}
+
+static inline float64
+f64_max(float64 a, float64 b)
+{
+    if (isnan(a) || isnan(b))
+        return NAN;
+    else if (a == 0 && a == b)
+        return signbit(a) ? b : a;
+    else
+        return a > b ? a : b;
 }
 
 static inline uint32
@@ -2497,13 +2523,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 b = *(float32 *)(frame_lp + GET_OFFSET());
                 a = *(float32 *)(frame_lp + GET_OFFSET());
 
-                if (isnan(a))
-                    *(float32 *)(frame_lp + GET_OFFSET()) = a;
-                else if (isnan(b))
-                    *(float32 *)(frame_lp + GET_OFFSET()) = b;
-                else
-                    *(float32 *)(frame_lp + GET_OFFSET()) =
-                        (float32)wa_fmin(a, b);
+                *(float32 *)(frame_lp + GET_OFFSET()) = f32_min(a, b);
                 HANDLE_OP_END();
             }
 
@@ -2514,13 +2534,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 b = *(float32 *)(frame_lp + GET_OFFSET());
                 a = *(float32 *)(frame_lp + GET_OFFSET());
 
-                if (isnan(a))
-                    *(float32 *)(frame_lp + GET_OFFSET()) = a;
-                else if (isnan(b))
-                    *(float32 *)(frame_lp + GET_OFFSET()) = b;
-                else
-                    *(float32 *)(frame_lp + GET_OFFSET()) =
-                        (float32)wa_fmax(a, b);
+                *(float32 *)(frame_lp + GET_OFFSET()) = f32_max(a, b);
                 HANDLE_OP_END();
             }
 
@@ -2615,12 +2629,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 b = POP_F64();
                 a = POP_F64();
 
-                if (isnan(a))
-                    PUSH_F64(a);
-                else if (isnan(b))
-                    PUSH_F64(b);
-                else
-                    PUSH_F64(wa_fmin(a, b));
+                PUSH_F64(f64_min(a, b));
                 HANDLE_OP_END();
             }
 
@@ -2631,12 +2640,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 b = POP_F64();
                 a = POP_F64();
 
-                if (isnan(a))
-                    PUSH_F64(a);
-                else if (isnan(b))
-                    PUSH_F64(b);
-                else
-                    PUSH_F64(wa_fmax(a, b));
+                PUSH_F64(f64_max(a, b));
                 HANDLE_OP_END();
             }