Skip to content

Commit c30574b

Browse files
committed
See if a more explicit r4_equality implementation fixes the issues
1 parent 0489876 commit c30574b

File tree

1 file changed

+77
-23
lines changed

1 file changed

+77
-23
lines changed

src/mono/mono/mini/interp/interp-simd.c

+77-23
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <wasm_simd128.h>
77
#endif
88

9+
#include <mono/utils/mono-math.h>
10+
911
#ifdef INTERP_ENABLE_SIMD
1012

1113
gboolean interp_simd_enabled = TRUE;
@@ -175,13 +177,18 @@ interp_v128_op_bitwise_or (gpointer res, gpointer v1, gpointer v2)
175177
static void
176178
interp_v128_op_bitwise_equality (gpointer res, gpointer v1, gpointer v2)
177179
{
178-
gint64 *v1_cast = (gint64*)v1;
179-
gint64 *v2_cast = (gint64*)v2;
180+
gint64 *v1_typed = (gint64*)v1;
181+
gint64 *v2_typed = (gint64*)v2;
180182

181-
if (*v1_cast == *v2_cast && *(v1_cast + 1) == *(v2_cast + 1))
182-
*(gint32*)res = 1;
183-
else
184-
*(gint32*)res = 0;
183+
bool succeeded = true;
184+
185+
if (v1_typed [0] != v2_typed [0]) {
186+
succeeded = false;
187+
} else if (v1_typed [1] != v2_typed [1]) {
188+
succeeded = false;
189+
}
190+
191+
*(gint32*)res = succeeded ? 1 : 0;
185192
}
186193

187194
// op_ExclusiveOr
@@ -195,36 +202,83 @@ interp_v128_op_exclusive_or (gpointer res, gpointer v1, gpointer v2)
195202
static void
196203
interp_v128_op_bitwise_inequality (gpointer res, gpointer v1, gpointer v2)
197204
{
198-
gint64 *v1_cast = (gint64*)v1;
199-
gint64 *v2_cast = (gint64*)v2;
205+
gint64 *v1_typed = (gint64*)v1;
206+
gint64 *v2_typed = (gint64*)v2;
207+
208+
bool succeeded = false;
200209

201-
if (*v1_cast == *v2_cast && *(v1_cast + 1) == *(v2_cast + 1))
202-
*(gint32*)res = 0;
203-
else
204-
*(gint32*)res = 1;
210+
if (v1_typed [0] != v2_typed [0]) {
211+
succeeded = true;
212+
} else if (v1_typed [1] != v2_typed [1]) {
213+
succeeded = true;
214+
}
215+
216+
*(gint32*)res = succeeded ? 1 : 0;
205217
}
206218

207-
// Vector128<float>EqualsFloatingPoint
219+
static bool
220+
r4_float_equality(float v1, float v2)
221+
{
222+
if (v1 == v2) {
223+
return true;
224+
} else if (mono_isnan (v1) && mono_isnan (v2)) {
225+
return true;
226+
}
227+
228+
return false;
229+
}
230+
231+
// Vector128<float>.EqualsFloatingPoint
208232
static void
209233
interp_v128_r4_float_equality (gpointer res, gpointer v1, gpointer v2)
210234
{
211-
v128_r4 v1_cast = *(v128_r4*)v1;
212-
v128_r4 v2_cast = *(v128_r4*)v2;
213-
v128_r4 result = (v1_cast == v2_cast) | ~((v1_cast == v1_cast) | (v2_cast == v2_cast));
214-
memset (&v1_cast, 0xff, SIZEOF_V128);
235+
float *v1_typed = (float*)v1;
236+
float *v2_typed = (float*)v2;
237+
238+
bool succeeded = true;
239+
240+
if (!r4_float_equality(v1_typed [0], v2_typed [0])) {
241+
succeeded = false;
242+
} else if (!r4_float_equality(v1_typed [1], v2_typed [1])) {
243+
succeeded = false;
244+
} else if (!r4_float_equality(v1_typed [2], v2_typed [2])) {
245+
succeeded = false;
246+
} else if (!r4_float_equality(v1_typed [3], v2_typed [3])) {
247+
succeeded = false;
248+
}
249+
250+
*(gint32*)res = succeeded ? 1 : 0;
251+
}
252+
253+
static bool
254+
r8_float_equality(double v1, double v2)
255+
{
256+
bool succeeded = false;
257+
258+
if (v1 == v2) {
259+
return true;
260+
} else if (mono_isnan (v1) && mono_isnan (v2)) {
261+
return true;
262+
}
215263

216-
*(gint32*)res = memcmp (&v1_cast, &result, SIZEOF_V128) == 0;
264+
return false;
217265
}
218266

219267
static void
220268
interp_v128_r8_float_equality (gpointer res, gpointer v1, gpointer v2)
221269
{
222-
v128_r8 v1_cast = *(v128_r8*)v1;
223-
v128_r8 v2_cast = *(v128_r8*)v2;
224-
v128_r8 result = (v1_cast == v2_cast) | ~((v1_cast == v1_cast) | (v2_cast == v2_cast));
225-
memset (&v1_cast, 0xff, SIZEOF_V128);
270+
double *v1_typed = (double*)v1;
271+
double *v2_typed = (double*)v2;
272+
273+
bool succeeded = true;
274+
275+
if (!r8_float_equality(v1_typed [0], v2_typed [0])) {
276+
succeeded = false;
277+
} else if (!r8_float_equality(v1_typed [1], v2_typed [1])) {
278+
succeeded = false;
279+
}
226280

227-
*(gint32*)res = memcmp (&v1_cast, &result, SIZEOF_V128) == 0;
281+
*(gint32*)res = succeeded ? 1 : 0;
228282
}
229283

230284
// op_Multiply

0 commit comments

Comments
 (0)