优化器:优化内联汇编

Optimizer: optimize inline assembly

本文关键字:优化 汇编      更新时间:2023-10-16

我听说过几次编译器不会优化内联汇编,或者内联汇编是一种黑盒。我很怀疑,因为我没有看到任何编译器失败的情况,所以我不在乎。

但是今天我在GCC wiki上发现了一个名为DontUseInlineAsm的页面。它包含了人们之前告诉我的相同问题,但没有详细说明为什么编译器不能理解内联asm,因此不会优化它。那么,有人知道编译器不做这些优化的原因吗?

当然,我把像

这样的特殊情况放在一边

asm volatile("" : : "g"(value) : "memory");
asm volatile("" : : : "memory");

,当我们显式地告诉编译器这段代码有明显的副作用,因此它不应该优化它。

您的问题似乎是基于错误的假设,即编译器首先生成汇编,然后,如果您想要优化输出,那么它读取它生成的汇编,优化它,并将其写回来。如果是这样的话,那么读取和优化内联程序集应该没什么大不了的,对吧?

编译器不会优化您的内联程序集,因为编译器根本不会优化任何程序集。编译器无法在执行优化所需的级别上理解汇编。这不关它的事。

编译器通过对其内部数据结构(解析树、中间语言如p-code等)进行特殊处理来生成优化的机器码,这些数据结构都是而不是汇编。

如果涉及程序集生成步骤,则它是只写步骤,这意味着编译器将为您生成该程序集,但它永远不会尝试读取它。那是装配工的工作。我从来没听说过什么优化汇编器。

因此,可以很安全地假设没有编译器会尝试优化任何人的内联汇编。

我不知道你是怎么想的,但坦率地说,如果编译器试图修改我的内联程序集,我会非常恼火。如果我要使用汇编程序,我会这样做,因为我知道(或者我认为我知道)比编译器更好。

编译器不优化内联汇编,因为这会破坏目的。当程序员觉得他们比编译器知道得更好时,或者程序员认为他们可以生成更好的代码,或者编译器不能生成他们想要的代码时,就使用内联汇编。在前一种情况下,程序员自己优化汇编代码,如果编译器在优化等效的C代码方面做得不够好,那么它就不太可能改进汇编代码。在后面的情况下,没有等效的C代码,内联程序集使用编译器无法生成的指令或其他程序集特性。在这种情况下,它也不太可能理解这些指令为了优化代码实际上做了什么。

没有编译器能够像你在评论中建议的那样将内联汇编转换为其内部的"字节码"。GCC将内联汇编作为字符串粘贴到它的汇编输出中。它完全不理解字符串中的代码。Clang通常不生成汇编作为输出,所以它有一个内置汇编器,但它也不真正理解汇编代码。它只是将其翻译成机器码,并将机器码插入到目标文件输出中。微软的编译器是另一种通常不生成汇编代码输出的编译器,它实际上理解汇编,但只是在有限的程度上。它只理解代码使用的寄存器之类的事情,所以编译器会做保留内联程序集使用的寄存器之类的事情。它不知道汇编代码实际做什么。

如果你想让编译器优化你的代码,不要使用内联汇编。即使没有直接对应于你想要的汇编代码的语言特性,那么编译器也可以生成它,就像Mike Nakis在关于ROTL的评论中建议的那样。您还可以使用扩展语言并对应于各种汇编指令的内在函数,编译器在许多情况下能够对其进行优化。