Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
502 changes: 502 additions & 0 deletions docs/topics/13-窥孔优化器-设计文档.md

Large diffs are not rendered by default.

192 changes: 192 additions & 0 deletions docs/topics/13-窥孔优化器-赛道A-开发文档.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# ScratchV 课题13 赛道 A:Parser 复用与健壮性加固 — 开发文档

> **文档版本**:v1.0
> **创建日期**:2026-08-04
> **作者**:孟子旭(@zinoe-1)
> **关联**:[PR #39](https://github.com/ScratchV-Compiler/ScratchV/pull/39);设计文档见同目录 `13-窥孔优化器-赛道A-设计文档.md`
> **涉及模块**:`scratchv/backend/`、`tests/test_asm_peephole*.py`、`docs/topics/`

---

## 1. 功能概述与目标

### 1.1 背景与动机

- **现状问题**:PR #39 的窥孔实现内嵌重复汇编 parser;AI review 指出 mv-swap 检查与 `x0`/`zero` 别名等技术债。
- **应用场景**:保证 `--peephole-asm` 在畸形输入下不崩溃;与 beautifier 等 pass 共享解析语义,降低后续赛道 B/C/D 的集成成本。

### 1.2 功能描述

- **一句话定义**:让窥孔优化器复用 `_asm_parser`,并修掉 PR #39 review 中的关键健壮性问题。
- **核心价值**:单一 parser、更少崩溃面、别名正确匹配,为后续 CI / Benchmark / 深度优化打底。

### 1.3 目标与非目标

| 类型 | 内容 |
|------|------|
| ✅ 包含范围 | Parser 复用、IndexError 防护、零寄存器别名、文档、回归测试、fixture 小清理 |
| ❌ 不包含范围 | 全链路 simulator CI、compare_peephole、CFG/liveness |

---

## 2. 设计与规格说明

### 2.1 用户视角(外部接口)

公开 API 不变:

```python
from scratchv.backend.asm_peephole import AsmPeepholeOptimizer

opt = AsmPeepholeOptimizer()
text, n = opt.optimize(asm)
print(opt.report())
```

CLI 不变:

```bash
python -m scratchv.backend.asm_peephole input.s -o out.s --report
python -m scratchv model.onnx -o out.s --peephole-asm --count-instr
```

兼容别名(供测试使用):

```python
from scratchv.backend.asm_peephole import AsmLine, _parse_line, _parse_asm, _lines_to_asm
# AsmLine is ParsedAsmLine
```

### 2.2 内部设计

1. `asm_text` → `_parse_asm` → `list[ParsedAsmLine]`
2. 固定点滑动窗口匹配 `_match_rule`
3. `_apply_replacement` → `_lines_to_asm`

关键辅助:

- `_canon_reg` / `_regs_equal` / `_is_zero_reg`
- `_count_opcodes` 使用 `is_directive`

### 2.3 模块间交互

- **上游**:`compiler._run_asm_passes` 在开启 `peephole_asm` 时调用。
- **下游**:美化 / const-merge 等仍接收文本;不改变其输入契约。
- **共享依赖**:`_asm_parser.ParsedAsmLine`。

---

## 3. 模块修改与实现步骤

### 3.1 文件清单

| 文件路径 | 修改类型 | 修改内容概述 |
|----------|----------|--------------|
| `scratchv/backend/asm_peephole.py` | 修改 | 复用 parser;别名;IndexError 防护 |
| `tests/test_asm_peephole.py` | 修改 | 新增赛道 A 回归用例 |
| `tests/fixtures/asm_peephole/*.s` | 修改 | `.globl` + 意图注释 |
| `docs/topics/13-窥孔优化器-赛道A-*.md` | 新增 | 设计 / 开发文档 |
| `topic13/README.md` | 修改 | 索引赛道 A 文档 |

### 3.2 分步实现计划

| 步骤 | 任务 | 预期产出 | 验证 |
|------|------|----------|------|
| 1 | 基于 PR #39 tip 建分支 | `feat/topic13-peephole-parser-reuse` | `git log -1` |
| 2 | 替换本地 parser | 无 `_LINE_RE` | grep |
| 3 | 别名 + IndexError | `_regs_equal` / `len>=2` | 单元测试 |
| 4 | 文档 | 设计+开发 md | 人工 review |
| 5 | 全量 peephole 测试 | 全绿 | pytest |
| 6 | 提 PR | GitHub PR | 审阅 |

### 3.3 边界条件

- [x] 畸形 `mv`(操作数不足)不崩溃
- [x] `x0`/`zero` 混用 beq / 约束
- [x] directive 不计入指令节省统计
- [ ](已知限制)不做 `li rd,0` ↔ `mv rd,x0` 等价折叠

---

## 4. 测试与验证方案

### 4.1 单元测试

文件:`tests/test_asm_peephole.py`

新增场景:

1. 共享 parser:directive 不计入 `_count_opcodes`
2. 短操作数 mv:无异常
3. `addi zero, x0, 0` 可消除

### 4.2 回归命令

```powershell
.\.venv\Scripts\Activate.ps1
pytest tests/test_asm_peephole.py tests/test_asm_peephole_blackbox.py `
tests/test_asm_peephole_integration.py tests/test_asm_peephole_stress.py -v
```

### 4.3 验收标准(Definition of Done)

- [ ] 上述 pytest 全绿
- [ ] `asm_peephole.py` 不再包含独立 `_LINE_RE` 实现
- [ ] 设计文档 + 开发文档已提交,作者姓名经人工确认
- [ ] PR 描述写明依赖 / 包含 PR #39 基线

---

## 5. 风险评估与依赖

| 风险项 | 影响 | 缓解 |
|--------|------|------|
| PR #39 未合入导致与 main 冲突 | 中 | 分支基于 `pull/39/head`;PR 说明合并顺序 |
| 共享 `lines_to_asm` 格式细微差异 | 低 | 黑盒 / 集成测试覆盖 |

- **外部依赖**:无新增第三方库
- **兼容性**:公开 `AsmPeepholeOptimizer` API 不变

---

## 6. 开发进度跟踪

| 阶段 | 计划完成日期 | 状态 |
|------|--------------|------|
| 设计评审(本文档) | 2026-08-04 | ✅ |
| 编码实现 | 2026-08-04 | ⏳ |
| 自测与调试 | 2026-08-04 | ⏳ |
| 代码审查(PR) | 2026-08-04 | ⬜ |
| 合并主分支 | TBD | ⬜ |

---

## 7. 附录

### 7.1 参考资料

- [PR #39](https://github.com/ScratchV-Compiler/ScratchV/pull/39)
- 设计文档模板 / 开发文档模板(课程提供)
- [`_asm_parser.py`](../../scratchv/backend/_asm_parser.py)

### 7.2 PR 标题建议

```
feat(peephole): reuse shared _asm_parser and harden match guards (topic13 track A)
```

### 7.3 PR 正文草稿

```markdown
## Summary
- Reuse `scratchv/backend/_asm_parser.py` inside `asm_peephole` (remove duplicate parser)
- Harden `redundant mv elimination` swap check (operand length guards)
- Normalize `x0`/`zero` aliases in register constraint matching
- Add track-A design/dev docs + regression tests

## Baseline
Based on PR #39 (`docs/topic13-peephole`). Please merge #39 first or review this as a stacked follow-up.

## Test plan
- [x] pytest tests/test_asm_peephole*.py
```
154 changes: 154 additions & 0 deletions docs/topics/13-窥孔优化器-赛道A-设计文档.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# ScratchV 课题13 赛道 A:窥孔 Parser 复用与健壮性加固 — 技术设计文档

> 文档版本:v1.0
> 编写日期:2026-08-04
> 作者:孟子旭(@zinoe-1)
> 涉及模块:`scratchv/backend/asm_peephole.py`、`scratchv/backend/_asm_parser.py`
> 功能范围:复用共享汇编解析器、删除重复 parser、修复 PR #39 review 中的健壮性问题
> 关联:基于 [PR #39](https://github.com/ScratchV-Compiler/ScratchV/pull/39) 后续完善;导师建议赛道 A

---

## 一、功能介绍

### 1.1 功能概述

PR #39 已为汇编层窥孔优化器打下基础(8 条默认规则、测试与文档)。本工作在其上做**工程化加固**:

1. **Parser 复用**:`asm_peephole.py` 不再维护独立的 `AsmLine` / `_LINE_RE` / `_parse_*`,改为调用共享模块 `scratchv/backend/_asm_parser.py`。
2. **健壮性**:修复 review 指出的 mv-swap 检查潜在 `IndexError`;在规则匹配中统一 `x0` / `zero` 别名。
3. **文档与测试**:补充设计/开发文档,并为上述改动增加回归测试。

### 1.2 设计目标

- **单一真相来源**:后端所有汇编 pass 共用一套行解析语义(操作数括号感知、directive 标记)。
- **向后兼容**:对外仍导出 `AsmLine`、`_parse_line`、`_parse_asm`、`_lines_to_asm`(薄封装),现有测试尽量零改动。
- **安全优先**:短操作数 / 畸形行不得崩溃;零寄存器别名不得漏匹配或误匹配。
- **范围可控**:本次不做 CFG / liveness / 深度优化(留给赛道 D)。

### 1.3 目标与非目标

| 类型 | 内容 |
|------|------|
| ✅ 包含 | 复用 `_asm_parser`;删重复 parser;IndexError 防护;`x0`/`zero` 规范化;赛道 A 文档;回归测试 |
| ❌ 不包含 | CI 全链路仿真对比(赛道 B);`compare_peephole.py`(赛道 C);CFG / liveness / coalescing(赛道 D) |

---

## 二、设计与规格

### 2.1 现状问题

| 问题 | 影响 |
|------|------|
| `asm_peephole` 内嵌独立 parser | 与 beautifier / const-merge 行为漂移;导师明确要求复用 `_asm_parser` |
| mv-swap 排除仅检查 `window[1].operands` 非空 | 仅 1 个操作数时访问不安全(review 🔴) |
| 寄存器约束用裸字符串比较 | `addi x0, zero, 0` 等别名组合可能漏优化 |

### 2.2 架构决策

```
asm_text
_asm_parser.parse_asm ──► list[ParsedAsmLine] (= AsmLine 别名)
AsmPeepholeOptimizer.optimize(滑动窗口 + 固定点)
_asm_parser.lines_to_asm ──► optimized asm
```

**`PeepholeRule.register_constraints` 索引约定**(澄清 PR #39 review):

- 三元组 `(dst_instr, src_instr, src_op)` 均为**匹配窗口内** 0-based 下标。
- 语义:`window[dst_instr].operands[0] == window[src_instr].operands[src_op]`(经 `_canon_reg`)。
- 示例:`(0, 1, 1)` → 第 0 条指令的 rd 必须等于第 1 条指令的第 1 个源操作数。

### 2.3 寄存器别名

| 输入 | 规范名 |
|------|--------|
| `x0`、`zero` | `x0` |

用于:寄存器约束比较、beq 零零判定、addi-zero 的 rd/rs 相等判定、mv-swap 形状判定。

**刻意不做**:把 `li rd, 0` 与 `mv rd, x0` 视为同一模式(那是规则层面的扩展,超出本次范围;文档中记为已知限制)。

### 2.4 标签安全(与 PR #39 对齐)

- 窗口内第 2 条及以后若带 `label` → **拒绝匹配**(避免吞掉跳转目标)。
- 窗口首条若带 `label` → **允许匹配**;替换结果第一条继承该 label;删除规则时保留裸 label。

---

## 三、测试设计

### 用例 1:共享 parser 指令计数

- 输入含 `.text` directive + 真指令。
- 预期:`_count_opcodes` 不计 directive(依赖 `is_directive`)。

### 用例 2:mv 短操作数不崩溃

- 输入:`mv t0`(畸形,仅 1 操作数)后接另一行。
- 预期:优化器不抛 `IndexError`,结果可返回。

### 用例 3:`x0`/`zero` 混用 beq

- 已有:`beq zero, x0, L` → `j`。
- 补充:约束路径上 `addi zero, x0, 0` 可被 self-elimination 删除。

### 用例 4:回归

- `pytest tests/test_asm_peephole*.py` 全绿。

---

## 四、修改模块与实现步骤

### 4.1 涉及文件

| 文件 | 修改类型 | 概述 |
|------|----------|------|
| `scratchv/backend/asm_peephole.py` | 修改 | 删本地 parser;包装 `_asm_parser`;别名与 IndexError 修复 |
| `tests/test_asm_peephole.py` | 新增用例 | parser 复用 / 别名 / 短操作数 |
| `tests/fixtures/asm_peephole/*.s` | 小改 | `.globl main`、注释 |
| `docs/topics/13-窥孔优化器-赛道A-设计文档.md` | 新增 | 本文档 |
| `docs/topics/13-窥孔优化器-赛道A-开发文档.md` | 新增 | 实现与验收 |
| `topic13/README.md` | 修改 | 链到赛道 A 文档 |

### 4.2 实现步骤

1. 引入 `ParsedAsmLine as AsmLine` 与共享 parse/format。
2. 删除 `_LINE_RE`、本地 `_split_operands` 实现体。
3. `_count_opcodes` 改为 `not al.is_directive`。
4. `_regs_equal` / `_is_zero_reg` 接入约束与特殊规则。
5. mv-swap 分支要求 `len(operands) >= 2`。
6. 补测试并跑全量 peephole 测试。

---

## 五、风险评估

| 风险 | 程度 | 缓解 |
|------|------|------|
| 共享 parser 与旧 parser 细微差异导致测试失败 | 中 | 薄封装保留 `strip()`;跑全套 peephole 测试 |
| directive 表示变化(去点号) | 低 | 使用 `is_directive` 而非 `startswith('.')` |
| 与未合并的 PR #39 冲突 | 中 | **本 PR 基线即为 PR #39 tip**;合并顺序:先 #39 再本 PR,或本 PR 直接含 #39 变更 |

### 基线说明

本工作基于 `refs/pull/39/head`(`d62acdf`)开发。向 `ScratchV-Compiler/ScratchV:main` 提 PR 时,若 #39 尚未合并,审阅者需知本分支已包含 #39 的窥孔基建;若 #39 已合并,则 rebase 到最新 `main` 即可。

---

## 六、附录

### 参考资料

- [PR #39](https://github.com/ScratchV-Compiler/ScratchV/pull/39) 及 AI review 评论
- 导师群消息:完善评论点 + 复用 `_asm_parser.py`
- [`scratchv/backend/_asm_parser.py`](../../scratchv/backend/_asm_parser.py)
- 课题13 设计文档(PR #39):[`13-窥孔优化器-设计文档.md`](./13-窥孔优化器-设计文档.md)
Loading
Loading