Macos 为什么Mac ABI要求x86-32的16字节堆栈对齐?

Macos 为什么Mac ABI要求x86-32的16字节堆栈对齐?,macos,memory-alignment,callstack,calling-convention,abi,Macos,Memory Alignment,Callstack,Calling Convention,Abi,我可以理解旧的PPC RISC系统甚至x86-64的这一要求,但对于久经考验的真正的x86?在这种情况下,堆栈只需在4字节边界上对齐。是的,某些MMX/SSE指令需要16字节对齐,但如果这是被调用方的要求,则应确保对齐正确。为什么每一个来电者都有这个额外的要求?这实际上会导致性能下降,因为每个呼叫站点都必须管理此需求。我错过什么了吗 更新:经过进一步调查,并咨询了一些内部同事,我对此有了一些理论: 操作系统的PPC、x86和x64版本之间的一致性 似乎GCC codegen现在一致地执行子esp

我可以理解旧的PPC RISC系统甚至x86-64的这一要求,但对于久经考验的真正的x86?在这种情况下,堆栈只需在4字节边界上对齐。是的,某些MMX/SSE指令需要16字节对齐,但如果这是被调用方的要求,则应确保对齐正确。为什么每一个来电者都有这个额外的要求?这实际上会导致性能下降,因为每个呼叫站点都必须管理此需求。我错过什么了吗

更新:经过进一步调查,并咨询了一些内部同事,我对此有了一些理论:

  • 操作系统的PPC、x86和x64版本之间的一致性
  • 似乎GCC codegen现在一致地执行子esp、xxx,然后“mov”将数据写入堆栈,而不是简单地执行“推送”指令。在某些硬件上,这实际上可能更快
  • 虽然这会使调用站点稍微复杂一些,但当使用默认的“cdecl”约定时,调用方清理堆栈,额外的开销非常小
  • 最后一项的问题是,对于依赖于被调用方清理堆栈的调用约定,上述要求实际上是“丑化”了codegen。例如,一些编译器决定实现一种更快的基于寄存器的调用风格,以供其内部使用(即任何不打算从其他语言或源调用的代码)?这种堆栈对齐方式可能会抵消通过在寄存器中传递某些参数而获得的一些性能增益

    更新:到目前为止,唯一真正的答案是一致性,但对我来说,这太简单了。我在x86体系结构方面有超过20年的经验,如果一致性,而不是性能,或者其他具体的东西是真正的原因,那么我恭敬地建议开发人员需要它有点幼稚。他们忽视了近三十年的工具和支持。尤其是如果他们希望工具供应商能够快速、轻松地为他们的平台调整他们的工具(可能不是……它是苹果公司的……),而不必跳过几个看似不必要的障碍

    我会给这个话题一天左右,然后关闭它

    相关的

    我认为最好将其与x86-64 ABI保持一致。

    以保持内核的一致性。这使得同一个内核可以在多个体系结构上启动而无需修改。

    我不确定,因为我没有第一手证据,但我相信原因在于SSE。如果您的缓冲区已经在16字节边界上对齐(movps与movups),并且任何x86都至少有针对mac os x的sse2,则SSE的速度要快得多。它可以由应用程序用户处理,但成本相当高。如果在ABI中强制执行的总成本不太大,那么它可能是值得的。SSE在mac os X:accelerate framework等应用非常广泛。

    嗯,os X ABI不是也做了类似RISC的有趣事情,比如在寄存器中传递小结构吗

    这表明了与其他平台理论的一致性

    仔细想想,FreeBSD系统调用api也会对齐64位值。(如lseek和mmap)

    摘自“英特尔64和IA-32体系结构优化参考手册”,第4.4.2节:

    为获得最佳性能,“数据流单指令多数据扩展指令集”和“数据流单指令多数据扩展指令集2”要求其内存操作数与16字节边界对齐。与对齐数据相比,未对齐的数据可能会导致严重的性能损失

    附录D:

    确保堆栈帧在函数输入时与16字节边界对齐非常重要,以便在整个函数调用过程中保持本地_m128数据、参数和XMM寄存器溢出位置对齐


    虽然我无法回答您的问题,但您可能会发现以下网站上的手册很有用:

    关于ABI,请特别关注:


    希望有用。

    这是一个效率问题

    确保堆栈在使用新SSE指令的每个函数中都是16字节对齐的,这会增加使用这些指令的大量开销,从而有效地降低性能

    另一方面,始终保持堆栈16字节对齐可以确保可以自由使用SSE指令,而不会造成性能损失。这是没有成本的(成本至少在说明书中衡量)。它只涉及在函数的序言中更改一个常量


    浪费堆栈空间很便宜,它可能是缓存中最热门的部分。

    首先,请注意,16字节对齐是Apple在System V IA-32 ABI中引入的一个例外

    只有在调用系统函数时才需要堆栈对齐,因为许多系统库使用SSE或Altivec扩展,它们需要16字节对齐。我在文档中找到了一个明确的引用

    您可以按照您想要的方式完美地处理堆栈帧,但是如果您尝试使用未对齐的堆栈调用系统函数,您将得到一条未对齐的堆栈错误消息

    编辑:
    作为记录,使用GCC编译时,您可以通过使用该选项来避免对齐问题。

    我的猜测是,苹果相信每个人都只使用XCode(GCC)来为您对齐堆栈。因此,要求堆栈对齐以使内核不必对齐只是一种微观优化。

    不确定为什么没有人考虑过从基于传统PowerPC的平台轻松移植的可能性

    请阅读以下内容:

    然后放大到“32位PowerPC函数调用约定”,最后是:

    “这些是32位处理器中可用的嵌入对齐模式 PowerPC