emscripten-core / emscripten-core/emscripten

Incorrect result for vector at -O3 with -msimd128

Open
#14,643 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
27.6k
Forks
3.6k
Avg merge
1d 1h
Merged PRs (30d)
105

Description

I'm trying to test a vector extension-based implementation of `_mm_cvttps_epi32`, and my tests pass at -O2 but not -O3. I've [attached a reproducer](https://github.com/emscripten-core/emscripten/files/6812945/sse2.c.gz) (not preprocessed, so you can check other compilers if you want), compile with something like `emcc -s ENVIRONMENT=shell -Wextra -Werror -O3 -msimd128 -DSIMDE_TEST_BARE -DSIMDE_NO_NATIVE -o sse2.js sse2.c`.

If you run the output as-is you'll get a failure. Uncommenting line 24084 (which just prints the result before testing it) causes the error to vanish, as does switching the -O2 to -O3. Commenting out the test cases with NaNs and out-of-range values also works around the issue.

The relevant implementation is line 19446-19463, and the test which fails is at line 24085.

C-Reduce seems to be having trouble with this one. I've pasted what I got below, but I don't really trust that there isn't any undefined behavior so you might want to ignore it.

```c
typedef int int32_t;
typedef long int64_t;
typedef float simde_float32;
__builtin_va_list simde_test_debug_printf__ap;
void simde_test_debug_printf_(char *format, ...) {
__builtin_va_start(simde_test_debug_printf__ap, format);
__builtin_abort();
}
int simde_assert_equal_vi32_(unsigned vec_len, int32_t a[], int32_t b[]) {
for (unsigned i = 0; i < vec_len; i++)
if (__builtin_expect(a[i] != b[i], 0))
simde_test_debug_printf_("");
return 0;
}
typedef struct {
simde_float32 f32 __attribute__((__vector_size__(16)));
} simde__m128_private;
simde_float32 simde__m128_from_private_r;
simde__m128_private simde__m128_to_private(v) {
simde__m128_private r;
__builtin_memcpy(&r, &v, sizeof(r));
return r;
}
typedef struct {
int32_t i32 __attribute__((__vector_size__(16)));
} simde__m128i_private;
typedef int64_t simde__m128i __attribute__((__vector_size__(16)));
simde__m128i simde_mm_cvttps_epi32_r;
int32_t test_simde_mm_cvttps_epi32_a_[1];
int32_t test_simde_mm_cvttps_epi32_a__0;
simde__m128i_private test_simde_mm_cvttps_epi32_r_;
int test_simde_mm_cvttps_epi32() {
struct {
simde_float32 a[4];
} test_vec[] = {{__builtin_nanf("")}, {}, {}, {}, {}, {}};
for (unsigned i = 0; i < sizeof(test_vec) / sizeof(test_vec[0]); i++) {
simde__m128_private r_;
__builtin_memcpy(&r_, test_vec[i].a, sizeof(r_));
simde__m128_private v = r_;
__builtin_memcpy(&simde__m128_from_private_r, &v,
sizeof(simde__m128_from_private_r));
{
simde__m128_private a_ =
simde__m128_to_private(simde__m128_from_private_r);
__typeof__(test_simde_mm_cvttps_epi32_r_.i32) valid_input =
a_.f32 < 2147483648.0f & a_.f32 >= -2147483648.0f;
test_simde_mm_cvttps_epi32_r_.i32 = valid_input;
simde__m128i_private v = test_simde_mm_cvttps_epi32_r_;
__builtin_memcpy(&simde_mm_cvttps_epi32_r, &v,
sizeof(simde_mm_cvttps_epi32_r));
}
int32_t b_[sizeof(int32_t)];
{
void *mem_addr = test_simde_mm_cvttps_epi32_a_;
simde__m128i a = simde_mm_cvttps_epi32_r;
__builtin_memcpy(mem_addr, &a, sizeof(simde_mm_cvttps_epi32_r));
;
__builtin_memcpy(b_, &a, sizeof(simde_mm_cvttps_epi32_r));
}
simde_assert_equal_vi32_(sizeof(test_simde_mm_cvttps_epi32_a__0),
test_simde_mm_cvttps_epi32_a_, b_);
}
return 0;
}
int test_suite_tests;
int main() {
for (unsigned i = 0; i < sizeof(test_suite_tests); i++)
test_simde_mm_cvttps_epi32();
}
```

The problem happens with emscripten tot ("emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 2.0.26 (a560a678aca86f05dd7888dd5d71cc00c4cabe41)"), v8 version 9.3.341.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.