我正在阅读GCC的优化选项时,发现了选项-funroll-all-loops
。
它的描述如下:
展开所有循环,即使它们进入循环时迭代次数不确定。这通常会使程序运行更慢。 '-funroll-all-loops'意味着与'-funroll-loops'相同的选项
如果编译器无法在编译时知道循环迭代次数,那么它如何展开循环呢?编译器不需要这些信息来展开吗?它生成什么相应的C代码?在什么情况下这可能有用,如果通常会使程序运行更慢?
我正在阅读GCC的优化选项时,发现了选项-funroll-all-loops
。
它的描述如下:
展开所有循环,即使它们进入循环时迭代次数不确定。这通常会使程序运行更慢。 '-funroll-all-loops'意味着与'-funroll-loops'相同的选项
如果编译器无法在编译时知道循环迭代次数,那么它如何展开循环呢?编译器不需要这些信息来展开吗?它生成什么相应的C代码?在什么情况下这可能有用,如果通常会使程序运行更慢?
int iterations = 100;
int unrollValue = 8;
while (iterations%unrollvalue)
{
// insert loop code here
iterations--;
}
while (iterations)
{
// insert unrollValue copies of loop code here
iterations-= unrollValue;
}
如果这个选项通常会使程序运行更慢,那么它在什么情况下会有用呢?
嗯,他们假设如果你选择了这个选项,你知道你在做什么,如果你不知道,就不应该使用这个选项。
gcc将会做什么呢?我用了这个样例程序:
#include <stdio.h>
void f(int j )
{
for( int k = 0; k < j; ++k )
{
printf( "%d\n", k ) ;
}
}
我已经使用godbolt进行测试,它根据剩余迭代次数生成跳转表(在此处查看实例):
cmpl $1, %ebp
movl $1, %ebx
je .L1
testl %r12d, %r12d
je .L27
cmpl $1, %r12d
je .L28
cmpl $2, %r12d
je .L29
cmpl $3, %r12d
je .L30
cmpl $4, %r12d
je .L31
cmpl $5, %r12d
je .L32
cmpl $6, %r12d
je .L33
printf
,那么好处基本上为零;-) - Mike Dunlaveywhile(n >= 8){
foo(); foo(); foo(); foo(); foo(); foo(); foo(); foo();
n -= 8;
}
while(n > 0){
foo();
n--;
}
当然,使用 Duff's Device可以避免编写第二个循环。
为什么这样做呢?这取决于用户。如果 foo()
花费的时间多于几个周期,或者原始循环所占用的总体墙钟时间少于5%,或者 n
通常很小,则可能不值得麻烦。
你不能假设编译器的中间表示形式有所谓的相应的 C 代码。但在这种情况下,我期望最接近的等效物是类似于Duff's Device的东西,它是一个序列(通常在循环中),可以在计算位置进入。