[解決済み] なぜC++コンパイラはこの条件付きブール代入を無条件代入として最適化しないのでしょうか?
疑問点
次のような関数を考えてみましょう。
void func(bool& flag)
{
if(!flag) flag=true;
}
flag が有効なブール値を持っている場合、これは無条件にそれを
true
に設定するのと同じです。
void func(bool& flag)
{
flag=true;
}
しかし、gccもclangもこのように最適化せず、以下のように
-O3
最適化レベルでは以下のようになります。
_Z4funcRb:
.LFB0:
.cfi_startproc
cmp BYTE PTR [rdi], 0
jne .L1
mov BYTE PTR [rdi], 1
.L1:
rep ret
私の質問は、コードが特殊すぎて最適化する気になれないだけなのか、それとも、以下のように、最適化が望ましくない正当な理由があるのか、ということです。
flag
への参照ではなく
volatile
? 唯一の理由は
flag
が何らかの形で非
true
-または
false
の値を読み込む時点で未定義の動作にならないようにする必要がありますが、これが可能かどうかはわかりません。
どのように解決するのですか?
により、プログラムのパフォーマンスに悪影響を与える可能性があります。
キャッシュコヒーレンス
を考慮する必要があります。に書き込むと
flag
その都度
func()
が呼び出されるたびに、そのキャッシュラインを汚してしまいます。これは、書き込まれた値が、書き込む前に宛先アドレスで見つかったビットと正確に一致するかどうかに関係なく起こります。
EDIT
hvd は、別の 良い理由 を提示しました。それは提案された最適化に対してより説得力のある議論です。なぜなら、私の (元の) 回答がパフォーマンスの側面のみを扱ったのに対し、未定義の動作になる可能性があるからです。
もう少し考えた後、なぜコンパイラーは、変換が特定のコンテキストにとって安全であることを証明できない限り、無条件の書き込みを導入することを強く禁止されるべきなのか、もう 1 つの例を提案することができます。このコードを考えてみてください。
const bool foo = true;
int main()
{
func(const_cast<bool&>(foo));
}
無条件に書き込むと
func()
において、これは間違いなく未定義の動作を引き起こします (読み取り専用メモリへの書き込みは、書き込みの効果がそうでなくても no-op であったとしても、プログラムを終了させます)。
関連
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】Visual Studio 2015で「非標準の構文; '&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】C++でランダムな2倍数を生成する
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】C++エラー:の初期化に一致するコンストラクタがありません。
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された
-
[解決済み] なぜGCCは、速度の代わりにサイズに最適化すると、15-20%速いコードを生成するのですか?
-
[解決済み] なぜこのプログラムは3つのC++コンパイラで誤って拒否されるのですか?
-
[解決済み】なぜC++コンパイラはoperator==とoperator!=を定義しないのでしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】構造体のベクター初期化について
-
[解決済み】コンストラクターでのエラー:識別子を期待されますか?
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み】「std::operator」で「operator<<」にマッチするものがない。
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない