Справочная информация:
У меня есть блок оптимизированных подпрограмм Delphi / BASM, в основном для тяжелых вычислений. Некоторые из этих подпрограмм содержат внутренние циклы, для которых я могу добиться значительного ускорения, если начало цикла выровнено по границе DQWORD (16-байт). Я могу гарантировать, что рассматриваемые петли выровнены по желанию, если я знаю выравнивание в обычной точке входа.
Насколько я вижу, компилятор Delphi выравнивает процедуры / функции по границам DWORD и, например, добавление функций к устройству может изменить выравнивание последующих. Однако, пока я дополняю конец подпрограмм кратными 16, я могу гарантировать, что последующие подпрограммы также выровнены - или выровнены, в зависимости от выравнивания первой подпрограммы. Поэтому я попытался поместить критические подпрограммы в начале раздела реализации модуля и поместить перед ними немного кода дополнения, чтобы первая процедура была выровнена по DQWORD.
Это выглядит примерно так:
interface
procedure FirstProcInUnit;
implementation
procedure __PadFirstProcTo16;
asm
// variable number of NOP instructions here to get the desired code length
end;
procedure FirstProcInUnit;
asm //should start at DQWORD boundary
//do something
//padding to align the following label to DQWORD boundary
@Some16BAlignedLabel:
//code, looping back to @Some16BAlignedLabel
//do something else
ret #params
//padding to get code length to multiple of 16
end;
initialization
__PadFirstProcTo16; //call this here so that it isn't optimised out
ASSERT ((NativeUInt(Pointer(@FirstProcInUnit)) AND $0F) = 0, 'FirstProcInUnit not DQWORD aligned');
end.
Это что-то вроде боли в шее, но я могу заставить такого рода вещи работать, когда это необходимо. Проблема в том, что когда я использую такой юнит в других проектах или вносю некоторые изменения в другие юниты в том же проекте, это все равно может нарушить выравнивание самого __PadFirstProcTo16
. Аналогично, повторная компиляция одного и того же проекта с разными версиями компилятора (например, D2009 и D2010) обычно также нарушает выравнивание. Таким образом, единственный способ сделать что-то подобное, что я обнаружил, был вручную - это почти что последнее, что нужно сделать, когда весь остальной проект находится в окончательной форме.
Вопрос 1:
Есть ли другой способ добиться желаемого эффекта, гарантирующего, что (хотя бы некоторые конкретные) подпрограммы будут выровнены по DQWORD?
Вопрос 2:
Какие именно факторы влияют на выравнивание кода компилятором и (как) я мог бы использовать такие специфические знания для преодоления проблемы, изложенной здесь?
Предположим, что для ответа на этот вопрос "не беспокойтесь о выравнивании кода / связанных, по-видимому, небольших преимуществах в скорости" это не допустимый ответ.