【问题标题】:Do empty body functions get optimized by clang?空体功能会被clang优化吗?
【发布时间】:2017-07-14 17:09:32
【问题描述】:

类似这样的:

static void MyFunction(int x, int y) {};

Clang 会在调用时优化它们吗?

【问题讨论】:

  • 为什么不写一个简单的例子自己去看看呢?这是最好的学习方式。 ;-)

标签: function optimization clang compiler-optimization


【解决方案1】:

这取决于优化级别。如果您没有优化,那么you'll probably still end up with a function。但是,即使使用 -O you'll see it disappear。如果您的函数没有标记为static,它会有点复杂,因为该函数需要存在于其他翻译单元,所以您可能会see an empty body,并且对它的调用在同一个TU中省略,但函数本身必须仍然存在。

【讨论】:

  • 而且,就其价值而言,如果您提到的 empty body 没有在其他 TU 中实际使用,则链接器应将其删除。
【解决方案2】:

当然,只要定义对调用站点的编译器可见。既然你已经声明了它static,那可能永远都是真的。

【讨论】:

    【解决方案3】:

    当然是 -O3(实际上是任何!= 0)

    【讨论】:

      【解决方案4】:

      给定代码:

      /* Optmizing empty functions */
      
        static void myFunc(int x, int y); 
      
        int main(void)
        {
            int x=1, y=2;
      
            myFunc(x, y); 
      
            return 0;
        }
      
      static void myFunc(int x, int y)
      {
            ;   
      }
      

      每个优化级别生成的程序集如下所示:

      GCC - 优化级别 0 与 -g(调试)

      • gcc emptyfunc.c -g -O0 -o emptyfunc.x

        Dump of assembler code for function main:
           0x0000000000000660 <+0>:     push   %rbp
           0x0000000000000661 <+1>:     mov    %rsp,%rbp
           0x0000000000000664 <+4>:     sub    $0x10,%rsp
           0x0000000000000668 <+8>:     movl   $0x1,-0x4(%rbp)
           0x000000000000066f <+15>:    movl   $0x2,-0x8(%rbp)
           0x0000000000000676 <+22>:    mov    -0x8(%rbp),%edx
           0x0000000000000679 <+25>:    mov    -0x4(%rbp),%eax
           0x000000000000067c <+28>:    mov    %edx,%esi
           0x000000000000067e <+30>:    mov    %eax,%edi
           0x0000000000000680 <+32>:    callq  0x68c <myFunc>
           0x0000000000000685 <+37>:    mov    $0x0,%eax
           0x000000000000068a <+42>:    leaveq
           0x000000000000068b <+43>:    retq
        End of assembler dump.
        

      GCC - 优化级别 1

      • gcc emptyfunc.c -O1 -o emptyfunc-gccO1.x

        Dump of assembler code for function main:
           0x0000000000000660 <+0>:     mov    $0x0,%eax
           0x0000000000000665 <+5>:     retq
        End of assembler dump.
        

      GCC - 优化级别 2、3、Os(大小)、Og(调试)和 Ofast

      • gcc emptyfunc.c -O2 -o emptyfunc-gccO2.x
      • gcc emptyfunc.c -O3 -o emptyfunc-gccO3.x
      • gcc emptyfunc.c -Os -o emptyfunc-gccOs.x
      • gcc emptyfunc.c -Og -o emptyfunc-gccOg.x
      • gcc emptyfunc.c -Ofast -o emptyfunc-gccOfast.x

        Dump of assembler code for function main:
           0x0000000000000530 <+0>:     xor    %eax,%eax
           0x0000000000000532 <+2>:     retq
        End of assembler dump.
        

      Clang - 优化级别 0 与 -g(调试)

      • clang emptyfunc.c -o emptyfunc-clangO0.x -g -O0

        Dump of assembler code for function main:
           0x00000000004004c0 <+0>:     push   %rbp
           0x00000000004004c1 <+1>:     mov    %rsp,%rbp
           0x00000000004004c4 <+4>:     sub    $0x10,%rsp
           0x00000000004004c8 <+8>:     movl   $0x0,-0x4(%rbp)
           0x00000000004004cf <+15>:    movl   $0x1,-0x8(%rbp)
           0x00000000004004d6 <+22>:    movl   $0x2,-0xc(%rbp)
           0x00000000004004dd <+29>:    mov    -0x8(%rbp),%edi
           0x00000000004004e0 <+32>:    mov    -0xc(%rbp),%esi
           0x00000000004004e3 <+35>:    callq  0x4004f0 <myFunc>
           0x00000000004004e8 <+40>:    xor    %eax,%eax
           0x00000000004004ea <+42>:    add    $0x10,%rsp
           0x00000000004004ee <+46>:    pop    %rbp
           0x00000000004004ef <+47>:    retq
        End of assembler dump.
        

      Clang - 优化级别 1、2、3、Os(大小)、Ofast、Oz(大小 II)

      • clang emptyfunc.c -o emptyfunc-clangO1.x -O1
      • clang emptyfunc.c -o emptyfunc-clangO2.x -O2
      • clang emptyfunc.c -o emptyfunc-clangO3.x -O3
      • clang emptyfunc.c -o emptyfunc-clangOs.x -Os
      • clang emptyfunc.c -o emptyfunc-clangOfast.x -Ofast
      • clang emptyfunc.c -o emptyfunc-clangOz.x -Oz

        Dump of assembler code for function main:
           0x00000000004004c0 <+0>:     xor    %eax,%eax
           0x00000000004004c2 <+2>:     retq
        End of assembler dump.
        

      如您所见,是的,它当然会删除空函数。

      【讨论】:

      • 您的代码格式无效。当代码块是项目符号列表的一部分时,它们需要缩进 8 个空格。 (这比正常的 4 个缩进空格多 4 个。)
      • 谢谢。这真的不是我的错。我没有使用任何缩进,因为我使用``` 来标记该块。无论在哪里,它都应该工作。但无论如何,因为它似乎是一个错误,我已经删除了 3 个折痕符号并在所有行中添加了缩进。做起来很痛苦,而不是仅仅打开```粘贴代码并用```关闭
      • ``` 不是一个东西。它不用于标记块。您使用反引号的唯一地方是获取内联代码格式;这在开头使用一个反引号,在文本字符串的末尾使用另一个反引号。对于 block 代码格式,总是需要缩进。每行前面通常有 4 个空格,除了在有序/无序列表内部,所需空格的数量加倍为 8。(制表符也可以,其中 1 个制表符等于 4 个空格,但每个人都知道空格更好比标签。:-)
      猜你喜欢
      • 2016-04-26
      • 2011-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多