【问题标题】:Disable named return value optimization in gcc for pure C在 gcc 中为纯 C 禁用命名返回值优化
【发布时间】:2016-01-23 09:44:59
【问题描述】:

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

实现它的源代码是here,但是由于它是一个中端,即使在cmets中也不会破坏前端信息。 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 编译,我们看到“复制”结构天真地分配在堆栈上:

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 

【问题讨论】:

  • 既然您已确定要禁用的通行证:-fdisable-tree-nrv。您的“它必须是以下之一”没有意义。
  • 我们中的一些人当然很好奇什么时候这很有用。
  • 你这样做的目的是什么?
  • 也许您应该向我们展示源代码,以及 O0 和 O1 之间的汇编差异,以便我们知道您要禁用什么。
  • @user3386109 更新

标签: c gcc compiler-optimization nrvo


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多