考虑下面的C代码:
extern void foo(int* ip);
void myfunc(void)
{
int arr[15] = {0};
for (int i=0; i<10; i++)
{
arr[i] = 42;
}
foo(arr);
}
我尝试使用gcc和clang以及-O3
和-Os
。在所有情况下,编译后的程序集都会写入所有15个零,然后再用42个覆盖其中的10个。
我想可能还没有针对这种情况编写任何优化,但是对于我来说,这似乎是一个显而易见的常见情况。是否有阻碍优化的因素?
我在x86-32 Linux上并使用了以下命令:
gcc -std=c99 -S -O3 hello.c
clang -std=c99 -S -O3 hello.c
这不是一个很科学的解释,而只是一种直觉(但是,我确实知道GCC的某些内部知识)。
为了可靠地进行所需的优化,编译器必须管理子数组或切片。然后,它变得非常复杂且容易出错。最优化的编译器可能会消耗大量内存(用于子数组的符号表示)和大量编译时间。这通常是不值得的工作(最好在编译器内部花费以优化循环)。
顺便说一句,GCC有一个插件框架和MELT扩展(MELT是扩展GCC的一种轻快的领域专用语言,我是MELT的主要作者)。因此,您可以尝试添加新的优化遍(通过MELT扩展或某些C ++插件)来完成工作。您很快就会意识到,您的传递可能是非常特殊的,或者将需要处理大量的GCC内部表示,并且很可能会浪费编译时间和内存,而获得的收益却很少。
请注意,GCC和Clang都巧妙地展开了两个循环(这在性能方面很重要)。
顺便说一句,Frama-C(由同事开发的用于C程序的静态分析器)价值分析器似乎能够推断出您的arr
因此,可以随时将优化添加到GCC中。如果您不知道(或没有时间-数月或数年)如何添加它,请随时向能够增强GCC的公司或组织付款,以满足您的需求。要使这种优化在有趣的情况下进行,可能需要一个100万欧元(或美元)/ 3年的项目。
如果您真的想花这么多钱,请通过电子邮件与我联系。
具有这种优化功能的编译器将需要一些启发式方法来禁用它们(例如,如果arr
是一百万个成员的数组,而您正在编写一些Erasthothenes的筛子,则可能不值得编译器付出任何努力来保持所有子切片的并集)。综合索引)。
顺便说一句,您会接受二十倍慢的优化编译器(在编译时变慢)来获得增益(运行时可能是百分之一的百分比),这种增益在实践中很少发生并且不是很重要吗?最后,我不认为这是优化的常见情况。YMMV。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句