这个带输入=输出的gcc样式asm是否需要早期的破坏?

时间:2012-06-19 17:06:47

标签: gcc inline-assembly

gcc内联asm早期clobber约束在这里的gcc文档中描述:

http://gcc.gnu.org/onlinedocs/gcc/Modifiers.html#Modifiers

我们有128位add的amd64实现:

#define ADD128(rh, rl, ah, al, bh, bl)                                     \
    __asm__("addq %2, %0; adcq %3, %1"                                     \
            /* outputs */ : "=r"(rl),  /* %0 */                            \
                            "=r"(rh)   /* %1 */                            \
            /* inputs */  : "emr"(bl), /* %2 */                            \
                            "emr"(bh), /* %3 */                            \
                            "0"(al),   /* %4 == %0 */                      \
                            "1"(ah)    /* %5 == %1 */                      \
            /* clobbers */: "cc"       /* condition registers (CF, ...) */ \
           )

我想知道这是否必须使用早期clobber(&)来表示%0:

#define ADD128(rh, rl, ah, al, bh, bl)                                 \
    __asm__("addq %2, %0; adcq %3, %1"                                     \
            /* outputs */ : "=&r"(rl),  /* %0 */                            \
                            "=r"(rh)   /* %1 */                            \
            /* inputs */  : "emr"(bl), /* %2 */                            \
                            "emr"(bh), /* %3 */                            \
                            "0"(al),   /* %4 == %0 */                      \
                            "1"(ah)    /* %5 == %1 */                      \
            /* clobbers */: "cc"       /* condition registers (CF, ...) */ \
           )

但是,我不太确定,因为我们在amd64版本中明确地输入=输出(%0 == %4%1 == %5)?

第一个非早期版本似乎目前适用于我们正在使用的所有优化级别,至少使用intel编译器(如果使用gcc,我们不需要这个,因为gcc现在支持对此目标的本机int128操作)。

为了严格遵守inline asm中早期clobber的gcc规范,我们需要& %0约束,即使使用inputs = outputs语句?

1 个答案:

答案 0 :(得分:1)

如果您使用bhal的完全相同的表达式调用此宏,则需要早期的clobber。在这种情况下,如果没有clobber,编译器可能会选择对%3%4使用相同的寄存器(与%0相同),因此第一条指令可能会破坏那个第二个表达式读取之前的值。

你实际上不太可能以可能触发这个问题的方式调用宏,所以如果没有clobber你没有看到任何问题就不足为奇了。当您调用albl相同的宏时,添加clobber还会引入额外的(不需要的)寄存器副本(例如,在其中添加128位值),因此稍微不合需要。