【问题标题】:Why does gcc4 not unroll this loop?为什么 gcc4 不展开这个循环?
【发布时间】:2012-11-12 01:06:24
【问题描述】:

gcc 4.4.6 文档中声明:

-funroll-all-loops:
Unroll all loops, even if their number of iterations is uncertain 
when the loop isentered. 

我正在编译这段代码:

int unroll(){
  int i = 0;
  int array[1000];
  do {
    use(i,array);
    i++;
  }while(i<1000);
  return(0);
}

void use(int i, int *array){
   int x = i*5;
   array[i] = x;
}

...一次使用funroll-all-loops 优化,一次没有:

OPT = -funroll-all-loops
NOOPT = -O0

然后我使用diff 比较每个的汇编代码(使用-S -fverbose-asm 生成)。

生成的代码是相同的。

尝试将循环更改为do while; 调整循环计数器(最多 100 个); 更改循环体内的语句。

我会错过什么?为什么这个循环没有展开?

更新

Nikos C 建议使用--param max-unroll-times=N 提高循环注册参数,其中 N 是上限。 虽然这是一个明智的建议,但它并没有改变行为。 我还将循环迭代次数降低到只有 10 次。 还更新了代码以实际“做”某事,没有变化。

【问题讨论】:

  • -O0 告诉 gcc 不要应用任何优化,包括展开。试试-O-O2
  • 我认为NOOPT = -O0 表示一种控制情况(即,预期没有展开循环的情况)。
  • 是的,这是故意的。 NOOPT 是用于生成汇编代码以进行比较而无需展开循环的标志。
  • 尝试强制编译器内联use()。通常根本没有理由展开具有函数调用的循环。
  • 又一个If I disable optimization, why doesn't gcc optimize? 问题。

标签: c optimization gcc gcc4 loop-unrolling


【解决方案1】:

因为您在“OPT”案例中禁用了所有其他优化,所以您告诉编译器展开所有循环,然后拒绝他这样做的方法,例如循环归纳等。尝试

NOOPT = -O2
OPT = -O2 -funroll-all-loops

如果我翻译 sn-p(稍微更改为外部函数以避免任何内联和死代码消除)

void use(int i, int *array);

int unroll(){
  int i = 0;
  int array[1000];
  do {
    use(i,array);
    i++;
  }while(i<1000);
  return(0);
}

使用gcc -O2 -funroll-all-loops test.c -o test2.o -c,生成的目标代码 展开八次:

  0000000000000000 <unroll>:
  0:   53                      push   %rbx
  1:   31 db                   xor    %ebx,%ebx
  3:   48 81 ec a0 0f 00 00    sub    $0xfa0,%rsp
  a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
  10:   89 df                   mov    %ebx,%edi
  12:   48 89 e6                mov    %rsp,%rsi
  15:   e8 00 00 00 00          callq  1a <unroll+0x1a>
  1a:   8d 7b 01                lea    0x1(%rbx),%edi
  1d:   48 89 e6                mov    %rsp,%rsi
  20:   e8 00 00 00 00          callq  25 <unroll+0x25>
  25:   8d 7b 02                lea    0x2(%rbx),%edi
  28:   48 89 e6                mov    %rsp,%rsi
  2b:   e8 00 00 00 00          callq  30 <unroll+0x30>
  30:   8d 7b 03                lea    0x3(%rbx),%edi
  33:   48 89 e6                mov    %rsp,%rsi
  36:   e8 00 00 00 00          callq  3b <unroll+0x3b>
  3b:   8d 7b 04                lea    0x4(%rbx),%edi
  3e:   48 89 e6                mov    %rsp,%rsi
  41:   e8 00 00 00 00          callq  46 <unroll+0x46>
  46:   8d 7b 05                lea    0x5(%rbx),%edi
  49:   48 89 e6                mov    %rsp,%rsi
  4c:   e8 00 00 00 00          callq  51 <unroll+0x51>
  51:   8d 7b 06                lea    0x6(%rbx),%edi
  54:   48 89 e6                mov    %rsp,%rsi
  57:   e8 00 00 00 00          callq  5c <unroll+0x5c>
  5c:   8d 7b 07                lea    0x7(%rbx),%edi
  5f:   48 89 e6                mov    %rsp,%rsi
  62:   83 c3 08                add    $0x8,%ebx
  65:   e8 00 00 00 00          callq  6a <unroll+0x6a>
  6a:   81 fb e8 03 00 00       cmp    $0x3e8,%ebx
  70:   75 9e                   jne    10 <unroll+0x10>
  72:   48 81 c4 a0 0f 00 00    add    $0xfa0,%rsp
  79:   31 c0                   xor    %eax,%eax
  7b:   5b                      pop    %rbx
  7c:   c3                      retq   

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-18
    • 2018-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多