如果您编写的应用程序是:
现代整个程序优化编译器可以优化所有堆栈分配(例如GCC,MSVC,ICC)吗?在这种情况下,它似乎应该能够静态地分配所有可能的堆栈空间。 “整个程序”我的意思是编译器可以访问/ all /源代码(在运行时没有可能的dlopen'ing事物等)。
答案 0 :(得分:2)
如果您保证您所声明的条件,那么是:可以有效地将堆栈完全静态分配。每个函数都有一个堆栈内存块。
然而,实际编译器会这样做吗?否。
它绝对没有任何事情可做。实际上,它可能收益少于零。通常,大部分工作堆栈都在缓存中,因此对它的修改非常便宜。如果堆栈在静态内存中,那么任何特定函数的“堆栈”内存被缓存的唯一时间就是你最近调用过那个函数。使用真实堆栈,您更有可能在缓存中工作。
此外,为每个函数提供一个堆栈内存块可以轻松地使程序的静态内存使用量大大超出需要的范围。堆栈是固定大小的构造;无论你有多少函数,堆栈都占用一定的大小。如果你有100,000个函数,并且每个函数占用64个字节的空间,那么你的静态“堆栈”必须占用大约6.4MB的空间。
为什么呢?你永远不会在任何时候使用大部分内存。该程序可以在1MB甚至512KB的堆栈中运行良好;为什么要占用6倍的内存呢?
因此,这不是性能优化,而会使程序的内存膨胀。
答案 1 :(得分:1)
这是一条很长时间无法发表评论的评论:
请注意,虽然理论上可以优化所有堆栈分配,但可以分配比所需更多的堆栈分配。这不是OP所要求的,但考虑可能会很有趣。找到所需的最小尺寸分配等同于解决暂停问题。想象一下程序结构如下:
<do 'something'>
<call last thing which happens to require more
stack space than everything else in 'something'>
如果<do 'something'>
&#34;暂停&#34;你只需要额外的堆栈空间。
您还可以想象其他变化,其中优化变得任意变硬。例如,您的程序可以简单地使用用户输入评估3SAT表达式并根据具体情况执行某些操作 - 但该3SAT表达式可能具有或不具有任何导致true的值。
也许有一个更简单的情况:用户可能根本不会输入需要更多堆栈空间进行处理的输入。
答案 2 :(得分:1)
编译器可以这样做,但它可能是一个特定的优化,它可能不会。
如果你有一个完全内联的程序,你将负责为函数调用设置堆栈帧的开销。
但是,如果您还想摆脱局部变量的堆栈分配,编译器必须将这些局部变量转换为全局变量。我所知道的编译器没有这样做,并且在某些平台上,与局部变量相比,它需要额外的指令来引用全局变量(因为地址必须加载两个指令而不是一个)。另外,由于引用堆栈变量是一种常见的操作,因此通常将其编码为较小的指令。
答案 3 :(得分:0)
除非你在列表中添加“不使用任何外部库”,否则对外部函数的任何调用都需要堆栈设置,因为它们已被编译,期望调用代码以特定方式传递其参数,很可能是堆栈。此外,这些库几乎肯定必须调整他们自己的本地人的堆栈。
此外,根据您的精确应用程序,即使您知道堆栈可以静态分配,编译器也可能很难知道您的代码中没有任何回调等会导致需要堆栈分配。
我只是看不到编译会尝试这种优化的情况,因为分配堆栈空间已经非常快(我相信几个寄存器操作)