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语句?
答案 0 :(得分:1)
如果您使用bh
和al
的完全相同的表达式调用此宏,则需要早期的clobber。在这种情况下,如果没有clobber,编译器可能会选择对%3
和%4
使用相同的寄存器(与%0
相同),因此第一条指令可能会破坏那个第二个表达式读取之前的值。
你实际上不太可能以可能触发这个问题的方式调用宏,所以如果没有clobber你没有看到任何问题就不足为奇了。当您调用al
与bl
相同的宏时,添加clobber还会引入额外的(不需要的)寄存器副本(例如,在其中添加128位值),因此稍微不合需要。