1. ホーム
  2. c

[解決済み] asm、asm volatile、clobbering memoryの違いについて

2022-03-11 04:55:29

質問

ロックフリーのデータ構造とタイミングコードを実装する場合、コンパイラの最適化を抑制する必要があることがよくあります。通常、これを行うには asm volatilememory を使うことができますが、たまに asm volatile または単なる asm クラビングメモリー

これらの異なる記述は、コード生成にどのような影響を与えますか(特にGCCでは移植性が低いので)?

参考までに、面白いバリエーションを挙げておきます。

asm ("");   // presumably this has no effect on code generation
asm volatile ("");
asm ("" ::: "memory");
asm volatile ("" ::: "memory");

解決方法は?

をご覧ください。 GCC ドキュメントの "Extended Asm" のページです。 .

<ブロッククオート

を防ぐことができます。 asm というキーワードを記述することで、命令が削除されるのを防ぐことができます。 volatile の後に asm . [...] volatile キーワードは、その命令が重要な副作用を持つことを示します。GCCは volatile asmに到達可能である場合。

そして

An asm 出力オペランドを持たない命令は、揮発性の asm 命令です。

どの例も出力オペランドが指定されていないので asmasm volatile の動作は同じです。コード内にポイントを作成し、(到達不可能であることが証明されない限り)削除することはできません。

これは、何もしないことと全く同じではありません。 参照 この質問 の例として、ダミーの asm この例では、ループを1000回繰り返すコードが、ループの16回の繰り返しを一度に計算するコードにベクトル化されます。 asm は最適化を阻害する(ループ内の asm に1000回到達しなければならない)。

は、その "memory" によって任意のメモリが読み書きに使われる可能性があると GCC に思わせます。 asm ブロックの中でロードやストアの順序を変更することを防ぎます。

<ブロッククオート

これにより、GCCは、アセンブラ命令にわたってレジスタにキャッシュされたメモリ値を保持せず、そのメモリへのストアやロードを最適化しないようになります。

(ただし、CPUが他のCPUに対してロードとストアを並べ替えることは防げません。そのためには本物のメモリバリア命令が必要です)。