From 9b8fcf60ebbe70df606f640bd45a59900956acd4 Mon Sep 17 00:00:00 2001 From: Lane0218 Date: Thu, 12 Mar 2026 16:40:22 +0800 Subject: [PATCH] =?UTF-8?q?style(doc):=20=E7=AE=80=E5=8C=96=E5=AE=9E?= =?UTF-8?q?=E9=AA=8C=E6=96=87=E6=A1=A3=E6=96=87=E4=BB=B6=E6=8C=87=E5=BC=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/Lab1-语法树构建.md | 11 +++-- doc/Lab2-中间表示生成.md | 42 ++++------------- doc/Lab3-指令选择与汇编生成.md | 55 ++++++---------------- doc/Lab4-寄存器分配.md | 61 ++++++------------------- doc/Lab5-基本标量优化.md | 61 ++++++------------------- doc/Lab6-并行与循环优化.md | 52 +++++++-------------- 6 files changed, 74 insertions(+), 208 deletions(-) diff --git a/doc/Lab1-语法树构建.md b/doc/Lab1-语法树构建.md index 3198dee..ba4f6d2 100644 --- a/doc/Lab1-语法树构建.md +++ b/doc/Lab1-语法树构建.md @@ -14,12 +14,13 @@ Lab1 聚焦前端第一步:词法/语法分析。 2. 通过构建流程重新生成 Lexer/Parser。 3. 让更多合法 SysY 程序可以被解析通过(不再仅限当前最小样例)。 -## 3. Lab1 需要补充的内容 +## 3. 相关文件 -1. 需要修改的文件 - - `src/antlr4/SysY.g4`:补全文法规则。 - - `src/frontend/AntlrDriver.cpp`:解析入口与错误处理。 - - `src/frontend/SyntaxTreePrinter.cpp`:语法树打印逻辑(用于调试验证)。 +以下文件与本实验内容相关,建议优先阅读。 + +- `src/antlr4/SysY.g4` +- `src/frontend/AntlrDriver.cpp` +- `src/frontend/SyntaxTreePrinter.cpp` ## 4. 当前示例实现说明 diff --git a/doc/Lab2-中间表示生成.md b/doc/Lab2-中间表示生成.md index bdb73c1..057ce3e 100644 --- a/doc/Lab2-中间表示生成.md +++ b/doc/Lab2-中间表示生成.md @@ -12,39 +12,17 @@ Lab2 的目标是在该示例基础上扩展语义覆盖范围,逐步把更多 2. 理解当前语法树 -> IR 的最小实现流程。 3. 在现有框架上扩展 IR 生成能力,使其覆盖课程要求的Sysy语法。 -## 3. 当前代码框架 +## 3. 相关文件 -1. IR 定义与打印 - - `include/ir/IR.h` - - `src/ir/IRBuilder.cpp` - - `src/ir/IRPrinter.cpp` +以下文件与本实验内容相关,建议优先阅读。 -2. 语法树 -> IR 生成器 - - `include/irgen/IRGen.h` - - `src/irgen/IRGenDriver.cpp` - - `src/irgen/IRGenFunc.cpp` - - `src/irgen/IRGenDecl.cpp` - - `src/irgen/IRGenStmt.cpp` - - `src/irgen/IRGenExp.cpp` +- `include/ir/IR.h` +- `include/irgen/IRGen.h` +- `src/irgen/IRGenDecl.cpp` +- `src/irgen/IRGenStmt.cpp` +- `src/irgen/IRGenExp.cpp` -3. 入口流程 - - `src/main.cpp` - -## 4. Lab2 需要补充的内容 - -1. 必须修改的文件 - - `src/irgen/IRGenDecl.cpp` - - `src/irgen/IRGenStmt.cpp` - - `src/irgen/IRGenExp.cpp` - - `include/ir/IR.h`(当现有 IR 指令/类型不够用时) - - `src/ir/IRBuilder.cpp`(当需要新增构建接口时) - - `src/ir/IRPrinter.cpp`(新增 IR 指令后补齐打印) - - `include/irgen/IRGen.h`(当需要扩展状态或辅助接口时) - -2. 视实现需要可能修改 - - `src/main.cpp`(当需要调整输出阶段行为) - -## 5. 当前最小示例实现说明 +## 4. 当前最小示例实现说明 当前语法树 -> IR 仅覆盖最小子集: @@ -59,14 +37,14 @@ Lab2 的目标是在该示例基础上扩展语义覆盖范围,逐步把更多 此外,当前 IR 还维护了最基本的 use-def 关系:每个 `Value` 会记录哪些 `Instruction` 使用了它。 这对后续做数据流分析、死代码删除、常量传播等优化会很有帮助;但目前相关实现,接口仍不完整,后续实验中还需要同学继续补充和完善。 -## 6. 构建与运行 +## 5. 构建与运行 ```bash cmake -S . -B build -DCMAKE_BUILD_TYPE=Release cmake --build build -j "$(nproc)" ``` -## 7. Lab2 验证方式 +## 6. Lab2 验证方式 可先用单个样例检查 IR 输出是否基本正确: diff --git a/doc/Lab3-指令选择与汇编生成.md b/doc/Lab3-指令选择与汇编生成.md index 5a4b657..d06487c 100644 --- a/doc/Lab3-指令选择与汇编生成.md +++ b/doc/Lab3-指令选择与汇编生成.md @@ -13,45 +13,17 @@ Lab3 的目标是在该示例基础上扩展后端语义覆盖范围,逐步把 2. 理解当前 IR -> MIR -> 汇编输出的最小实现流程。 3. 在现有框架上扩展后端代码生成能力,使其覆盖课程要求的 SysY 语义。 -## 3. 当前代码框架 - -1. MIR 定义与目标相关抽象 - - `include/mir/MIR.h` - - `src/mir/MIRContext.cpp` - - `src/mir/MIRFunction.cpp` - - `src/mir/MIRBasicBlock.cpp` - - `src/mir/MIRInstr.cpp` - - `src/mir/Register.cpp` - -2. IR -> MIR 与汇编生成 - - `src/mir/Lowering.cpp` - - `src/mir/RegAlloc.cpp` - - `src/mir/FrameLowering.cpp` - - `src/mir/AsmPrinter.cpp` - -3. 入口流程 - - `src/main.cpp` - - `include/utils/CLI.h` - - `src/utils/CLI.cpp` - -## 4. Lab3 需要补充的内容 - -1. 必须修改的文件 - - `src/mir/Lowering.cpp` - - `src/mir/RegAlloc.cpp` - - `src/mir/FrameLowering.cpp` - - `src/mir/AsmPrinter.cpp` - - `include/mir/MIR.h`(当现有 MIR 数据结构或接口不够用时) - - `src/mir/MIRInstr.cpp`(当需要新增机器指令或操作数表达时) - - `src/mir/MIRFunction.cpp`(当需要扩展栈帧或机器函数状态时) - - `src/mir/Register.cpp`(当需要扩展物理/虚拟寄存器表示时) - -2. 视实现需要可能修改 - - `src/main.cpp`(当需要调整输出阶段行为时) - - `src/utils/CLI.cpp`(当需要扩展后端相关命令行选项时) - - `scripts/verify_asm.sh`(当需要扩展统一验证脚本时) - -## 5. 当前最小示例实现说明 +## 3. 相关文件 + +以下文件与本实验内容相关,建议优先阅读。 + +- `include/mir/MIR.h` +- `src/mir/Lowering.cpp` +- `src/mir/RegAlloc.cpp` +- `src/mir/FrameLowering.cpp` +- `src/mir/AsmPrinter.cpp` + +## 4. 当前最小示例实现说明 当前 IR -> 汇编仅覆盖最小子集: @@ -61,17 +33,16 @@ Lab3 的目标是在该示例基础上扩展后端语义覆盖范围,逐步把 4. `RegAlloc` 当前仅执行最小一致性检查,不实现真实寄存器分配。 5. `FrameLowering` 当前会插入最小序言/尾声,并按 16 字节对齐栈帧。 - 说明:当前阶段后端主要用于演示完整流程。即使中间值可以暂存在寄存器中,也会先写回栈槽,而不是直接构造更接近最终机器代码的寄存器流。后续实验中,同学可按需求继续扩展指令选择、寄存器分配、调用约定与控制流相关功能。 -## 6. 构建与运行 +## 5. 构建与运行 ```bash cmake -S . -B build -DCMAKE_BUILD_TYPE=Release cmake --build build -j "$(nproc)" ``` -## 7. Lab3 验证方式 +## 6. Lab3 验证方式 可先用单个样例检查汇编输出是否基本正确: diff --git a/doc/Lab4-寄存器分配.md b/doc/Lab4-寄存器分配.md index 4ea4acd..621af60 100644 --- a/doc/Lab4-寄存器分配.md +++ b/doc/Lab4-寄存器分配.md @@ -18,52 +18,17 @@ Lab4 的目标是在 Lab3 示例基础上,把“固定寄存器 + 栈槽”的 7. 图着色寄存器分配与线性扫描寄存器分配均可作为实现路线,同学可自行选择其中一种完成;后端优化部分也不限定具体实现方式,只要求功能正确、收益明确。 8. 在 `test/test_case` 提供的全部测试用例上验证正确性,并在保证功能正确的前提下尽量减少冗余 spill/reload、无效拷贝、冗余访存与低效机器指令,提升生成代码质量。 -## 3. 当前代码框架 - -1. MIR 定义与寄存器相关抽象 - - `include/mir/MIR.h` - - `src/mir/MIRContext.cpp` - - `src/mir/MIRFunction.cpp` - - `src/mir/MIRBasicBlock.cpp` - - `src/mir/MIRInstr.cpp` - - `src/mir/Register.cpp` - -2. IR -> MIR、寄存器分配与后续落地 - - `src/mir/Lowering.cpp` - - `src/mir/RegAlloc.cpp` - - `src/mir/FrameLowering.cpp` - - `src/mir/AsmPrinter.cpp` - -3. 后端优化 Pass - - `src/mir/passes/PassManager.cpp` - - `src/mir/passes/Peephole.cpp` - -4. 入口流程 - - `src/main.cpp` - - `include/utils/CLI.h` - - `src/utils/CLI.cpp` - -## 4. Lab4 需要补充的内容 - -1. 必须修改的文件 - - `include/mir/MIR.h`(扩展寄存器、操作数、机器函数等数据结构,使其能够表示虚拟寄存器与分配结果) - - `src/mir/Register.cpp`(补充物理/虚拟寄存器表示、可分配寄存器集合等) - - `src/mir/MIRInstr.cpp`(当需要扩展机器指令或操作数表达时) - - `src/mir/MIRFunction.cpp`(当需要维护虚拟寄存器、spill 栈槽、callee-saved 等状态时) - - `src/mir/Lowering.cpp`(将当前固定寄存器写法改造为生成虚拟寄存器形式的 MIR) - - `src/mir/RegAlloc.cpp`(实现真实寄存器分配主逻辑,可选择图着色或线性扫描) - - `src/mir/FrameLowering.cpp`(根据寄存器分配结果完成栈帧布局、spill 栈槽计算与保存恢复) - - `src/mir/AsmPrinter.cpp`(保证寄存器分配后的 MIR 能正确打印为最终汇编) - - `src/mir/passes/PassManager.cpp`(组织寄存器分配后相关优化 pass 的运行顺序) - - `src/mir/passes/Peephole.cpp`(实现窥孔优化与其他局部后端优化规则) - -2. 视实现需要可能修改 - - `src/mir/MIRBasicBlock.cpp`(当需要扩展基本块级活跃性或辅助接口时) - - `src/main.cpp`(当需要调整后端阶段行为时) - - `src/utils/CLI.cpp`(当需要扩展后端调试相关命令行选项时) - - `scripts/verify_asm.sh`(当需要扩展统一验证脚本时) - -## 5. 当前最小示例实现说明 +## 3. 相关文件 + +以下文件与本实验内容相关,建议优先阅读。 + +- `include/mir/MIR.h` +- `src/mir/Lowering.cpp` +- `src/mir/RegAlloc.cpp` +- `src/mir/FrameLowering.cpp` +- `src/mir/passes/Peephole.cpp` + +## 4. 当前最小示例实现说明 当前后端中的寄存器分配与后端优化相关实现仍停留在最小示例阶段: @@ -120,14 +85,14 @@ Lab4 的目标是在 Lab3 示例基础上,把“固定寄存器 + 栈槽”的 无论采用图着色还是线性扫描,都不应把寄存器分配理解为“把虚拟寄存器简单替换成物理寄存器名字”。真正完整的实现还需要和 spill/reload、栈帧布局、callee-saved 保存恢复以及最终汇编输出联动,否则后端仍然无法支撑完整 SysY 程序。 -## 6. 构建与运行 +## 5. 构建与运行 ```bash cmake -S . -B build -DCMAKE_BUILD_TYPE=Release cmake --build build -j "$(nproc)" ``` -## 7. Lab4 验证方式 +## 6. Lab4 验证方式 项目编译后可先用当前示例用例检查后端链路是否仍能运行: diff --git a/doc/Lab5-基本标量优化.md b/doc/Lab5-基本标量优化.md index 61c1076..eef2530 100644 --- a/doc/Lab5-基本标量优化.md +++ b/doc/Lab5-基本标量优化.md @@ -109,52 +109,21 @@ use-def(或 def-use)描述的是“值在哪里被定义、又在哪里被 --- -## 5. 当前代码框架 - -1. IR 核心 - - `include/ir/IR.h` - - `src/ir/Instruction.cpp` - - `src/ir/BasicBlock.cpp` - - `src/ir/Function.cpp` - - `src/ir/Module.cpp` - - `src/ir/IRPrinter.cpp` - -2. 分析与优化 - - `src/ir/analysis/DominatorTree.cpp` - - `src/ir/analysis/LoopInfo.cpp` - - `src/ir/passes/Mem2Reg.cpp` - - `src/ir/passes/ConstFold.cpp` - - `src/ir/passes/CSE.cpp` - - `src/ir/passes/DCE.cpp` - - `src/ir/passes/CFGSimplify.cpp` - - `src/ir/passes/PassManager.cpp` - -3. 入口 - - `src/main.cpp` +## 5. 相关文件 ---- - -## 6. 需要修改的文件 - -1. 核心优化实现 - - `src/ir/passes/Mem2Reg.cpp`(建议先完成,作为后续标量优化前置) - - `src/ir/passes/ConstFold.cpp` - - `src/ir/passes/CSE.cpp` - - `src/ir/passes/DCE.cpp` - - `src/ir/passes/CFGSimplify.cpp` - - `src/ir/passes/PassManager.cpp` +以下文件与本实验内容相关,建议优先阅读。 -2. 视实现需要可能修改 - - `include/ir/IR.h`、`src/ir/Instruction.cpp`(补充副作用/可删除性信息) - - `src/ir/IRPrinter.cpp`(调试输出增强) - - `src/ir/analysis/DominatorTree.cpp`、`src/ir/analysis/LoopInfo.cpp`(辅助分析) - - `src/ir/Value.cpp`(若补充 use-def 关系) +- `include/ir/IR.h` +- `src/ir/passes/Mem2Reg.cpp` +- `src/ir/passes/ConstFold.cpp` +- `src/ir/passes/DCE.cpp` +- `src/ir/passes/PassManager.cpp` --- -## 7. 算法说明 +## 6. 算法说明 -### 7.1 Dead(无用代码删除) +### 6.1 Dead(无用代码删除) 可以采用“标记 + 清扫”思路: @@ -164,7 +133,7 @@ use-def(或 def-use)描述的是“值在哪里被定义、又在哪里被 > 本实验不限定具体思路,实现可自由设计。 -### 7.2 Clean +### 6.2 Clean 在 DCE 后对 CFG 做结构化清理,常见包括: @@ -173,7 +142,7 @@ use-def(或 def-use)描述的是“值在哪里被定义、又在哪里被 3. 线性可合并块合并 4. 不可达块删除 -### 7.3 优化顺序建议 +### 6.3 优化顺序建议 建议仅约束一条: @@ -181,7 +150,7 @@ use-def(或 def-use)描述的是“值在哪里被定义、又在哪里被 其余优化遍(如 `ConstFold`、`CSE`、`DCE`、`CFGSimplify`)的组织顺序不做硬性规定,可根据你的实现自由设计;必要时可采用迭代方式直到 IR 不再变化。 -### 7.4 公共子表达式消除(Common Subexpression Elimination) +### 6.4 公共子表达式消除(Common Subexpression Elimination) 原理: 如果同一个表达式在程序中被多次计算,并且其操作数在计算之间没有改变,则可以只计算一次,并复用计算结果。 @@ -194,14 +163,14 @@ use-def(或 def-use)描述的是“值在哪里被定义、又在哪里被 --- -## 8. 构建与验证 +## 7. 构建与验证 ```bash cmake -S . -B build -DCMAKE_BUILD_TYPE=Release cmake --build build -j "$(nproc)" ``` -### 8.1 观察 IR +### 7.1 观察 IR ```bash ./build/bin/compiler --emit-ir test/test_case/simple_add.sy @@ -209,7 +178,7 @@ cmake --build build -j "$(nproc)" 这条命令只适合先观察单个样例的 IR 形态。完成 Lab5 后,不能只检查 `simple_add`,还应覆盖 `test/test_case` 下全部测试用例。 -### 8.2 语义回归 +### 7.2 语义回归 ```bash ./scripts/verify_ir.sh test/test_case/simple_add.sy test/test_result/ir --run diff --git a/doc/Lab6-并行与循环优化.md b/doc/Lab6-并行与循环优化.md index 0aa5cee..fd2e213 100644 --- a/doc/Lab6-并行与循环优化.md +++ b/doc/Lab6-并行与循环优化.md @@ -38,36 +38,18 @@ Lab6 的目标是在 Lab5 基本标量优化之后,面向“循环密集型代 --- -## 4. 当前代码框架 +## 4. 相关文件 -1. IR 与分析 - - `include/ir/IR.h` - - `src/ir/analysis/DominatorTree.cpp` - - `src/ir/analysis/LoopInfo.cpp` +以下文件与本实验内容相关,建议优先阅读。 -2. IR 优化 - - `src/ir/passes/` - -3. 入口与验证 - - `src/main.cpp` - ---- - -## 5. 需要修改的文件 - -1. 核心文件 - - `src/ir/analysis/LoopInfo.cpp`(完善循环分析) - - `src/ir/passes/PassManager.cpp`(接入新的循环优化 pass) - - 新增循环优化 pass 文件(建议放在 `src/ir/passes/` 下) - -2. 视实现需要可能修改 - - `src/ir/analysis/DominatorTree.cpp`(若分析信息不足) - - `include/ir/IR.h`、`src/ir/Instruction.cpp`(若需要补充指令属性) - - `src/ir/IRPrinter.cpp`(调试输出增强) +- `include/ir/IR.h` +- `src/ir/analysis/DominatorTree.cpp` +- `src/ir/analysis/LoopInfo.cpp` +- `src/ir/passes/PassManager.cpp` --- -## 6. 可选优化方向 +## 5. 可选优化方向 1. 循环不变代码外提(LICM) 2. 归纳变量简化与强度削弱 @@ -78,9 +60,9 @@ Lab6 的目标是在 Lab5 基本标量优化之后,面向“循环密集型代 --- -## 7. 简要优化原理 +## 6. 简要优化原理 -### 7.1 循环不变量外提(Loop Invariant Code Motion) +### 6.1 循环不变量外提(Loop Invariant Code Motion) 原理: 将循环中“每次迭代结果都不变”的表达式移动到循环外执行。若某表达式不依赖循环内变化的值,并且其操作数在循环内不被改写,则它是循环不变量。 @@ -91,7 +73,7 @@ Lab6 的目标是在 Lab5 基本标量优化之后,面向“循环密集型代 实现思路: 先识别循环结构,再判断循环体中哪些表达式对所有迭代恒定。把这些表达式外提到循环前置块(或等价安全位置),循环体改用外提结果。 -### 7.2 强度削弱(Strength Reduction) +### 6.2 强度削弱(Strength Reduction) 原理: 将高开销运算替换为等价低开销运算。典型场景是把循环中的乘法/除法改写为增量更新(加减)。 @@ -102,7 +84,7 @@ Lab6 的目标是在 Lab5 基本标量优化之后,面向“循环密集型代 实现思路: 识别归纳变量与其线性相关表达式,判断是否可改写为递增/递减更新。引入辅助变量后,用加减替代高成本运算并保持语义一致。 -### 7.3 循环展开(Loop Unrolling) +### 6.3 循环展开(Loop Unrolling) 原理: 一次迭代中执行多份循环体副本。 @@ -113,7 +95,7 @@ Lab6 的目标是在 Lab5 基本标量优化之后,面向“循环密集型代 实现思路: 选择展开因子,复制循环体并调整步长。若总迭代次数不能整除展开因子,需要保留余数迭代处理路径以保证结果正确。 -### 7.4 循环分裂(Loop Fission) +### 6.4 循环分裂(Loop Fission) 原理: 把一个包含多类语句的循环拆成多个循环,每个循环执行原循环的一部分语句。 @@ -124,7 +106,7 @@ Lab6 的目标是在 Lab5 基本标量优化之后,面向“循环密集型代 实现思路: 先做数据依赖分析。若若干语句间不存在阻碍重排的依赖,可将其拆分到不同循环中,同时维持必要执行顺序保证语义不变。 -### 7.5 循环并行化(Loop Parallelization) +### 6.5 循环并行化(Loop Parallelization) 原理: 把循环不同迭代同时执行,以利用多核并行能力。前提是迭代间不存在破坏语义的数据依赖。 @@ -137,7 +119,7 @@ Lab6 的目标是在 Lab5 基本标量优化之后,面向“循环密集型代 --- -## 8. 推荐实验流程 +## 7. 推荐实验流程 1. 跑通循环分析。 2. 选择循环优化实现 @@ -147,14 +129,14 @@ Lab6 的目标是在 Lab5 基本标量优化之后,面向“循环密集型代 --- -## 9. 构建与验证 +## 8. 构建与验证 ```bash cmake -S . -B build -DCMAKE_BUILD_TYPE=Release cmake --build build -j "$(nproc)" ``` -### 9.1 功能回归 +### 8.1 功能回归 ```bash ./scripts/verify_ir.sh test/test_case/simple_add.sy test/test_result/ir --run @@ -165,7 +147,7 @@ cmake --build build -j "$(nproc)" 完成 Lab6 后,不能只检查 `simple_add` 这类单个样例,而应对 `test/test_case` 下全部测试用例逐个回归;如有需要,也可以自行编写批量测试脚本统一执行。 -### 9.2 优化效果对比(示例) +### 8.2 优化效果对比(示例) ```bash # 对比优化前后 IR/汇编输出(按你实现的开关或日志方式执行)