G CC не имеет возможности сделать это.
Вместо этого скомпилируйте в asm и выполните некоторые манипуляции с текстом на этом выходе . Например, gcc -O3 -S foo.c
, затем запустите некоторый скрипт на foo.s
для нечетного выравнивания перед некоторыми метками функций, перед компиляцией в конечный исполняемый файл с gcc -o benchmark foo.s
.
Один простой способ (который стоит от 32 до 95 байт Это простой способ c:
.balign 64 # byte-align by 64
.space 32 # emit 32 bytes (of zeros)
starts_half_way_into_a_cache_line:
testfunc1:
Настройка вывода GCC / clang после компиляции - это, в общем, хороший способ узнать, что g cc должен иметь сделанный. Все ссылки на другой код / данные внутри и снаружи функции используют имена символов, ничто не зависит от относительных расстояний между функциями или абсолютными адресами до тех пор, пока вы не соберете (и ссылку) , поэтому редактирование источника asm на этом этапе совершенно безопасно. (В другом ответе предлагается скопировать окончательный машинный код; это очень просто agile, см. Комментарии под ним.)
Сценарий автоматической обработки текста позволит вам провести эксперимент с большим количеством кода. Это может быть так просто, как
awk '/^testfunc.*:/ { print ".p2align 6; .skip 32"; print $0 }' foo.s
сделать это перед каждым ярлыком, который соответствует шаблону ^testfunc.*
. (Предполагая, что имя подчеркивания не будет начальным.)
Или даже используйте sed
, который имеет удобную опцию -i
, чтобы сделать это "на месте", переименовав выходной файл поверх оригинала, или perl
есть нечто подобное. К счастью, вывод компилятора довольно формульный c, для данного компилятора это должно быть довольно простой задачей сопоставления с образцом.
Имейте в виду, что эффекты выравнивания кода не всегда являются чисто локальными. Ветви в одной функции могут быть псевдонимами (в предсказателе ветвления) с ветвями из другой функции в зависимости от деталей выравнивания.
Точно знать сложно почему изменение влияет на производительность, особенно если вы рано говорите о функции, где она сдвигает адреса ветвей в остальной части функции на пару байтов. Однако вы не говорите об этих изменениях, а просто перемещаете всю функцию. Но это изменит выравнивание относительно других функций, поэтому это может повлиять на тесты, вызывающие несколько функций, чередующихся друг с другом, или если функции вызывают друг друга.
Другие эффекты выравнивания включают упаковку uop-cache на современных x86, а также блок выборки. (Помимо очевидного эффекта оставления неиспользуемого пространства в строке I-кэша).
В идеале вы должны вставить только 0,63 байта, чтобы достичь желаемой позиции относительно 64- граница байта. Этот раздел является неудачной попыткой заставить это работать.
.p2align
и .balign
1 поддерживают дополнительный 3-й аргумент, который определяет максимум количество заполнения, так что мы близки к тому, чтобы сделать это с директивами GAS. Возможно, мы можем использовать это, чтобы определить, близки ли мы к нечетной или четной границе, проверив, вставил ли он какие-либо отступы или нет. (Предположим, мы говорим только о 2 случаях, а не о 4 случаях 16-байтовых данных, например, относительно 64-байтовых.)
# DOESN'T WORK, and maybe not fixable
1: # local label
.balign 64,,31 # pad with up to 31 bytes to reach 64-byte alignment
2:
.balign 32 # byte-align by 32, maybe to the position we want, maybe not
.ifne 2b - 1b
# there is space between labels 2 and 1 so that balign reached a 64-byte boundary
.space 32
.endif # else it was already an odd boundary
Но, к сожалению, это не работает: Error: non-constant expression in ".if" statement
. Если код между метками 1:
и 2:
имеет фиксированный размер, например .long 0xdeadbeef
, он будет собираться просто отлично. Таким образом, очевидно, что GAS не позволит вам запросить с .if
, сколько заполнено вставленной директивы выравнивания.
Сноска 1: .align
это либо .p2align
(степень 2), либо .balign
(байт). ) в зависимости от того, для какой цели вы собираете. Вместо того, чтобы помнить, что и на какой цели, я бы рекомендовал всегда использовать .p2align
или .balign
, а не .align
.