_mm256_setr_epi64x вызывает неправильные результаты при сборке x86 msvc v143 с /arch:AVX ⇐ C++
-
Anonymous
_mm256_setr_epi64x вызывает неправильные результаты при сборке x86 msvc v143 с /arch:AVX
EDIT2: я дополнительно сократил регистр и улучшил код тестирования
Я размышляю над этим уже неделю, возможно, это ошибка компилятора, но я не могу быть полностью уверен.
Я использую MSVC — 19.37.32822.0 с cmake, мои target_compile_options — /arch:AVX (/arch:AVX2 не работает, слишком). Мой target_compile_features — cxx_std_20.
Внутренние функции _mm256_setr_epi64x и _mm256_set_epi64x дают неправильные результаты. Проблема не воспроизводится в отладочных сборках. Проблема не воспроизводится для сборок g++, clang++, clang-cl со всеми комбинациями параметров SIMD.
Это происходит только в этой конкретной сборке msvc x86 с включенным /arch:AVX или /arch:AVX2. Сборка с использованием /O1 и /O2 решает проблему, а поскольку это происходит только в версии, это вполне жизнеспособное решение! Нет, это не решает проблему. Нет, это не решает проблему. р> Я не пробовал предыдущие наборы инструментов msvc — только последнюю версию v143 (MSVC — 19.37.32822.0)
РЕДАКТИРОВАТЬ: Похоже, что эту проблему сложнее воспроизвести, чем ожидалось - godbolt не позволяет мне запустить ее с помощью компилятора msvc. На первый взгляд кажется, что это связано с платформой тестирования Catch2. Я настроил репозиторий GitHub с необходимой кроссплатформенной настройкой cmake для его последовательного воспроизведения. Он автоматически получит для вас среду тестирования Catch2. После клонирования просто откройте CMakeLists.txt с помощью Visual Studio 2022, и он должен работать сразу после установки.
Вот отрывок из теста на репродукцию:
/// ОШИБКА TEST_CASE("Тестирование с помощью GIVEN", "[ошибка]") { const int64_t значения[4] {11, 22, 33, 0}; ДАНО("а1") { const __m256i a1 = _mm256_setr_epi64x( значения[0], ценности[1], ценности[2], 0 // если я заменю это значением [3], все будет работать нормально ); WHEN("a1 сохранен") { alignas(32) int64_t b1[4]; _mm256_store_si256(reinterpret_cast(b1), a1); THEN("Результат должен быть правильным") { REQUIRE(b1[0] == значения[0]); REQUIRE(b1[1] == значения[1]); REQUIRE(b1[2] == значения[2]); // здесь всегда терпит неудачу REQUIRE(b1[3] == значения[3]); } } } } Вы можете клонировать его и экспериментировать с ним. Я также добавил рабочий процесс (если вы нажмете «Действия» и войдёте в github, вы даже сможете увидеть журналы сборки/тестирования)
Я написал соответствующий отчет об ошибке на веб-сайте Microsoft, но решил, что было бы полезно получить некоторую информацию и отсюда.
EDIT2: я дополнительно сократил регистр и улучшил код тестирования
Я размышляю над этим уже неделю, возможно, это ошибка компилятора, но я не могу быть полностью уверен.
Я использую MSVC — 19.37.32822.0 с cmake, мои target_compile_options — /arch:AVX (/arch:AVX2 не работает, слишком). Мой target_compile_features — cxx_std_20.
Внутренние функции _mm256_setr_epi64x и _mm256_set_epi64x дают неправильные результаты. Проблема не воспроизводится в отладочных сборках. Проблема не воспроизводится для сборок g++, clang++, clang-cl со всеми комбинациями параметров SIMD.
Это происходит только в этой конкретной сборке msvc x86 с включенным /arch:AVX или /arch:AVX2. Сборка с использованием /O1 и /O2 решает проблему, а поскольку это происходит только в версии, это вполне жизнеспособное решение! Нет, это не решает проблему. Нет, это не решает проблему. р> Я не пробовал предыдущие наборы инструментов msvc — только последнюю версию v143 (MSVC — 19.37.32822.0)
РЕДАКТИРОВАТЬ: Похоже, что эту проблему сложнее воспроизвести, чем ожидалось - godbolt не позволяет мне запустить ее с помощью компилятора msvc. На первый взгляд кажется, что это связано с платформой тестирования Catch2. Я настроил репозиторий GitHub с необходимой кроссплатформенной настройкой cmake для его последовательного воспроизведения. Он автоматически получит для вас среду тестирования Catch2. После клонирования просто откройте CMakeLists.txt с помощью Visual Studio 2022, и он должен работать сразу после установки.
Вот отрывок из теста на репродукцию:
/// ОШИБКА TEST_CASE("Тестирование с помощью GIVEN", "[ошибка]") { const int64_t значения[4] {11, 22, 33, 0}; ДАНО("а1") { const __m256i a1 = _mm256_setr_epi64x( значения[0], ценности[1], ценности[2], 0 // если я заменю это значением [3], все будет работать нормально ); WHEN("a1 сохранен") { alignas(32) int64_t b1[4]; _mm256_store_si256(reinterpret_cast(b1), a1); THEN("Результат должен быть правильным") { REQUIRE(b1[0] == значения[0]); REQUIRE(b1[1] == значения[1]); REQUIRE(b1[2] == значения[2]); // здесь всегда терпит неудачу REQUIRE(b1[3] == значения[3]); } } } } Вы можете клонировать его и экспериментировать с ним. Я также добавил рабочий процесс (если вы нажмете «Действия» и войдёте в github, вы даже сможете увидеть журналы сборки/тестирования)
Я написал соответствующий отчет об ошибке на веб-сайте Microsoft, но решил, что было бы полезно получить некоторую информацию и отсюда.
Мобильная версия