clang(LLVM)内联汇编 - 无限溢出/重载的多个约束

时间:2013-05-31 05:25:06

标签: gcc assembly clang x86-64 inline-assembly

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会在这种情况下选择效率较低的约束?

其次,使用较少,逗号分隔的multiple alternative constraint语法:
"r,m" (y),其中应该评估每种替代方案的成本,并选择导致较少复制的方法。这似乎有用,但是clang只是选择第一个 - 如下所示:"m,r" (y)


我可以简单地删除"m"替代约束,但这并不表示可能合法操作数的范围。这让我想到第二个问题:这些问题是否已在3.3中得到解决或至少得到承认?我已经尝试过查看LLVM开发档案,但我宁愿在不必要地限制约束之前征求一些答案,或加入项目讨论等。

1 个答案:

答案 0 :(得分:9)

我对其中一位开发者的cfe-dev(clang前端开发人员名单)做了回复:

  

LLVM目前总是溢出“rm”约束以简化   在后端处理内联asm(如果需要,可以在llvmdev上询问   细节)。我不知道有什么计划在不久的将来解决这个问题。

所以这显然是一个“已知”的问题。 clang的目标之一是正确处理gcc的内联汇编语法,以及其他扩展,在这种情况下它也是如此 - 只是效率不高。简而言之,这本身并不是一个错误。


由于这不是错误,我将继续使用"r,m"约束语法。我认为这是目前最好的妥协方案。 gcc将选择最好的 - 可能是可能的寄存器 - clang将通过忽略逗号后面的其他选项来强制使用寄存器。如果没有别的,它仍然保留汇编语句的语义意图,即描述可能的约束,即使它们被忽略。


<强>最后需要说明的(20130715)::此特定示例不会编译使用"r,m"约束在一个单一的位置 - 我们将不得不提供一个替代的约束匹配的每个,例如,

: "=a,a" (rl), "=d,d" (rh) : "%0,0" (x), "r,m" (y)

对于GCC的多个替代约束,这是必需的。但是我们进入的领域过去已经知道海湾合作委员会会出现虫子 - 不管是否属于 4.8.1 ,我不知道。 Clang在没有的情况下使用其他约束中的替代项,这与GCC语法不兼容,因此必须被视为错误。

如果性能至关重要,请使用"r",否则,坚持使用"rm",并且可能会在将来解决此问题,即使它有利于GCC。