# 機能設計書 41-llvm-profdata

## 概要

本ドキュメントは、LLVM llvm-profdataツールの機能設計を記述したものである。llvm-profdataはプロファイルデータの操作ツールであり、プロファイルファイルのマージ、表示、比較、順序付けなどの機能を提供する。

### 本機能の処理概要

llvm-profdataは、LLVMのプロファイルガイド最適化（PGO）およびAutomatic Feedback-Directed Optimization（AutoFDO）で使用されるプロファイルデータを操作するためのコマンドラインツールである。

**業務上の目的・背景**：コンパイラ最適化において、実行時プロファイル情報は最適化の判断に重要な役割を果たす。llvm-profdataは、複数の実行から収集されたプロファイルデータを統合し、解析可能な形式で表示し、プロファイル間の比較を行うことで、より効果的な最適化を実現するための基盤ツールである。

**機能の利用シーン**：
- 複数のテスト実行から得られたプロファイルデータを1つに統合する場合
- プロファイルデータの内容を確認・デバッグする場合
- 2つのプロファイル間の差異を分析する場合
- 時系列プロファイルから最適な関数順序を計算する場合

**主要な処理内容**：
1. merge: 複数のプロファイルファイルをマージして1つのファイルに統合
2. show: プロファイルデータの内容を人間が読める形式で表示
3. overlap: 2つのプロファイル間の重複度を計算・表示
4. order: 時系列プロファイルトレースから関数順序を計算

**関連システム・外部連携**：
- Clangのインストルメンテーションプロファイリング機能と連携
- サンプルベースプロファイリング（AutoFDO）と連携
- LLVMのPGO最適化パイプラインにプロファイルを提供

**権限による制御**：特になし（ローカルファイル操作のみ）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | コマンドライン | 主画面 | 各サブコマンドの実行とオプション指定 |

## 機能種別

データ変換処理 / データ解析処理 / レポート出力

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| サブコマンド | string | Yes | show/merge/overlap/order | 有効なサブコマンド名 |
| profdata-file | string | Yes | 入力プロファイルファイル | ファイル存在チェック |
| -output / -o | string | No | 出力ファイル名（デフォルト: -） | 書き込み可能パス |
| -format | enum | No | 出力形式（binary/extbinary/text/gcc） | 有効な形式 |
| -weighted-input | string | No | 重み付き入力（weight,filename） | 形式チェック |
| -function | string | No | フィルタリング対象の関数名 | - |

### 入力データソース

- インストルメンテーションプロファイルファイル（.profdata / .profraw）
- サンプルプロファイルファイル
- メモリプロファイルファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 統合プロファイル | binary/text | マージされたプロファイルデータ |
| プロファイル表示 | text/json/yaml | プロファイル内容のダンプ |
| 重複度レポート | text | 2つのプロファイルの類似度分析 |
| 関数順序リスト | text | 最適化された関数配置順序 |

### 出力先

- 標準出力（デフォルト）
- 指定されたファイル

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数の解析
   └─ サブコマンドとオプションの識別
2. サブコマンドに応じた処理分岐
   └─ merge/show/overlap/orderの実行
3. 入力ファイルの読み込み
   └─ プロファイルリーダーによる解析
4. プロファイルデータの処理
   └─ マージ/フィルタリング/統計計算
5. 結果の出力
   └─ 指定形式でのシリアライズ
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{サブコマンド判定}
    B -->|merge| C[mergeMain]
    B -->|show| D[showMain]
    B -->|overlap| E[overlapMain]
    B -->|order| F[orderMain]
    C --> G[複数プロファイル読込]
    G --> H[プロファイルマージ]
    H --> I[出力ファイル書込]
    D --> J[プロファイル読込]
    J --> K[内容表示]
    E --> L[2プロファイル読込]
    L --> M[重複度計算]
    M --> N[結果出力]
    F --> O[時系列トレース読込]
    O --> P[関数順序計算]
    P --> Q[順序出力]
    I --> R[終了]
    K --> R
    N --> R
    Q --> R
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-41-01 | プロファイル互換性 | マージ対象のプロファイルは同じ種別である必要がある | merge時 |
| BR-41-02 | 重み付け | 重み付き入力では重みは正の数である必要がある | weighted-input使用時 |
| BR-41-03 | 形式自動検出 | 入力ファイルの形式は自動的に検出される | 常時 |

### 計算ロジック

- マージ時のカウンタ集計: 各関数の実行カウントを合計
- 重複度計算: 共通関数のカウント比率を算出
- 時系列順序計算: ページフォールト最小化アルゴリズム

## データベース操作仕様

### 操作別データベース影響一覧

該当なし（ファイルベースの処理）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ファイル不在 | 入力ファイルが存在しない | ファイルパスを確認 |
| - | 形式エラー | プロファイル形式が無効 | 正しい形式のファイルを指定 |
| - | 互換性エラー | マージ対象の形式が異なる | 同一形式のファイルを指定 |

### リトライ仕様

該当なし

## トランザクション仕様

該当なし

## パフォーマンス要件

- 大規模プロファイル（数GB）の処理をサポート
- マルチスレッドによる並列マージ（-num-threadsオプション）

## セキュリティ考慮事項

- 入力ファイルの検証（マルフォームドデータのチェック）
- 出力ファイルの上書き確認

## 備考

- llvm-profdataはLLVMのプロファイリングインフラストラクチャの中核ツールである
- インストルメンテーションプロファイルとサンプルプロファイルの両方をサポート

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

プロファイルデータの構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ProfileCommon.h | `llvm/include/llvm/ProfileData/ProfileCommon.h` | プロファイルサマリー構造 |
| 1-2 | InstrProfReader.h | `llvm/include/llvm/ProfileData/InstrProfReader.h` | プロファイル読み込みインターフェース |
| 1-3 | InstrProfWriter.h | `llvm/include/llvm/ProfileData/InstrProfWriter.h` | プロファイル書き込みインターフェース |

**読解のコツ**: LLVMのプロファイルデータは、インストルメンテーション（instr）とサンプル（sample）の2種類があり、それぞれ異なるデータ構造を持つ。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | llvm-profdata.cpp | `llvm/tools/llvm-profdata/llvm-profdata.cpp` | メイン関数とサブコマンド定義 |

**主要処理フロー**:
1. **57-77行目**: サブコマンド（show/order/overlap/merge）の定義
2. **79-93行目**: ProfileKinds列挙型とProfileFormat定義
3. **95-106行目**: 共通オプション（OutputFilename等）の定義

#### Step 3: mergeサブコマンドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | llvm-profdata.cpp | `llvm/tools/llvm-profdata/llvm-profdata.cpp` | merge処理の実装 |

**主要処理フロー**:
- **168-189行目**: 入力ファイル関連オプション
- **200-234行目**: マージオプション（MD5使用、圧縮等）
- **282-299行目**: FailureMode定義とスパース出力オプション

#### Step 4: showサブコマンドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | llvm-profdata.cpp | `llvm/tools/llvm-profdata/llvm-profdata.cpp` | show処理の実装 |

**主要処理フロー**:
- **386-446行目**: show固有オプション（ShowCounts、ShowFormat等）
- **390-397行目**: ShowFormat列挙型（Text/Json/Yaml）

### プログラム呼び出し階層図

```
main()
    │
    ├─ cl::ParseCommandLineOptions()
    │
    ├─ ShowSubcommand
    │      └─ showMain()
    │           └─ InstrProfReader / SampleProfileReader
    │
    ├─ MergeSubcommand
    │      └─ mergeMain()
    │           ├─ InstrProfReader::create()
    │           ├─ InstrProfWriter::write()
    │           └─ SampleProfileWriter::create()
    │
    ├─ OverlapSubcommand
    │      └─ overlapMain()
    │           └─ 重複度計算処理
    │
    └─ OrderSubcommand
           └─ orderMain()
                └─ 関数順序計算処理
```

### データフロー図

```
[入力]                    [処理]                         [出力]

.profraw           ───▶ InstrProfReader     ───▶ マージ/統計 ───▶ .profdata
.profdata          ───▶ SampleProfileReader ───▶ フィルタ    ───▶ stdout
sample profile     ───▶ MemProfReader       ───▶ 変換        ───▶ レポート
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| llvm-profdata.cpp | `llvm/tools/llvm-profdata/` | ソース | メインエントリーポイント |
| InstrProfReader.h | `llvm/include/llvm/ProfileData/` | ヘッダ | プロファイル読み込みAPI |
| InstrProfWriter.h | `llvm/include/llvm/ProfileData/` | ヘッダ | プロファイル書き込みAPI |
| SampleProfReader.h | `llvm/include/llvm/ProfileData/` | ヘッダ | サンプルプロファイル読み込み |
| SampleProfWriter.h | `llvm/include/llvm/ProfileData/` | ヘッダ | サンプルプロファイル書き込み |
| ProfileCommon.h | `llvm/include/llvm/ProfileData/` | ヘッダ | 共通データ構造 |
