Tor*_*erg 9 c compiler-optimization
考虑以下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);
}
Run Code Online (Sandbox Code Playgroud)
我尝试用gcc和clang,用-O3和-Os.在所有情况下,编译的程序集在用42覆盖其中10个之前写入所有15个零.
我想可能只是没有针对这个案例编写优化,但对我来说这似乎是一个相当明显和常见的情况.有没有阻止优化的东西?
我在x86-32 Linux上使用这些命令:
gcc -std=c99 -S -O3 hello.c
clang -std=c99 -S -O3 hello.c
Run Code Online (Sandbox Code Playgroud)
这不是一个非常科学的解释,而只是一种直觉(但是,我确实碰巧知道GCC的一些内部结构).
为了可靠地进行所需的优化,编译器必须管理子数组或切片.然后它变得非常复杂且容易出错.优化那么多的编译器可能会占用大量内存(用于子数组的符号表示)和大量的编译时间.这通常不值得努力(最好在编译器内部优化循环).
顺便说一下,GCC有一个插件框架和MELT扩展(MELT是一个扩展GCC的lispy域特定语言,我是MELT的主要作者).因此,您可以尝试添加新的优化传递(通过MELT扩展或某些C++插件)来完成工作.你很快就会意识到你的传递要么非常具体,要么需要处理大量的GCC内部表示,并且很可能会破坏编译时间和内存以获得极少的收益.
请注意,GCC和Clang都巧妙地展开了两个循环(这在很大程度上取决于性能).
顺便说一句,Frama-C(由同事开发的C程序的静态分析器)值分析器似乎能够推断出你的良好属性arr
因此,请随意将该优化添加到GCC.如果您不知道(或没有时间 - 许多个月或几年)如何添加它,请随时向能够根据您的需求增强GCC的公司或组织付款.可能需要一百万欧元(或美元)/ 3年的项目来完成有趣案例的优化工作.
如果您认真考虑花这么多钱,请通过电子邮件与我联系.
具有这种优化的编译器需要一些启发式来禁用它们(例如,如果arr是一个百万个成员的数组,并且你编写了一些Erasthothenes的筛子,编译器的努力可能不值得保留所有的子切片编译时的复合索引).
顺便说一下,你会接受一个20倍慢的优化编译器(在编译时更慢)获得增益(在运行时可能只有百分之几),这在实践中很少发生并且不是很重要吗?最后,我不认为这是优化的常见情况.因人而异.
您可能对源代码变换器PIPS4U感兴趣