Misexpect

開発者が llvm.expect 組み込み関数、つまり __builtin_expect(...) を使用する場合、コードが実行時にどのように動作するかをオプティマイザに伝えようとしています。しかし、これらのアノテーションは、コードベースの変更によって暗黙的に無効化されたり、開発者が誤ってアノテーションを付けたり(たとえば、UNLIKELY の代わりに LIKELY を使用したり)、アノテーションを記述したときに何かを誤って想定したりするなど、さまざまな理由で不正確になる可能性があります。理由に関係なく、オプティマイザがコードについてより有用な決定を下せるように、これらの状況を検出することは有用です。MisExpect 診断は、llvm.expect 組み込み関数の使用をプロファイリング入力によって提供されるグランドトゥルースと比較することにより、開発者がこれらの状況を特定して対処するのに役立つことを目的としています。

LLVM バックエンドの MisExpect チェックは、単純な手順に従います。プロファイリング中に収集された分岐の重みと llvm.expect 組み込み関数によって提供された分岐の重みに不一致がある場合、ユーザーに診断メッセージを出力します。

検証を実行する最も自然な場所は、分岐の重みが分岐重みメタデータの形式でターゲット命令に割り当てられる直前です。

LLVM バックエンドには、プロファイリング情報または llvm.expect 組み込み関数の使用に基づいて分岐の重みが作成および割り当てられる 3 つの主要な場所があり、実装ではこれらの場所に焦点を当てて検証を実行します。

MisExpect 関連の診断を出力するためのしきい値は、コンパイラが llvm.expect 組み込み関数に割り当てる値に基づいて計算します。これらの値は、-likely-branch-weight および -unlikely-branch-weight LLVM オプションを使用して設定できます。検証中に、プロファイルの重みが計算されたしきい値と一致しない場合、潜在的なパフォーマンスの低下を詳述したリマークまたは警告を出力します。診断では、アノテーションがプロファイリング中に正しかった時間の割合も報告され、開発者がどのように対処するかを判断するのに役立ちます。

診断は、最適化リマークの形式でも利用できます。これは、LLVM の opt-viewer.py スクリプトを使用してシリアル化および処理できます。

-pass-remarks=misexpect

プロファイリングデータが llvm.expect 組み込み関数の使用と競合する場合、misexpect の最適化リマークを有効にします。

-pgo-warn-misexpect

プロファイリングデータが llvm.expect 組み込み関数の使用と競合する場合、misexpect 警告を有効にします。

LLVM は、フロントエンド、IR、CS-IR、サンプリングの 4 種類のプロファイル形式をサポートしています。MisExpect 診断は、すべてのプロファイリング形式と互換性があります。

プロファイルの種類

説明

フロントエンド

コンパイル中にフロントエンド(例:clang)によって追加されたプロファイリング計測

IR

LLVM バックエンドによって追加されたプロファイリング計測

CS-IR

コンテキスト依存の IR ベースのプロファイル

サンプリング

Linux の perf などの外部ツールを使用したサンプリングによって収集されたプロファイル