编译器可以优化这段代码吗?

时间:2014-08-09 12:32:10

标签: optimization compiler-construction

考虑以下代码片段:

for(i = 0; i<10; i++)
{
    int n = a[i];//first loop statement

    //other statements
}

显然,编译器不会将第一个语句提升出循环。但编译器是否只能在循环上方提升n的声明?换句话说,编译器也可以优化上面的代码:

int n;

for(i = 0; i < 10; i++)
{
    n = a[i];//first loop statement
}

1 个答案:

答案 0 :(得分:3)

实际上,大多数编译器甚至会在-O0

执行此操作
~ $ cat t.c
volatile int v;

int a[10];

void f(void)
{
  int n;
  int i;
  for(i = 0; i < 10; i++) {

    n = a[i];
    v = n;
  }
}
~ $ clang -S -O0 t.c
~ $ cat t.s
…
_f:                                     ## @f
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp4:
    .cfi_def_cfa_register %rbp
    movl    $0, -8(%rbp)
LBB0_1:                                 ## =>This Inner Loop Header: Depth=1
    cmpl    $10, -8(%rbp)
    jge LBB0_4
## BB#2:                                ##   in Loop: Header=BB0_1 Depth=1
    movq    _v@GOTPCREL(%rip), %rax
    movq    _a@GOTPCREL(%rip), %rcx
    movslq  -8(%rbp), %rdx
    movl    (%rcx,%rdx,4), %esi
    movl    %esi, -4(%rbp)
    movl    -4(%rbp), %esi
    movl    %esi, (%rax)
## BB#3:                                ##   in Loop: Header=BB0_1 Depth=1
    movl    -8(%rbp), %eax
    addl    $1, %eax
    movl    %eax, -8(%rbp)
    jmp LBB0_1
LBB0_4:
    popq    %rbp
    ret
…
~ $ 

请注意,上面的循环体内没有指令来保留n。相反,无缝重用相同的堆栈槽-4(%rbp)。如果我使用最轻微的优化级别进行编译,那么n甚至不会成为堆栈槽:一个寄存器足以在短时间内保持其值:

~ $ clang -S -O1 t.c
~ $ cat t.s
…
_f:                                     ## @f
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp4:
    .cfi_def_cfa_register %rbp
    xorl    %eax, %eax
    movq    _a@GOTPCREL(%rip), %rcx
    movq    _v@GOTPCREL(%rip), %rdx
    .align  4, 0x90
LBB0_1:                                 ## =>This Inner Loop Header: Depth=1
    movl    (%rcx,%rax,4), %esi
    movl    %esi, (%rdx)
    incq    %rax
    cmpq    $10, %rax
    jne LBB0_1
## BB#2:
    popq    %rbp
    ret

在这个新的编译版本中,%esin


即使在最低级别的优化中,编译器实现“在循环外提升变量声明”优化的方式是将所有块范围自动变量的声明提升到函数范围。绝对没有任何意义。在没有对目标语言的最小理解的情况下,对编译器优化的讨论也没有多大意义,其中变量声明不需要导致任何代码。