使用gcc正确展开循环的方法

时间:2013-09-30 21:31:27

标签: c optimization gcc loop-unrolling

#include <stdio.h>
int main() {
        int i;
        for(i=0;i<10000;i++){
            printf("%d",i);
    }
}

我想使用gcc循环展开此代码 但即使使用旗帜。

gcc -O2 -funroll-all-loops --save-temps unroll.c

我得到的汇编代码包含一个10000次迭代的循环

_main:
Leh_func_begin1:
        pushq   %rbp
Ltmp0:
movq    %rsp, %rbp
Ltmp1:
pushq   %r14
pushq   %rbx
Ltmp2:
xorl    %ebx, %ebx
leaq    L_.str(%rip), %r14
.align  4, 0x90
LBB1_1:
xorb    %al, %al
movq    %r14, %rdi
movl    %ebx, %esi
callq   _printf
incl    %ebx
cmpl    $10000, %ebx
jne LBB1_1
popq    %rbx
popq    %r14
popq    %rbp
ret
Leh_func_end1:

可以告诉我如何在gcc中正确实现循环展开

3 个答案:

答案 0 :(得分:7)

循环展开不会给这个代码带来任何好处,因为函数调用printf()本身的开销在每次迭代完成的工作中占主导地位。编译器可能已经意识到这一点,并且由于要求它优化代码,因此它可能会决定展开会增加代码大小,从而没有明显的运行时性能增益,并且决定引发指令高速缓存未命中的风险太高执行展开。

加速此循环所需的展开类型需要减少对printf()本身的调用次数。我不知道任何能够做到这一点的优化编译器。

作为展开循环以减少printf()次调用次数的示例,请考虑以下代码:

void print_loop_unrolled (int n) {
    int i = -8;
    if (n % 8) {
        printf("%.*s", n % 8, "01234567");
        i += n % 8;
    }
    while ((i += 8) < n) {
        printf("%d%d%d%d%d%d%d%d",i,i+1,i+2,i+3,i+4,i+5,i+6,i+7);
    }
}

答案 1 :(得分:6)

gcc具有最大循环展开参数。

您必须使用-O3 -funroll-loops并使用参数max-unroll-timesmax-unrolled-insnsmax-average-unrolled-insns

示例:

-O3 -funroll-loops --param max-unroll-times=200

答案 2 :(得分:1)

替换

 printf("%d",i);

 volatile int j = i;

并查看循环是否展开。