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 アーカイブを調べてみましたが、不必要に制約をさらに制限したり、プロジェクトの議論に参加したりする前に、いくつかの回答を求めたいと思います。