Как компилятор знает выравнивание физического адреса?

Я знаю, что некоторые архитектуры ЦП не поддерживают равноудаленный адресный доступ (например, архитектуры ARM до ARM 4 не имели инструкций для доступа к объектам полуслова в памяти). И какой-то компилятор (например, некоторая версия GCC) для этой архитектуры будет использовать серию доступа к памяти, когда обнаруживает смещенный адрес, так что смещенный доступ почти прозрачен для разработчиков (см. Окончательное руководство по GCC, Уильям фон Хаген)

Но мне интересно, как компилятор знает, выравнивается ли адрес или нет? В конце концов, то, что видит компилятор, это виртуальный адрес (эффективный адрес, EA), если он видит что-либо. Когда программа запускается, EA может быть сопоставлена ​​с любым физическим адресом ОС. Даже если виртуальный адрес выровнен, результирующий физический адрес может быть смещен, не так ли? Выравнивание физического адреса - это то, что действительно имеет значение, и передача по адресным строкам ЦП.

Поскольку компилятор вообще не знает о физическом адресе, как он может быть достаточно умным, чтобы узнать, выровнен ли адрес переменной?

Ответ 2

Выравнивание - очень полезный атрибут для объектного кода, отчасти потому, что некоторые машины настаивают на "согласованном доступе", но на современных компьютерах, поскольку строки кэша оказывают огромное влияние на производительность, и, таким образом, выравнивание по кодам кода/циклов/данных/блокировок является таким образом требование от вашего локального компилятора.

Практически все загрузчики в мире поддерживают загрузку кода при двух-двух выравниваемых границах некоторого скромного размера и вверх. (Ассемблеры и линкеры поддерживают это также с помощью различных директив ALIGNMENT). Часто линкеры и загрузчики выравнивают первое загруженное значение в любом случае до известного размера границы; Операционные системы с виртуальной памятью часто обеспечивают удобную границу, основанную на размере страницы VM (связь с другим ответом).

Таким образом, компилятор может по существу знать, что такое выравнивание его испускаемого кода/данных. И, отслеживая, сколько кода он испустил, он может знать, что такое выравнивание любого испускаемого значения. Если он требует выравнивания, он может выдавать директиву компоновщика или для скромных размеров просто прокладывать до тех пор, пока испущенное количество кода не будет соответствующим образом выровнено.

Из-за этого вы можете быть уверены, что большинство компиляторов не будут размещать конструкции кода или данных таким образом, чтобы границы кросс-кеш (или другие наложенные на архитектуру) границы оказывали существенное влияние на производительность, если только не направлены на это.