此问题部分是GCC 5.1 Loop unrolling的后续问题。GCC中的循环展开行为
按照GCC documentation,并且如在我的回答表示对上述问题,标志,如-funroll-loops
接通“完整循环剥离(即完全除去环的具有小恒定数目的迭代)”。因此,如果启用这样的标志,编译器可以选择展开循环,如果它确定这将优化给定代码段的执行。
尽管如此,我注意到在我的一个项目中,即使相关标志未启用,GCC有时也会展开循环。例如,考虑下面的一段简单的代码:
int main(int argc, char **argv)
{
int k = 0;
for(k = 0; k < 5; ++k)
{
volatile int temp = k;
}
}
当-O1
编译时,循环被展开,并与任何现代版本的GCC产生下面的汇编代码:
main:
movl $0, -4(%rsp)
movl $1, -4(%rsp)
movl $2, -4(%rsp)
movl $3, -4(%rsp)
movl $4, -4(%rsp)
movl $0, %eax
ret
即使与附加-fno-unroll-loops -fno-peel-loops
编译,以确保标志是禁用,海湾合作委员会意外仍然执行循环展开上述例子。
这个观察将我引向以下密切相关的问题。为什么GCC执行循环展开,即使与此行为相对应的标志被禁用?展开也受其他标志控制,即使-funroll-loops
被禁用,可以使编译器在某些情况下展开循环。有没有办法完全禁用GCC中的循环展开(从编译-O0
开始)?
有趣的是,锵编译器在这里有预期的行为,并似乎在-funroll-loops
被启用,而不是在其他情况下,仅执行展开。
在此先感谢,有关此事的任何其他见解将不胜感激!
恭喜。你发现不同的编译器在行为上有所不同,你传给他们的标志并不总是表示你认为他们的意思。欢迎来到真实的世界。 –
它会破坏你程序的功能吗? – Serge
不,它不会破坏功能。对于GCC如何执行循环展开以及如何调整这种行为,这更是一个普遍关心的问题。 – Pyves