繁体   English   中英

为什么编译器不优化这种初始化?

[英]Why does the compiler not optimize this initialization?

考虑以下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 在所有情况下,编译的程序集在用42覆盖其中10个之前写入所有15个零。

我想可能只是没有针对这个案例编写优化,但对我来说这似乎是一个相当明显和常见的情况。 有没有阻止优化的东西?

我在x86-32 Linux上使用这些命令:

gcc -std=c99 -S -O3 hello.c
clang -std=c99 -S -O3 hello.c

这不是一个非常科学的解释,而只是一种直觉(但是,我确实碰巧知道GCC的一些内部结构)。

为了可靠地进行所需的优化,编译器必须管理子数组切片 然后它变得非常复杂且容易出错。 优化那么多的编译器可能会占用大量内存(用于子数组的符号表示)和大量的编译时间。 这通常不值得努力(最好在编译器内部优化循环)。

顺便说一下,GCC有一个插件框架和MELT扩展(MELT是一个扩展GCC的lispy域特定语言,我是MELT的主要作者)。 因此,您可以尝试添加新的优化传递(通过MELT扩展或某些C ++插件)来完成工作。 你很快就会意识到你的传递要么非常具体,要么需要处理大量的GCC内部表示,并且很可能会破坏编译时间和内存以获得极少的收益。

请注意,GCC和Clang都巧妙地展开了两个循环(这在很大程度上取决于性能)。

顺便说一句, Frama-C (由同事开发的C程序的静态分析器)值分析器似乎能够推断出关于你的arr良好属性

因此,请随意将该优化添加到GCC。 如果您不知道(或没有时间 - 许多个月或几年)如何添加它,请随时向能够根据您的需求增强GCC的公司或组织付款。 可能需要一百万欧元(或美元)/ 3年的项目来完成有趣案例的优化工作。

如果您认真考虑花这么多钱,请通过电子邮件与我联系。

具有这种优化的编译器需要一些启发式来禁用它们(例如,如果arr是一个百万个成员的数组,并且你编写了一些Erasthothenes的筛子,编译器努力保留所有子切片的联合可能是不值得的。编译时的复合索引)

顺便说一句,你会接受一个20倍慢的优化编译器(在编译时更慢)获得一个增益(在运行时可能只有一小部分),这在实践中很少发生并且不是很重要吗? 最后,我不认为这是优化的常见情况 因人而异。

您可能对源代码变换器PIPS4U感兴趣

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM