通常在编写代码时,我发现自己多次使用来自特定函数调用的值。我意识到一个明显的优化是在变量中捕获这些重复使用的值。这(伪代码):
function add1(foo){ foo + 1; }
...
do_something(foo(1));
do_something_else(foo(1));
变成:
function add1(foo){ foo + 1; }
...
bar = foo(1);
do_something(bar);
do_something_else(bar);
但是,根据我的经验,明确地这样做会使代码的可读性降低。我假设如果我们选择的语言允许函数具有副作用,编译器就无法进行这种优化。
最近我研究了这个,如果我理解正确的话,这种优化是/可以对函数必须是纯的语言进行。这并不让我感到惊讶,但据说这也可以用于不纯函数。通过一些快速的谷歌搜索,我发现了这些片段: GCC 4.7 Fortran 改进
在执行前端优化时,-faggressive-function-elimination 选项允许删除重复的函数调用,即使对于不纯函数也是如此。
例如,在某些语言中,函数不允许有副作用。因此,如果一个程序使用相同的参数多次调用同一个函数,编译器可以立即推断该函数的结果只需要计算一次。在允许函数具有副作用的语言中,另一种策略是可能的。优化器可以确定哪个函数没有副作用,并将此类优化限制为无副作用的函数。仅当优化器可以访问被调用函数时,才可能进行此优化。
根据我的理解,这意味着优化器可以确定函数何时是纯函数或非纯函数,并在函数为纯函数时执行此优化。我这样说是因为如果一个函数在给定相同的输入时总是产生相同的输出,并且没有副作用,那么它将满足这两个条件被认为是纯的。
这两个片段向我提出了两个问题。
- 如果函数不是纯函数,编译器如何能够安全地进行这种优化?(如-faggressive-function-elimination)
- 编译器如何确定一个函数是否是纯函数?(如维基百科文章中建议的策略)
最后:
- 这种优化可以应用于任何语言,还是仅在满足某些条件时应用?
- 即使对于极其简单的功能,这种优化是否值得?
- 从堆栈中存储和检索值会产生多少开销?
如果这些是愚蠢或不合逻辑的问题,我深表歉意。它们只是我最近一直好奇的一些事情。:)