clang / gcc:一些内联汇编操作数可以满足多个约束条件,例如,"rm"
当操作数可以满足寄存器或内存位置时。例如,64 x 64 = 128 位乘法:
__asm__ ("mulq %q3" : "=a" (rl), "=d" (rh) : "%0" (x), "rm" (y) : "cc")
生成的代码似乎为参数选择了一个内存约束3
,如果我们被寄存器饿死,这会很好,以避免溢出。显然,x86-64 上的注册压力比 IA32 上要小。但是,生成的程序集片段(由clang)是:
movq %rcx, -8(%rbp)
## InlineAsm Start
mulq -8(%rbp)
## InlineAsm End
选择内存约束显然是没有意义的!将约束更改为: "r" (y)
,但是(强制注册)我们得到:
## InlineAsm Start
mulq %rcx
## InlineAsm End
正如预期的那样。这些结果适用于 clang / LLVM 3.2(当前 Xcode 版本)。第一个问题:在这种情况下,clang 为什么会选择效率较低的约束?
其次,使用不太广泛的、逗号分隔的多个替代约束语法:
"r,m" (y)
,它应该评估每个替代方案的成本,并选择导致较少复制的那个。这似乎可行,但 clang 只是选择了第一个- 如下所示:"m,r" (y)
我可以简单地放弃"m"
替代约束,但这并不表示可能的合法操作数的范围。这就引出了第二个问题:这些问题在 3.3 中是否已经解决或至少得到了承认?我试过浏览 LLVM 开发档案,但我宁愿在不必要地进一步限制约束或加入项目讨论等之前征求一些答案。