2

gcc インライン asm ステートメントに問題があります。gcc は、結果が定数であると考えているようで (そうではありません)、ステートメントを最適化します。オペランド制約を正しく使用していると思いますが、この問題についてセカンド オピニオンをお願いします制約の使用に問題がない場合は、gcc バグ レポートのテスト ケースを分離しようとしますが、周囲のコードのわずかな変更でも問題が消えるため、難しい場合があります。

問題のインラインasmは

static inline void
ularith_div_2ul_ul_ul_r (unsigned long *r, unsigned long a1,
                 const unsigned long a2, const unsigned long b)
{
  ASSERT(a2 < b); /* Or there will be quotient overflow */
  __asm__(
            "# ularith_div_2ul_ul_ul_r: divq %0 %1 %2 %3\n\t"
            "divq %3"
            : "+a" (a1), "=d" (*r)
            : "1" (a2), "rm" (b)
            : "cc");
}

これは、2 語の被除数を 1 語の除数で割った、ありきたりの剰余です。入力の上位ワード a2 と剰余出力 *r は、"1" 制約によって同じレジスタ %rdx に関連付けられていることに注意してください。

周囲のコードから、ularith_div_2ul_ul_ul_r()あたかも

if (s == 1)
  modpp[0].one = 0;
else
  ularith_div_2ul_ul_ul_r(&modpp[0].one, 0UL, 1UL, s);

したがって、入力の上位ワード a2 は定数 1UL です。gcc -S -fverbose_asm の結果の asm 出力は次のようになります。

(earlier:)
        xorl    %r8d, %r8d      # cstore.863
(then:)
        cmpq    $1, -208(%rbp)  #, %sfp
        movl    $1, %eax        #, tmp841
        movq    %rsi, -184(%rbp)        # prephitmp.966, MEM[(struct __modulusredcul_t *)&modpp][0].invm
        cmovne  -208(%rbp), %rcx        # prephitmp.966,, %sfp, prephitmp.966
        cmovne  %rax, %r8       # cstore.863,, tmp841, cstore.863
        movq    %r8, -176(%rbp) # cstore.863, MEM[(struct __modulusredcul_t *)&modpp][0].one

その結果、ularith_div_2ul_ul_ul_r()呼び出しの結果は定数 1 であると見なされます。divq は出力に表示されません。

さまざまな変更により、問題が解消されます。異なるコンパイラ フラグ、異なるコード コンテキスト、または asm ブロックのマーキング__asm__ __volatile__ (...)。出力には divq 命令が正しく含まれています。

#APP
        # ularith_div_2ul_ul_ul_r: divq %rax %rdx %rdx -208(%rbp)       # a1, tmp590, tmp590, %sfp
        divq -208(%rbp) # %sfp
#NO_APP

そこで、ここでインライン アセンブリ担当者に質問します。制約に何か問題がありましたか?

4

1 に答える 1

1

このバグは gcc の Ubuntu バージョンのみに影響します。ストックGNU gccは、私たちが知る限り影響を受けていません。このバグは Ubuntu ランチパッドに報告され、確認されました: Bug #1029454

于 2012-08-01T11:53:36.330 に答える