Я обнаружил проблему с скомпилированным кодом, однако пока не нашел решения. Но кажется, что это всего лишь проблема лягушек, и g ++ исправляет ее.
Эта проблема лучше всего проиллюстрирована на примере некоторых кодов сборки. Строка кода auto arr(e);
компилируется в некоторые инструкции перемещения для копирования данных из вектора в стек; clang использует (при компиляции с -mavx) инструкции avx2, подобные следующим (синтаксис AT & T):
vmovaps 0xa0(%rax),%ymm0
vmovaps %ymm0,0x120(%rsp)
...
Где% rax - адрес текущего массива в векторе. Целевое значение arr находится в 0x80 (% rsp). Программа будет копировать в 32-байтовые фрагменты (256-битные инструкции avx2).
Однако проблема становится понятной, если взглянуть на значения: %rax = 0x55555556be70
в моем тесте отладки. проблема состоит в том, что vmovaps (перемещать выровненный пакет с одинарной точностью) в 256-битный регистр avx2 ожидает, что цель и источник выровнены по границам 256 или 32 байта (0x20), однако% rax выровнен только по 16 байтам. При компиляции без alignas clang использует vmovups (та же инструкция, но не требует выравнивания данных).
Таким образом, проблема в том, что распределитель std :: vector не учитывает alignas и не выравнивает массив на границах 64 байта. g ++ также не выравнивает массив внутри вектора по 32-байтовым границам и не использует инструкции avx, когда также не используется -O [not 0]. Однако g ++ всегда использует 128-битные регистры xmm, которые должны быть выровнены только до 16 байтов, в которые распределитель выравнивает данные с обоими компиляторами.
EDIT:
Я только что понял, что забыл скомпилировать с -std = c ++ 17. с этим флагом у меня работает clang ++. Код выглядит так же, но распределитель корректно выравнивает код на границе 64 байта. Так что я думаю, это связано со старой библиотекой. Может быть, вы можете отправить мне свой бинарный файл, тогда я мог бы более подробно взглянуть на него.