-fstrict-aliasing включен в Clang по умолчанию. Если его выключить -fno-strict-aliasing, то метаданные TBAA (type-based alias analysis) не будут сгенерированы и TBAA не сможет доказать что float *a и int gi не алиасят друг друга, соответственно векторизации не будет.
Я ваши циклы разнёс по отдельным функциям и скормил LLVM. Вот что с вашими циклами сделал экспериментальный векторизатор (ну и остальные оптимизации):
1. заменён на memset
2. векторизован + хвост memset
3. выброшен за ненадобностью, так как b[10] он не инициализирует :)
4. не векторизирован
5. не векторизирован
6. векторизован
7. не векторизирован
8. векторизован
9. векторизован
В-третиьх, вот можете посмотреть у Страуструпа описана интересная задача, в которой по асимптотике выигрывает связный список, но на практике std::vector быстрее из-за константы.
Depending on the machine architecture and the programming language, the answer will be that the vector is best for small to medium values of N. When I ran the experiment on my 8-Gbyte laptop, I found N to be much larger than 500,000.
> Да, есть случаи, когда память нужно затереть из соображений безопасности
>> Соответсвенно проблема «обнуление памяти «здесь и сейчас», вне зависимости от того, кто там дальше будет (или не будет) в неё писать» имеет чисто академический интерес.
Пересмотрел пост — теперь вижу. Да, там есть кусок кода с volatile char* и я скопировал не тот кусок. Да, в моём комментарии имелось ввиду volatile char*.
С точки зрения программиста — это массив. А с точки зрения машинного кода это скорее всего будет только два регистра. Понимаете, инициализация не-volatile данных не наблюдаема и поэтому может быть что угодно пока с точки зрения программиста всё выглядит неотличимо.
Это не наблюдаемое поведение. Компилятор имеет право сделать ну, например, SROA (scalar replacement of aggregates), и разбить ваш массив на несколько различных переменных, лежащих даже не в соседних ячейках памяти, а несипользуемые ячейки вообще не распределять в памяти (конечно же если адрес этого массива никуда не убегает (escapes)).
> Граница в том, что mov ax, bx и mov bx, ax это две разные команды, а не одна команда с двумя аргументами, куда что-то можно подставить, а что-то нет.
Вы не поверите, но это одна и та же команда с двумя полями, куда подставляется любой номер регистра. (Посмотрите в интеловском мануале: mov r/m16, r16.)
Вы тоже не можете провести точно границу. Разве граница в том, что «безтиповые» ищут по таблице?
Лексическая/синтаксическая/семантическая проверка в компиляторе ЯВУ тоже может быть реализована таблично. А в ассемблере может быть реализована и нетаблично, а алгоритмически.
> Между прочим, в C есть совершенно легальное средство работать с одной и той же памятью и как с int и как с double без преобразования указателей. Называется union. [...] но компиляторы его до сих пор поддерживают.
Потому что это единственный разрешённый стандартом способ это делать. А вот преобразования типов указателей во многих случаях — нарушение strict aliasing.
1. заменён на memset
2. векторизован + хвост memset
3. выброшен за ненадобностью, так как b[10] он не инициализирует :)
4. не векторизирован
5. не векторизирован
6. векторизован
7. не векторизирован
8. векторизован
9. векторизован
Забыли добавить «в моей версии компилятора, которым я пользуюсь»
А во-вторых, возьмите сами и попробуйте.
В-третиьх, вот можете посмотреть у Страуструпа описана интересная задача, в которой по асимптотике выигрывает связный список, но на практике std::vector быстрее из-за константы.
www.stroustrup.com/Software-for-infrastructure.pdf
>> Соответсвенно проблема «обнуление памяти «здесь и сейчас», вне зависимости от того, кто там дальше будет (или не будет) в неё писать» имеет чисто академический интерес.
Мне кажется вы немного себе противоречите.
Как видно, массива как таквого в промежуточном коде нет.
Ага, да. Внезапно DR 1054:
www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1054
В C++11 исправлено.
Вы не поверите, но это одна и та же команда с двумя полями, куда подставляется любой номер регистра. (Посмотрите в интеловском мануале: mov r/m16, r16.)
Вы тоже не можете провести точно границу. Разве граница в том, что «безтиповые» ищут по таблице?
Лексическая/синтаксическая/семантическая проверка в компиляторе ЯВУ тоже может быть реализована таблично. А в ассемблере может быть реализована и нетаблично, а алгоритмически.
Потому что это единственный разрешённый стандартом способ это делать. А вот преобразования типов указателей во многих случаях — нарушение strict aliasing.