我可以理解旧PPC RISC系统的这个要求,甚至是x86-64,但是对于旧的,经过验证的x86?在这种情况下,堆栈只需要在4字节边界上对齐.是的,某些MMX/SSE指令需要16字节对齐,但如果这是被调用者的要求,则应确保对齐正确.为什么要为每个来电者增加这项额外要求?这实际上可能会导致性能下降,因为每个呼叫站点都必须管理此要求.我错过了什么吗?
更新:在对此进行一些调查并与一些内部同事进行一些咨询后,我对此有一些理论:
PPC,x86和x64版操作系统之间的一致性
似乎GCC codegen现在始终执行子esp,xxx然后将数据"移动"到堆栈而不是简单地执行"推送"指令.在某些硬件上,这实际上可能更快.
虽然这确实使调用站点变得复杂,但是当使用默认的"cdecl"约定时,调用者清理堆栈时几乎没有额外的开销.
我对最后一项的问题是,对于依赖于被调用者清理堆栈的调用约定,上述要求实际上 "uglify"了codegen.例如,某些编译器决定为自己的内部使用实现更快的基于寄存器的调用样式(即任何不打算从其他语言或源调用的代码)?这种堆栈对齐可能会通过在寄存器中传递一些参数来抵消一些性能提升.
更新:到目前为止,唯一真正的答案是一致性,但对我来说,答案有点太容易了.我有超过20年的x86架构经验,如果一致性,而不是性能,或其他具体的东西,那么我真的是因为我恭敬地建议开发人员要求它有点天真.他们忽略了近三十年的工具和支持.特别是如果他们期望工具供应商能够快速轻松地为他们的平台调整他们的工具(可能不是......这是 Apple ......),而不必跳过几个看似不必要的箍.
我会在另一天左右给出这个话题,然后关闭它......
这是我的堆栈框架,我不关心你的堆栈框架!
rob mayoff.. 29
从"英特尔®64和IA-32架构优化参考手册",第4.4.2节:
"为了获得最佳性能,Streaming SIMD Extensions和Streaming SIMD Extensions 2要求其内存操作数与16字节边界对齐.与对齐数据相比,未对齐数据可能会导致严重的性能损失."
来自附录D:
"在函数输入时确保堆栈帧与16字节边界对齐非常重要,以保持本地__m128数据,参数和XMM寄存器溢出位置在整个函数调用中保持一致."
http://www.intel.com/Assets/PDF/manual/248966.pdf
从"英特尔®64和IA-32架构优化参考手册",第4.4.2节:
"为了获得最佳性能,Streaming SIMD Extensions和Streaming SIMD Extensions 2要求其内存操作数与16字节边界对齐.与对齐数据相比,未对齐数据可能会导致严重的性能损失."
来自附录D:
"在函数输入时确保堆栈帧与16字节边界对齐非常重要,以保持本地__m128数据,参数和XMM寄存器溢出位置在整个函数调用中保持一致."
http://www.intel.com/Assets/PDF/manual/248966.pdf
我不确定,因为我没有第一手证据,但我相信原因是SSE.如果缓冲区已经在16字节边界(movps vs movups)上对齐,则SSE要快得多,并且任何x86对于mac os x至少具有sse2.它可以由应用程序用户负责,但成本非常高.如果在ABI中强制要求的总成本不是太大,那么它可能是值得的.SSE在mac os X中非常普遍使用:加速框架等......
我相信这是为了让它与x86-64 ABI保持一致.