Assembly 为什么bool=bool的代码生成有差异?int:int
此代码Assembly 为什么bool=bool的代码生成有差异?int:int,assembly,x86,x86-64,compiler-optimization,Assembly,X86,X86 64,Compiler Optimization,此代码 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 。。国际刑事法院第17号 test edi,
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
。。国际刑事法院第17号
test edi, edi
cmovne edx, esi
mov eax, 1
test edx, edx
cmove eax, edx
ret
..对于叮当声3.9
test edi, edi
cmove esi, edx
test esi, esi
setne al
ret
对于一个代码模式,为什么我们会有这些我认为是常见的差异?它们都依赖于条件指令、setne、cmovne、cmove,但gcc也有一个分支,它们都使用不同的指令顺序和参数
编译器中的哪个过程负责生成此代码?是由于寄存器分配方式造成的差异;如何进行一般数据流分析;或者在生成代码时编译器模式是否与此模式匹配
代码和asm清单:使用
test/cmov
策略,将返回类型更改为int
将导致来自所有三个编译器的无分支代码
我猜gcc认为将条件的两边都布尔化太麻烦了,于是决定使用一个分支。也许它没有意识到这是相同的工作,而表达式实际上可以用另一种方式完成(选择正确的输入,然后将其布尔化)
它生成的代码会布尔化b
,然后才测试条件并布尔化a
。因此,当cond
为true时,它实际上同时运行test
/setnz
对
这闻起来像是错过了一个优化错误。(或者是一个优化狂奔bug,它通过将返回类型应用于?:
的两个输入,而不是仅应用于结果,从而击中了自己的脚)
报告为
在修复之前,您可以通过将其分为两个步骤:
bool condSet(int cond, int a, int b) {
int tmp = cond ? a : b; // better asm from gcc this way
return tmp;
}
可能是因为不同的人编写了编译器代码。在形式上,向汇编程序的转换不是强制性的:可执行的C代码只需符合标准即可。所有这些都需要经过编译器优化设置。哪一关?C代码有一个预处理阶段,但编译器是一次性的。安娜·卡列尼娜有许多英文译本,但即使是基本句子,它们也使用不同的单词。你会认为对于一个普通的句子,他们会使用完全相同的词。@RaymondChen,@WeatherVane。抱歉说得这么不准确。我的问题仍然很模糊,因为我希望有人能告诉我如何在编译器中选择条件指令。(安娜·卡列尼娜的比喻很好)。我活该。:-)@RaymondChen它们都以相同的调用约定(即SYS V x64 ABI)为目标,但这并不重要。正如您所说,没有理由相信三个不同的编译器会给出相同的输出:)@PeterCordes。我的观点是,编译器之间的这些差异是由于一个相当特殊的情况造成的。像OP的问题那样,将其一般地外推到“三元运算符”似乎有些牵强;因此需要额外的说明。使用int作为返回类型,确实会生成“相同”的代码。我目前没有gcc bugzilla帐户,我对编译器的理解也是“零碎的”。你能把这个问题归档吗?我保证下次遇到可能的gcc错误时,我会亲自提交一个问题。@dannas:done。我认为gcc bugzilla帐户创建仍然是出于垃圾邮件原因关闭的,因此IDK如果你愿意的话也可以:/创建bugzilla帐户仍然是可能的,这个过程已经变成了手动的,你必须联系监督者。