Подтвердить что ты не робот

Почему Mac ABI требует 16-байтного выравнивания стека для x86-32?

Я могу понять это требование для старых систем PPC RISC и даже для x86-64, но для старого испробованного x86? В этом случае стек должен быть выровнен только на 4 байтовых границах. Да, некоторые инструкции MMX/SSE требуют 16-битных выравниваний, но если это требование вызываемого абонента, то это должно гарантировать правильность выравнивания. Зачем требовать каждого звонящего с этим дополнительным требованием? Это может привести к некоторому снижению производительности, потому что каждый узел вызова должен управлять этим требованием. Я что-то пропустил?

Обновление:. После некоторого расследования этого и некоторых консультаций с некоторыми внутренними коллегами у меня есть некоторые теории об этом:

  • Согласованность между версией ОС PPC, x86 и x64
  • Кажется, что GGC-кодеген теперь последовательно выполняет sub esp, xxx, а затем "переносит" данные в стек, а не просто выполняет команду "push". Это может быть быстрее на некоторых аппаратных средствах.
  • Хотя это немного усложняет сайты вызовов, при использовании стандартного соглашения "cdecl", когда вызывающий пользователь очищает стек, очень мало дополнительных накладных расходов.

Проблема, с которой я столкнулась с последним, заключается в том, что для вызова соглашений, которые полагаются на очистку стека, вышеуказанные требования действительно "угадывают" код. Например, какой-то компилятор решил реализовать более быстрый стиль вызова на основе регистров для собственного внутреннего использования (т.е. Любой код, который не предназначен для вызова с других языков или источников)? Это свойство выравнивания стека может свести на нет некоторые достижения в производительности, достигнутые при передаче некоторых параметров в регистры.

Обновление: Пока единственные реальные ответы были согласованными, но для меня это слишком легко ответить. У меня есть более чем 20-летний опыт работы с архитектурой x86, и если согласованность, а не производительность или что-то еще конкретное, на самом деле причина, то я почтительно полагаю, что это немного наивно для разработчиков, требующих этого. Они игнорируют почти три десятилетия инструментов и поддержки. Особенно, если они ожидают, что поставщики инструментов быстро и легко адаптируют свои инструменты для своей платформы (возможно, не... it есть Apple...), не перепрыгивая через несколько, казалось бы, ненужных обручей.

Я расскажу эту тему еще раз, а затем закрою ее...

Связанные

4b9b3361

Ответ 1

В "Справочном руководстве по оптимизации архитектуры Intel®64 и IA-32", раздел 4.4.2:

"Для обеспечения максимальной производительности потоковые SIMD-расширения и потоковые SIMD-расширения 2 требуют, чтобы их операнды памяти были выровнены с границами 16 байтов. Невысококачественные данные могут приводить к значительному снижению производительности по сравнению с согласованными данными".

Из приложения D:

"Важно обеспечить, чтобы кадр стека был выровнен с 16-байтовой границей при вводе функции, чтобы локальные данные __m128, параметры и местоположения разлива регистров XMM были выровнены по всему вызову функции."

http://www.intel.com/Assets/PDF/manual/248966.pdf

Ответ 2

Я считаю, что он поддерживает его с помощью x86-64 ABI.

Ответ 3

Я не уверен, поскольку у меня нет доказательств из первых рук, но я считаю, что причиной является SSE. SSE намного быстрее, если ваши буферы уже выровнены на границе 16 байтов (movps vs movups), и любой x86 имеет как минимум sse2 для mac os x. Его может заботиться пользователь приложения, но стоимость довольно значительна. Если общая стоимость обязательного использования в ABI не слишком значительна, это может стоить того. SSE используется повсеместно в Mac OS X: ускорение рамки и т.д.

Ответ 4

Во-первых, обратите внимание, что выравнивание по 16 байтов является исключением, введенным Apple в System V IA-32 ABI.

Выравнивание стека требуется только при вызове системных функций, так как многие системные библиотеки используют расширения SSE или Altivec, для которых требуется выравнивание по 16 байт. Я нашел явную ссылку в странице libgmalloc MAN.

Вы можете отлично обрабатывать свой стек стека, как хотите, но если вы попытаетесь вызвать системную функцию с несогласованным стеком, вы получите сообщение misaligned_stack_error.

Edit: Для записи вы можете избавиться от проблем с выравниванием при компиляции с помощью GCC с помощью опции mstack-realign.

Ответ 5

Это проблема эффективности.

Удостоверившись, что стек равен 16 байтам в каждой функции, использующей новые инструкции SSE, добавляет много накладных расходов для использования этих инструкций, эффективно снижая производительность.

С другой стороны, при сохранении выравнивания в 16 байт все время гарантирует, что вы можете свободно использовать инструкции SSE без штрафа за производительность. Для этого нет затрат (стоимость, измеренная по меньшей мере в инструкциях). Это связано только с изменением константы в прологе функции.

Тратить пространство стека дешево, это, вероятно, самая горячая часть кеша.

Ответ 6

Я предполагаю, что Apple считает, что все просто используют XCode (gcc), который выравнивает стек для вас. Поэтому, требуя выравнивания стека, чтобы ядро ​​не было просто микро-оптимизацией.

Ответ 7

Хм, разве OS X ABI также не смешно RISC, как такие вещи, как передача небольших структур в регистры?

Таким образом, это указывает на согласованность с теорией других платформ.

Подумайте об этом, сценарий FreeBSD syscall api также выравнивает 64-битные значения. (например, lseek и mmap)

Ответ 8

Пока я не могу ответить на ваш вопрос ПОЧЕМУ, вы можете найти руководства на следующем сайте полезными:

http://www.agner.org/optimize/

Что касается ABI, обратите особое внимание на:

http://www.agner.org/optimize/calling_conventions.pdf

Надеюсь, что это полезно.

Ответ 9

Чтобы поддерживать согласованность в ядре. Это позволяет загружать одно и то же ядро ​​на нескольких архитектурах без модификации.

Ответ 10

Не знаете, почему никто не рассмотрел возможность простой переносимости с платформы, основанной на PowerPC?

Прочтите это:

http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/LowLevelABI/100-32-bit_PowerPC_Function_Calling_Conventions/32bitPowerPC.html#//apple_ref/doc/uid/TP40002438-SW20

И затем увеличьте масштаб до 32-битных условных обозначений функций PowerPC и, наконец, это:

"Это режимы выравнивания вложения, доступные в 32-битном Окружение PowerPC:

Режим выравнивания мощности получается из правил выравнивания, используемых IBM XLC компилятор для операционной системы AIX. Это значение по умолчанию режим выравнивания для версии GCC для PowerPC-архитектуры, используемой в AIX и Mac OS X. Поскольку этот режим, скорее всего, будет совместим между компиляторами PowerPC-архитектуры от разных поставщиков, обычно используется с структурами данных, которые совместно используются различными программы".

В связи с устаревшим фоном OSX на базе PowerPC, переносимость является важным соображением - она ​​диктует в соответствии с конвенцией все пути к компилятору AIX XLC. Когда вы считаете, что необходимо обеспечить, чтобы все инструменты и приложения работали вместе с минимальной доработкой, я считаю, что важно придерживаться как можно большего числа прежних ABI.

Это дает философию, и чтение дальше - это правило, явно упомянутое ( "Пролог и Эпилог" ):

Вызываемая функция отвечает за распределение его собственный стек стека, чтобы сохранить 16-байтовое выравнивание в стек. Эта операция выполняется секцией кода, называемой пролог, который компилятор помещает перед телом подпрограммы. После тела подпрограммы компилятор помещает эпилог в восстановить процессор до состояния, которое было до подпрограммы звоните.