对于纯C,禁用gcc中的命名返回值优化

时间:2016-01-23 09:45:00

标签: c gcc compiler-optimization nrvo

我找不到控制C语言的命名返回值优化的标志。对于C ++,它似乎是-fno-elide-constructors。

实现它的源代码是here,但由于它是一个中端,即使在评论中也没有破坏前端信息。 The manual section也没有完全帮助。但是,反汇编表明,当它在O0上关闭并在O1上启用时,它必须是以下之一:

      -fauto-inc-dec 
      -fcprop-registers 
      -fdce 
      -fdefer-pop 
      -fdelayed-branch 
      -fdse 
      -fguess-branch-probability 
      -fif-conversion2 
      -fif-conversion 
      -finline-small-functions 
      -fipa-pure-const 
      -fipa-reference 
      -fmerge-constants
      -fsplit-wide-types 
      -ftree-builtin-call-dce 
      -ftree-ccp 
      -ftree-ch 
      -ftree-copyrename 
      -ftree-dce 
      -ftree-dominator-opts 
      -ftree-dse 
      -ftree-fre 
      -ftree-sra 
      -ftree-ter 
      -funit-at-a-time

C代码:

struct p {
    long x;
    long y;
    long z;
};

__attribute__((noinline))
struct p f(void) {
    struct p copy;
    copy.x = 1; 
    copy.y = 2;
    copy.z = 3;
    return copy;
}

int main(int argc, char** argv) {
    volatile struct p inst = f();
    return 0;
}

使用O0编译,我们看到'copy'结构在堆栈上被天真地分配:

00000000004004b6 <f>:
  4004b6:   55                      push   rbp
  4004b7:   48 89 e5                mov    rbp,rsp
  4004ba:   48 89 7d d8             mov    QWORD PTR [rbp-0x28],rdi
  4004be:   48 c7 45 e0 01 00 00    mov    QWORD PTR [rbp-0x20],0x1
  4004c5:   00 
  4004c6:   48 c7 45 e8 02 00 00    mov    QWORD PTR [rbp-0x18],0x2
  4004cd:   00 
  4004ce:   48 c7 45 f0 03 00 00    mov    QWORD PTR [rbp-0x10],0x3
  4004d5:   00 
  4004d6:   48 8b 45 d8             mov    rax,QWORD PTR [rbp-0x28]
  4004da:   48 8b 55 e0             mov    rdx,QWORD PTR [rbp-0x20]
  4004de:   48 89 10                mov    QWORD PTR [rax],rdx
  4004e1:   48 8b 55 e8             mov    rdx,QWORD PTR [rbp-0x18]
  4004e5:   48 89 50 08             mov    QWORD PTR [rax+0x8],rdx
  4004e9:   48 8b 55 f0             mov    rdx,QWORD PTR [rbp-0x10]
  4004ed:   48 89 50 10             mov    QWORD PTR [rax+0x10],rdx
  4004f1:   48 8b 45 d8             mov    rax,QWORD PTR [rbp-0x28]
  4004f5:   5d                      pop    rbp
  4004f6:   c3                      ret    

使用O1编译时未分配,但指针作为隐式参数传递

00000000004004b6 <f>:
  4004b6:   48 89 f8                mov    rax,rdi
  4004b9:   48 c7 07 01 00 00 00    mov    QWORD PTR [rdi],0x1
  4004c0:   48 c7 47 08 02 00 00    mov    QWORD PTR [rdi+0x8],0x2
  4004c7:   00 
  4004c8:   48 c7 47 10 03 00 00    mov    QWORD PTR [rdi+0x10],0x3
  4004cf:   00 
  4004d0:   c3                      ret 

1 个答案:

答案 0 :(得分:2)

与GCC最接近的事情(即复制省略的开关)是-fcprop-registers。 C中不存在复制省略,但这是最相似的功能。从手册页:

  

寄存器分配和寄存器后分配指令后   分裂,我们执行复制传播传递以尝试减少   调度依赖关系并偶尔消除副本。        启用级别-O,-O2,-O3,-Os。