当我找到-funroll-all-loops
选项时,我正在阅读optimization options for GCC。
其描述如下:
展开所有循环,即使它们的迭代次数不确定时也是如此 输入循环。这通常会使程序运行得更慢。 ' -funroll,全循环'暗示与' -funroll-loops'
相同的选项
如果编译时迭代次数未知,编译器如何展开循环?编译器是否需要此信息才能展开它?它产生了什么相应的C代码,如果它通常使程序运行得更慢,在什么情况下这可能是有用的?
答案 0 :(得分:3)
以下是一些显示如何操作的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;
}
编译器将用相对跳转替换第一个循环,但是在C中表示不容易。注意,以2的幂展开允许编译器使用掩码而不是(昂贵的)除法操作
答案 1 :(得分:3)
如果通常会使程序运行得更慢,那么在什么情况下这可能会有用呢?
他们假设你选择这个选项就知道你在做什么,如果你不这样做,你就不应该使用这个选项。
gcc将要做什么,我使用了这个示例程序:
#include <stdio.h>
void f(int j )
{
for( int k = 0; k < j; ++k )
{
printf( "%d\n", k ) ;
}
}
并使用godbolt对其进行测试,并根据剩余的迭代次数生成跳转表( see it live ):
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
答案 2 :(得分:2)
它可以做类似的事情:
while(n >= 8){
foo(); foo(); foo(); foo(); foo(); foo(); foo(); foo();
n -= 8;
}
while(n > 0){
foo();
n--;
}
当然,Duff的设备可以省去写第二个循环。
为什么这样?这取决于用户。
如果foo()
花费的时间超过几个周期,或,如果原始循环占用整个挂钟时间的5%,或,如果{{1}通常很小,这可能不值得麻烦。
答案 3 :(得分:0)
你不能假设编译器的中间表示存在对应的C代码这样的东西。但在这种情况下,我希望最接近的等价物类似于Duff's Device,这是一个可以在计算位置输入的序列(通常在循环中)。