(高いDWORDは、すべての場合においてゼロであると仮定して)任意のペナルティが存在してもよいですか?
No, writing to a 32-bit register always zero-extends to the full registerであるため、x86-64では、32ビットおよび64ビット命令の部分的なペナルティが回避されます。
したがって、私は32ビットがまだネイティブであると信じています。
はい、ほとんどの命令(other than PUSH/POP)のデフォルトのオペランドサイズは32ビットです。 64ビットにはWビットが1に設定されたREXプレフィックスが必要です。したがって、コードサイズの理由から32ビットを優先します。これは、コンパイラが静的データのアドレスにmov r32, imm32
を使用する理由です(デフォルトのコード・モデルでは、コード・アドレスと静的データ・アドレスが仮想アドレス空間の2GiBの低位にある必要があるためです)。
これはAMDによって設計された選択でした。彼らは他の方法を選ぶことができ、32ビットのオペランドサイズを得るために接頭辞が必要でした。ロングモードは独立したモードなので、x86-64マシンコードはx86-32マシンコードとは異なる場合があります。 AMDはその差異を最小限に抑えて、できるだけ多くのトランジスタをデコーダで共有できるようにしました。あなたの結論は正しいですが、あなたの推論はまったく間違っています。 (代わりに、EAXの斧のような)
部分レジスタの更新EFLAGSストールが発生し、パフォーマンスが低下する可能性があります。
パーシャルフラグストールは、パーシャルレジスタストールとは別です。それらは内部的にも同様に扱われます(EFLAGSの個別に名前が変更された部分は、変更されたAXをEAXの未変更の上位バイトとマージする必要があります)。 しかし、1つは他を引き起こさない。
# partial-reg stall
setcc al # leaves the upper 3 (or 7) bytes unmodified
add edx, eax # reads full EAX. Older CPUs stall while merging
Zeroing EAX ahead of the flag-setting and setcc with xor eax,eax
avoids the partial-register penalty entirely。 (Core2/Nehalemは、以前のCPUよりも少ないサイクルで停止しますが、併合uopを挿入している間は2または3cで停止します。マージアップを挿入している間、Sandybridgeは全く停止しません)。
(別のCPUでの部分的なレジスタペナルティの別の要約:Why doesn't GCC use partial registers?、基本的に同じことを言っています)。
AMDは後でフル・レジスタを読み出すときに部分的なレジスタ・ストールを受けませんが、部分的なレジスタの書き込みと読み出しは完全なレジスタに偽の依存性を持ちます。 (AMD CPUは最初の場所で別々にサブレジスタの名前を変更しないでください。インテルP4とSilvermont /ナイトのランディングは、同じ方法です。)
インテルハスウェル/ Skylakeマイクロアーキテクチャ(そしておそらくIvybridgeの)別にal
の名前を変更しないでくださいrax
はすべてなので、low8/low16レジスタをマージする必要はありません。しかし、setcc al
は、古い値に偽の依存性があります。彼らはまだ名前を変更してah
をマージします。 (Details on HSW/SKL partial-reg performance。)
# partial flag stall when reading a flag that didn't come from
# the last instruction to write any flags.
clc
# edi and esi = one-past-the-end of dst and src
# ecx = -count
bigInt_add:
mov eax, [esi+ecx*4]
adc [edi+ecx*4], eax # reads CF, partial flag stall on 2nd and later iterations
inc ecx # writes all flags except CF
jl bitInt_add # loop upwards towards zero
はSandybridge対インテル事前Sandybridge上の部分のフラグの問題の詳細な議論のためのthis Q&Aを参照してください。
はAgner Fog's microarch pdfも参照してください、とこれのすべての詳細についてはx86タグウィキ内の他のリンク。
16ビットアクセスのペナルティがあります。 32ビットレジスタの使用とr8-r15の回避はOKであり、実際にはコードサイズが小さくなることがあります。 –
32ビットレジスタに書き込むと、自動的に上位32ビットがクリアされるので、部分的な更新の問題は回避されます。 – Jester
EFLAGSレジスタは、最新のプロセッサで大幅に仮想化されています。すべてのレジスタと同様です。必然的に、あまりにも多くの命令がそれを修正し、それはスーパースカラー実行の大きなダンパーです。あなたのコードにないものは、実際に*レジスタを使用する命令です。だから、プロセッサがそれを連動させ、あなたが掲示したコードを停止させる魅力的な理由はありません。どのようにして/うまくいかなければならないかについて誰かの意見を聞かないでください。アセンブリコードを書く唯一のポイントは、Cコンパイラよりも高速にすることです。測定する。 –