【问题标题】:Compiler optimization of functions parameters函数参数的编译器优化
【发布时间】:2011-01-21 15:31:26
【问题描述】:

函数参数放置在堆栈上,但编译器可以通过使用可选寄存器来优化此任务。如果只有 1-2 个参数,而不是有 256 个参数时,这种优化就会启动是有道理的(并不是说希望有最大数量的参数)。

如何找出某个编译器(例如 gcc)的参数限制(参数数量),在哪里可以确定会使用这种优化?

【问题讨论】:

  • 函数参数是否入栈(如果有,是哪些)取决于平台。对于除 32 位 x86 之外的所有其他内容,它始终是“寄存器中的一些参数”——只有(现在很古老)x86 传统会将它们放在堆栈中。
  • 你为什么想知道这个?
  • 参数传递不是编译器优化“选择”。如何传递参数取决于代码的互操作性需求。查看 stackoverflow 中的“调用约定”和/或“ABI”。在同一平台上存在多个这样的调用约定(__cdecl__fastcall__stdcall 和所有这些)在很大程度上是 x86/DOS/Windows 特定的事情。
  • @FrankH 感谢您为我指明了正确的方向,这正是我所需要的。将评论作为答案发布:)
  • 不是赏金猎人,我读这个网站是为了好玩 ;-)

标签: c++ c function optimization cpu-registers


【解决方案1】:

函数参数放置在堆栈上,但编译器可以通过使用可选寄存器来优化此任务。

正如 FrankH 在他的 cmets 中所说的那样,正如我将在我的回答中所说的那样,相关系统的应用程序二进制接口决定了如何将参数传递给函数 - 这称为该平台的调用约定。

更复杂的是,x86 32 位实际上有几个。这是历史性的,因为当Win32 bit 到达时,每个人都疯狂地做着不同的事情。

所以,是的,您可以通过以这种方式编写函数调用来“优化”,但不,您不应该这样做。您应该遵循平台的标准。因为诚实的事实是,堆栈访问的速度可能不会使您的代码减慢到您需要与系统上的其他所有人不兼容的程度。

为什么需要 ABI/标准调用约定?好吧,就使用处理器寄存器、堆栈等而言,应用程序必须就它应该去哪里和去哪里达成一致。如果一个函数决定它的所有参数都在寄存器中,而另一个函数决定一些参数在堆栈中,它们将如何互操作?此外,您可能会遇到术语临时寄存器来表示那些您不必恢复的寄存器。如果你调用一个期望它不理会一些寄存器的函数会发生什么?

不管怎样,至于你的要求,这里有一些 ABI 文档:

最后一个是我最喜欢的。引用它:

在旧的 DOS 操作系统时代,通常可以结合开发 来自不同供应商的工具,几乎没有兼容性问题。对于 32 位 Windows, 局势已经完全失控。不同的编译器使用不同的数据 表示、不同的函数调用约定和不同的目标文件格式。 虽然静态链接库传统上被认为是特定于编译器的,但 动态链接库 (DLL) 的广泛使用使得函数的分布 二进制形式的库更常见。

因此,无论您试图通过修改函数调用方法来优化,都不要这样做。寻找另一种优化方式。分析您的代码。如果您认为它有帮助,请研究您为编译器 (-OX) 所做的编译器优化并转储程序集以检查速度是否真的那么重要

【讨论】:

    【解决方案2】:

    对于公开可见的功能,这在 ABI 标准中有记录。对于无法从外部引用的函数,无论如何,所有的赌注都没有。

    【讨论】:

      【解决方案3】:

      您必须阅读编译器的精美手册。如果幸运的话,您会在函数调用约定的描述中找到它。否则,对于像 gcc 这样的 OSS 编译器,您可能必须阅读其源代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-21
        • 2016-12-09
        • 2012-12-26
        • 2018-11-21
        • 1970-01-01
        • 2012-11-04
        相关资源
        最近更新 更多