MSVC + Union + SSE = некорректный скомпилированный код
Наблюдаю странное поведение компилятора MSVC. Подозреваю, что я неправильно использую union
и нарушаю выравнивание. Компилирую 64х битным MSVC командой cl /std:c++20 /O2 /Z7 algo.cpp
.
Имеется структура Board
размера 40 байт и функция print_board
. При компиляции с флагом /O2
проблемный участок кода (помечен комментом) превращается в набор SSE инструкций, а запуск программы приводит к выводу мусора (idx
считается неверно и выходит за границу массива). Проблема пропадает в билде без /O2
. Так же она пропадает, если развернуть цикл как написано в закомменченных строчках (работает корректно даже с /O2
, причём компилятор генерирует вообще другой код вроде бы без SSE и инлайнит всю функцию).
#include <cstdio>
using Bitboard = unsigned long long;
struct Board {
union {
struct {
Bitboard a,b,c,d;
};
Bitboard bbs[4];
};
Bitboard occ;
};
void print_board(const Board &b) {
constexpr char dict[] = ".ABCD";
for (int i = 0; i < 8; ++i) {
printf("%d ", i);
for (int j = 0; j < 8; ++j) {
int idx = 0, off = i*8+j;
// баг проявляется здесь
for (int k = 1; k <= 4; ++k)
idx += k * ((b.bbs[k-1] >> off) & 1);
/* idx = 1 * ((b.bbs[0] >> off) & 1) */
/* + 2 * ((b.bbs[1] >> off) & 1) */
/* + 3 * ((b.bbs[2] >> off) & 1) */
/* + 4 * ((b.bbs[3] >> off) & 1); */
printf("%c", dict[idx]);
}
printf("\n");
}
printf(" 01234567\n");
}
int main() {
// Сгенерировать случайную доску с фиксированным seed.
Board b;
b.bbs[0] = 9078816779534945ull;
b.bbs[1] = 576465150354178056ull;
b.bbs[2] = 2523335239976686852ull;
b.bbs[3] = 15337864866599151762ull;
b.occ = 18446744073709551615ull;
/* Board b = make_random_board(); */
print_board(b);
}
Ожидаемый вывод, получаемый без оптимизаций или с оптимизациями, но с развёрнутым циклом.
0 ADCBDAAD
1 CACDCDBB
2 CDDCDABD
3 ADCDCDAA
4 DADCDADD
5 ADBDCCAC
6 DDCDDADD
7 CCDBDCDD
01234567
Вывод с флагом /O2
и инструкциями SSE в дизассемблере.
0 ♠ ÄD Ä
1 Ä√♠
2 ♠Ä♠♠ÄD√Ä
3 ♠♠√♠♠
4 DADCDADD
5 ADBDCCAC
6 DDCDDADD
7 CCDBDCDD
01234567
UPD
Дополнил код до полностью воспроизводимого примера.