# 帳票設計書 3-OptReport

## 概要

本ドキュメントは、LLVMプロジェクトの最適化レポートツール（llvm-opt-report）の設計仕様を記載する。YAML形式の最適化記録を解析し、ソースコードに注釈付きのレポートを生成する機能である。

### 本帳票の処理概要

llvm-opt-reportは、コンパイラが出力するYAML形式の最適化記録（Optimization Remarks）を解析し、元のソースコードに最適化情報を注釈として付加したレポートを生成するコマンドラインツールである。

**業務上の目的・背景**：コンパイラによる最適化は、プログラムの性能に大きく影響する。開発者が「どのコードがインライン化されたか」「どのループがベクトル化されたか」「どのループがアンロールされたか」を把握することで、性能チューニングの方針を立てやすくなる。本帳票は、最適化の適用状況を視覚的に確認できるようにし、性能改善の余地を特定することを目的とする。

**帳票の利用シーン**：性能チューニング作業時、コンパイラ最適化の検証時、ホットスポット分析後の改善確認、ベクトル化・並列化の適用確認時に利用される。

**主要な出力内容**：
1. ソースコード各行への最適化注釈（インライン化：I、アンロール：U、ベクトル化：V）
2. ベクトル化係数（VectorizationFactor）とインターリーブカウント
3. アンロールカウント
4. 関数コンテキスト別の最適化情報
5. 複数の最適化が適用された箇所の詳細表示

**帳票の出力タイミング**：llvm-opt-reportコマンドに最適化記録ファイル（.opt.yaml等）を入力として実行した際に生成される。

**帳票の利用者**：性能エンジニア、コンパイラ開発者、システムプログラマ、HPC開発者

## 帳票種別

注釈付きソースコードリスト

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | コマンドライン | `llvm-opt-report <input.yaml>` | コマンド実行 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（標準出力またはファイル） |
| 用紙サイズ | - |
| 向き | - |
| ファイル名 | -o オプションで指定（デフォルト：標準出力） |
| 出力方法 | 標準出力 / ファイル出力 |
| 文字コード | UTF-8 |

### テキスト出力固有設定

| 項目 | 内容 |
|-----|------|
| 行番号表示 | あり（左端） |
| 最適化マーカー | I/U/V（行番号の後） |
| ソースコード | パイプ（|）の後に表示 |

## 帳票レイアウト

### レイアウト概要

各ソースファイルについて、行番号と最適化マーカーを付加した形式で出力する。

```
┌─────────────────────────────────────────────────────────────────┐
│ < filename.cpp                                                   │
├─────────────────────────────────────────────────────────────────┤
│ [行番号] [I][U][V] | [ソースコード行]                           │
│    1              | #include <vector>                           │
│    2              | void func() {                               │
│    3  I           |   inline_call();                            │
│    4    U2        |   for (int i=0; i<n; ++i) // unrolled x2   │
│    5      V4,2    |     vec_loop();  // vectorized VF=4, IL=2  │
│                   |                          ^                  │
│                   |        V4,2    |         ^                  │
└─────────────────────────────────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | ファイル名 | ソースファイルパス | LocationInfo.key | "< filename" 形式 |

### 明細部（各行）

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | 行番号 | ソースコード行番号 | line_iterator | 右寄せ整数 | LNDigits |
| 2 | インライン化マーカー | I（インライン化済み） | Inlined.Transformed | "I" または空白 | 1 |
| 3 | アンロールマーカー | U + アンロールカウント | Unrolled.Transformed, UnrollCount | "U" + 数値 | UCDigits+1 |
| 4 | ベクトル化マーカー | V + VF,IL | Vectorized.Transformed | "V" + 数値,数値 | VFDigits+ICDigits+2 |
| 5 | 区切り | パイプ文字 | - | " \| " | 3 |
| 6 | ソースコード | 元のソースコード行 | MemoryBuffer | そのまま | 可変 |

### 詳細マーカー（複数最適化時）

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | カラム指示子 | 最適化適用位置 | ColsInfo.key | "^" 文字 |
| 2 | 最適化情報 | 該当カラムの最適化 | ColsInfo.value | I/U/V マーカー |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 最適化記録ファイル | YAML形式の.opt.yaml等 | Yes |
| 元ソースファイル | 最適化記録が参照するソースファイル | Yes（読込用） |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | ファイルパス | 昇順（std::map順） |
| 2 | 行番号 | 昇順 |
| 3 | カラム番号 | 昇順 |

### 改ページ条件

ファイル間に空行を挿入

## データベース参照仕様

### 参照データソース一覧

| データソース | 用途 | 取得方法 |
|-------------|------|---------|
| YAML最適化記録 | 最適化情報 | remarks::RemarkParser |
| ソースファイル | 元コード表示 | MemoryBuffer::getFile() |

### 最適化記録データ構造

| フィールド | 説明 | 取得元 |
|-----------|------|-------|
| PassName | 最適化パス名 | Remark.PassName |
| RemarkType | Passed/Missed等 | Remark.RemarkType |
| FunctionName | 関数名 | Remark.FunctionName |
| SourceFilePath | ソースパス | Loc.SourceFilePath |
| SourceLine | 行番号 | Loc.SourceLine |
| SourceColumn | カラム番号 | Loc.SourceColumn |
| VectorizationFactor | ベクトル化係数 | Args["VectorizationFactor"] |
| InterleaveCount | インターリーブ数 | Args["InterleaveCount"] |
| UnrollCount | アンロール回数 | Args["UnrollCount"] |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| LNDigits | utostr(NumLines).size() | - | 行番号桁数 |
| VFDigits | utostr(MaxVF).size() + (isScalable ? 2 : 0) | - | VF桁数 |
| ICDigits | utostr(MaxIC).size() | - | IL桁数 |
| UCDigits | utostr(MaxUC).size() | - | UC桁数 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[llvm-opt-report実行] --> B[YAML最適化記録読込]
    B --> C[RemarkParser作成]
    C --> D{次のRemark取得}
    D -->|EOF| E[レポート出力開始]
    D -->|Remark| F[PassName判定]
    F -->|inline| G[Inlined情報更新]
    F -->|loop-unroll| H[Unrolled情報更新]
    F -->|loop-vectorize| I[Vectorized情報更新]
    G --> D
    H --> D
    I --> D
    E --> J[ファイルごとにループ]
    J --> K[ソースファイル読込]
    K --> L[最大値からカラム幅計算]
    L --> M[行ごとにループ]
    M --> N{複数関数コンテキスト?}
    N -->|Yes| O[関数別に出力]
    N -->|No| P[単一行出力]
    O --> Q[詳細マーカー出力]
    P --> Q
    Q --> R{次の行?}
    R -->|Yes| M
    R -->|No| S{次のファイル?}
    S -->|Yes| J
    S -->|No| T[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 入力ファイルエラー | YAMLファイル読込失敗 | "Can't open file <file>: <error>" | ファイルパス確認 |
| パーサーエラー | YAML解析失敗 | エラー詳細出力 | YAML形式確認 |
| ソースファイルエラー | ソースファイル読込失敗 | "Can't open file <file>: <error>" | パス/権限確認 |
| 出力ファイルエラー | 出力先書込失敗 | "Can't open file <file>: <error>" | パス/権限確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数千〜数万Remark |
| 目標出力時間 | 数秒以内 |
| 同時出力数上限 | 1（シングルスレッド） |

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

- ソースコードがレポートに全文表示される
- ファイルパスが露出する

## 備考

- -s オプションでベクトル化係数等の詳細を省略（Succinct モード）
- --no-demangle オプションで関数名のデマングルを無効化
- --format オプションでYAML以外の形式も対応可能

---

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

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

### 推奨読解順序

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

最適化情報を保持するデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | OptReport.cpp | `llvm/tools/llvm-opt-report/OptReport.cpp` | OptReportLocationItemInfo（行75-96）とOptReportLocationInfo（行99-149）の構造を理解 |

**読解のコツ**: OptReportLocationItemInfoはAnalyzed/Transformedのboolペア、OptReportLocationInfoはInlined/Unrolled/Vectorizedの3種とVF/IC/UCの数値を保持する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | OptReport.cpp | `llvm/tools/llvm-opt-report/OptReport.cpp` | main関数（行479-495）の処理フローを確認 |

**主要処理フロー**:
1. **行479-486**: InitLLVM、コマンドラインオプション解析
2. **行488-489**: readLocationInfo()で最適化記録読込
3. **行490-491**: writeReport()でレポート出力
4. **行493**: 終了

#### Step 3: YAML解析処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | OptReport.cpp | `llvm/tools/llvm-opt-report/OptReport.cpp` | readLocationInfo()関数（行155-262）の実装 |

**主要処理フロー**:
- **行156-162**: MemoryBuffer::getFile()でファイル読込
- **行164-181**: remarks::createRemarkParserFromMeta()でパーサー作成
- **行184-259**: whileループでRemark読込、PassName判定、LocationInfo更新

#### Step 4: レポート出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | OptReport.cpp | `llvm/tools/llvm-opt-report/OptReport.cpp` | writeReport()関数（行264-477）の実装 |

**主要処理フロー**:
- **行265-271**: 出力ファイルオープン
- **行274-287**: ファイルごとのループ開始、ソースファイル読込
- **行298-314**: MaxLI計算、カラム幅計算
- **行323-473**: 行ごとのループ、PrintLineラムダ関数での出力

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

```
main()
    │
    ├─ cl::ParseCommandLineOptions()
    │
    ├─ readLocationInfo()
    │      ├─ MemoryBuffer::getFile()
    │      ├─ remarks::parseFormat()
    │      ├─ remarks::createRemarkParserFromMeta()
    │      └─ Parser.next() [ループ]
    │             └─ LocationInfo更新
    │
    └─ writeReport()
           ├─ raw_fd_ostream作成
           └─ ファイルごとのループ
                  ├─ MemoryBuffer::getFile()
                  ├─ MaxLI計算
                  ├─ LNDigits/VFDigits等計算
                  └─ 行ごとのループ
                         └─ PrintLine()
                                ├─ UniqueLIs計算
                                └─ マーカー出力
```

### データフロー図

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

.opt.yaml ──────────▶ RemarkParser
                           │
                           ▼
                    LocationInfoTy
                    (File -> Line -> Func -> Col -> Info)
                           │
                           │
SourceFiles ───────▶ MemoryBuffer
                           │
                           ▼
                    writeReport()
                           │
                           ▼
                    [行番号][I][U][V] | [ソース]
                           │
                           ▼
                    [標準出力/ファイル]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| OptReport.cpp | `llvm/tools/llvm-opt-report/OptReport.cpp` | ソース | ツールの主要実装（唯一のソースファイル） |
| Remark.h | `llvm/include/llvm/Remarks/Remark.h` | ヘッダ | Remarkデータ構造定義 |
| RemarkParser.h | `llvm/include/llvm/Remarks/RemarkParser.h` | ヘッダ | YAMLパーサーインターフェース |
| RemarkFormat.h | `llvm/include/llvm/Remarks/RemarkFormat.h` | ヘッダ | 形式判定ユーティリティ |
