1

gcc でアセンブリをインライン化するとき、前のブロックで変数を有効にしておくために、定期的に空の asm ブロックを追加する必要があることに気付きます。たとえば、次のようになります。

asm("rcr $1,%[borrow];"
    "movq 0(%[b_],%[i],8),%%rax;"
    "adcq %%rax,0(%[r_top],%[i],8);"
    "rcl $1,%[borrow];"
    : [borrow]"+r"(borrow)
    : [i]"r"(i),[b_]"r"(b_.data),[r_top]"r"(r_top.data)
    : "%rax","%rdx");

asm("" : : "r"(borrow) : ); // work-around to keep borrow alive ...

奇妙さのもう 1 つの例は、以下のコードが最適化なしで問題なく動作することですが、-O3 を使用するとセグ フォールトが発生します。

ulong carry = 0,hi = 0,qh = s.data[1],ql = s.data[0];
asm("movq 0(%[b]),%%rax;"
    "mulq %[ql];"
    "movq %%rax,0(%[sb]);"
    "movq %%rdx,%[hi];"
    : [hi]"=r"(hi)
    : [ql]"r"(ql),[b]"r"(b.data),[sb]"r"(sb.data)
    : "%rax","%rdx","memory");
for (long i = 1; i < b.size; i++)
{
    asm("movq 0(%[b],%[i],8),%%rax;"
        "mulq %[ql];"
        "xorq %%r10,%%r10;"
        "addq %%rax,%[hi];"
        "adcq %%rdx,%[carry];"
        "adcq $0,%%r10;"
        "movq -8(%[b],%[i],8),%%rax;"
        "mulq %[qh];"
        "addq %%rax,%[hi];"
        "adcq %%rdx,%[carry];"
        "adcq $0,%%r10;"
        "movq %[hi],0(%[sb],%[i],8);"
        "movq %[carry],%[hi];"
        "movq %%r10,%[carry];"
        : [carry]"+r"(carry),[hi]"+r"(hi)
        : [i]"r"(i),[ql]"r"(ql),[qh]"r"(qh),[b]"r"(b.data),[sb]"r"(sb.data)
        : "%rax","%rdx","%r10","memory");
}
asm("movq -8(%[b],%[i],8),%%rax;"
    "mulq %[qh];"
    "addq %%rax,%[hi];"
    "adcq %%rdx,%[carry];"
    "movq %[hi],0(%[sb],%[i],8);"
    "movq %[carry],8(%[sb],%[i],8);"
    : [hi]"+r"(hi),[carry]"+r"(carry)
    : [i]"r"(long(b.size)),[qh]"r"(qh),[b]"r"(b.data),[sb]"r"(sb.data)
    : "%rax","%rdx","memory");

非常に多くのレジスタを使用しているという事実に関係していると思います。ここに欠けているものはありますか、それとも gcc インライン アセンブリでレジスタ割り当てに本当にバグがありますか?

4

1 に答える 1

2

あなたが見逃しているのは、GCCのオプティマイザーが、asmブロックの唯一の副作用が出力オペランドの変更であると想定することです。これらのオペランドがその後使用されない場合、asmブロックは不要であると見なされ、削除できる可能性があります。

たとえば、最初の例でborrowは、その後使用されない場合、ブロックを含める意味がまったくないと自由に想定できます。これはasm、その唯一の副作用は、二度と使用されない変数を更新することだからです。そして 2 番目の例では、あなたが示したコードの後にhi​​ とが再び使用されない場合、おそらくほとんどすべてを削除できると推測されます!carry

インライン アセンブリ ブロックを削除しないように GCC に指示するasm volatile(...)には、asm(...).

この詳細については、 http: //gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html (ページの半分くらい) を参照してください。

于 2011-02-20T13:22:21.367 に答える