GCCがpure
関数の最適化について保証していることに混乱しています(オンラインドキュメントから):
pure
多くの関数は、戻り値を除いて効果がなく、その戻り値はパラメーターやグローバル変数のみに依存します。(...)
興味深い非純粋関数は、無限ループを持つ関数、または揮発性メモリやその他のシステムリソースに依存する関数であり、2つの連続する呼び出し間で変更される可能性があります(
feof
マルチスレッド環境など)。
そしてのためにconst
:
const
多くの関数は、引数以外の値を調べず、戻り値以外の効果はありません。基本的に、これは、関数がグローバルメモリを読み取ることを許可されていないため、以下の純粋な属性よりもわずかに厳密なクラスです。
ポインタ引数を持ち、ポイントされたデータを検査する関数は宣言してはならないことに注意してください
const
。同様に、非const関数を呼び出す関数は、通常constであってはなりません。
そこで、ポインタパラメータを受け入れる関数を作成して、マークを付けてみましたpure
。しかし、私はオンラインGCCを使用してこの機能をコンパイルしようとした(私は両方を試してみましたconst
とpure
):
typedef struct
{
int32_t start;
int32_t end;
}
Buffer;
inline __attribute__((pure,always_inline)) int32_t getLen(Buffer * b)
{
return b->end - b->start;
}
そして、GCC(少なくとも私が試したいくつかのオンラインコンパイラバージョン)に気づきました:
Buffer*
パラメーターがグローバル値を指している場合、この関数の呼び出しは最適化されません(つまり、複数回呼び出されます)。const
代わりに関数をマークしても、どちらの場合も同じように機能しますが、ポインタ引数がある場合はpure
おそらくconst
無視されますか?これは良いことです。グローバルBuffer
はいつでも別のスレッド/割り込みによって変更される可能性がありますが、ローカルBuffer
は最適化に対して完全に安全です。
しかし、私はポインタの受け渡しに関する発言に完全に混乱しています。pure
ポインタ引数を受け入れる関数に対してGCCの動作が明示的に定義されている場所はありますか?
ポインタ引数を受け入れる純粋関数に対してGCCの動作が明示的に定義されている場所はありますか?
動作は、ポインター引数をとらない純粋関数と同じです。プログラム内の任意のメモリを読み取ることはできますが、メモリに書き込んだりIOを実行したりすることはできません。
pure関数とconst関数をインラインとして記述することで、物事を大幅に混乱させました。関数本体が呼び出しサイトでコンパイラーに使用可能である場合、呼び出された関数が実行する操作をそれ自体で計算できます。pure属性とconst属性は、別のコンパイルユニットで定義されるため、関数本体が表示されない場合に最も役立ちます。
たとえば、次の非純粋、純粋、およびconst関数のコレクションについて考えてみます。
__attribute__((__pure__)) int a();
__attribute__((__const__)) int b();
void c();
私たちが呼び出した場合a
何も操作が介在しないで、2回連続しているので、我々は、単一の呼び出しにそれを折りたたむことができa
だけで、それを読むためにアクセスグローバルメモリに保証されています。別のスレッドがほぼ同時にグローバルメモリに書き込む場合でも、a
そのスレッドと通信する方法がないため、コンパイラは、次の両方の呼び出しの前または後に書き込みが行われると想定できますa
。
int f() {
int i = a();
i += a();
return i; // optimized to "return a() * 2;"
}
の呼び出しのc
間に呼び出す場合a
、の戻り値は次a
の呼び出しの影響を受ける可能性があると想定する必要がありますc
。
int g() {
int i = a();
c();
i += a();
return i; // no optimization possible
}
ただし、純粋なa
constの代わりに、constを呼び出す場合は、次のように書き込む可能性のあるメモリを読み取ることができないb
ため、これを1回の呼び出しにまとめるb
ことができますc
。
int h() {
int i = b();
c();
i += b();
return i; // optimized to "c(); return b() * 2;"
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加