13

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 は効率の低い制約を選択するのでしょうか?

次に、あまり広く使用されていないコンマ区切りの複数の代替制約構文があります。
"r,m" (y)これ、各代替のコストを評価し、コピーが少なくなるものを選択する必要があります。これは機能しているように見えますが、clang は単に最初のものを選択するだけです"m,r" (y)


単純に代替制約を削除することもできます"m"が、これは有効なオペランドの範囲を表していません。これは 2 番目の質問につながります:これらの問題は解決されたか、少なくとも 3.3 で認識されましたか? LLVM dev アーカイブを調べてみましたが、不必要に制約をさらに制限したり、プロジェクトの議論に参加したりする前に、いくつかの回答を求めたいと思います。

4

1 に答える 1

12

開発者の 1 人からcfe-dev (clang フロント エンド開発者のリスト)に関する応答がありました。

LLVM は現在、バックエンドでのインライン asm の処理を​​簡素化するために、常に "rm" 制約をスピルします (詳細が必要な場合は llvmdev で尋ねることができます)。近い将来にこれを修正する計画については知りません。

したがって、これは明らかに「既知」の問題です。clang の目標の 1 つは、他の拡張機能の中でも gcc のインライン アセンブリ構文を正しく処理することです。要するに、これ自体はバグではありません。


"r,m"これはバグではないので、制約構文を続けます。今のところこれが最善の妥協点だと思います。gcc最適なもの (可能な場合はおそらくレジスター)clangを選択し、カンマの後のオプションを無視してレジスターの使用を強制します。たとえそれが無視されたとしても、アセンブリ ステートメントのセマンティックな意図、つまり可能な制約の記述は保持されます。


最後の注意 (20130715) :この特定の例は"r,m"、単一の位置で制約を使用してコンパイルされません。たとえば、それぞれに代替の制約の一致を提供する必要があります。

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

これは、GCC を使用した複数の代替制約に必要です。しかし、GCC が過去にバグを示すことが知られていた領域に入りつつあります。これが4.8.1の時点で正しいかどうかはわかりません。Clangは、GCC 構文と互換性のない他の制約の代替手段がなくても機能するため、バグと見なす必要があります。

パフォーマンスが重要な場合は を使用し"r"、それ以外の場合はそのまま使用し"rm"てください。GCC にメリットがあるとしても、将来的には clang がこれに対処するでしょう。

于 2013-06-06T05:17:22.440 に答える