【发布时间】:2017-05-10 11:39:14
【问题描述】:
这段代码...
bool condSet(int cond, int a, int b) {
return cond ? a : b;
}
..为 gcc 6.3 生成...
test edx, edx
setne al
test edi, edi
jne .L6
rep ret
.L6:
test esi, esi
setne al
ret
.. 对于 icc 17...
test edi, edi
cmovne edx, esi
mov eax, 1
test edx, edx
cmove eax, edx
ret
..对于clang 3.9
test edi, edi
cmove esi, edx
test esi, esi
setne al
ret
为什么我们有这些差异,对于我希望常见的代码模式?它们都依赖条件指令,setne、cmovne、cmove,但gcc也有分支,它们都使用不同的指令和参数顺序。
编译器中的哪个通道负责此代码生成?差异是由于寄存器分配的完成方式吗?如何进行一般数据流分析;或者编译器模式在生成代码时是否与此模式匹配?
代码和 asm 列表:https://godbolt.org/g/7heVGz
【问题讨论】:
-
可能是因为不同的人编写了编译器代码。形式上不强制转换为汇编器:可执行的 C 代码只需要符合标准即可。所有这些都受编译器优化设置的影响。哪个通行证? C 代码有预处理器阶段,但编译器是一次性的。
-
《安娜卡列尼娜》有很多英文翻译,但即使是基本句子,它们也使用不同的词。你会认为对于一个常见的句子,他们会使用完全相同的词。
-
@RaymondChen,@WeatherVane。抱歉这么不精确。而且我的问题仍然含糊不清,因为我希望有人能启发我了解如何在编译器中选择条件指令。 (安娜卡列尼娜的比喻很棒)。我应得的。 :-)
-
@RaymondChen 他们确实都针对相同的调用约定(即 SYS V x64 ABI),但这无关紧要。正如你所说,没有理由相信三个不同的编译器给出相同的输出:)
-
@PeterCordes 确实如此。我的观点是编译器之间的这些差异是由于一个相当具体的情况。正如 OP 的问题一样,将其一般地推断为“三元运算符”似乎有些牵强。
标签: assembly x86 x86-64 compiler-optimization