Compare commits

...

141 Commits

Author SHA1 Message Date
a1cca3c95a [midend-llvmirprint]修改i1类型不存在引入的临时寄存器保存比较结果重命名的逻辑,减少冲突的可能性 2025-08-11 19:10:11 +08:00
1361156b0d [midend-CFGOpt]修复上一次提交的漏洞 2025-08-11 18:46:07 +08:00
46179e3866 [midend-CFGOpt]修复部分指令删除逻辑错误 2025-08-11 18:40:58 +08:00
038552f58b [midend-SCCP]修复了函数参数没有正确初始化为Bottom的问题,现在f/64样例可以-O1通过 2025-08-11 16:47:03 +08:00
4d0e2d73ea [midend-LATG]将调试信息改为DEBUG生效 2025-08-10 17:32:45 +08:00
ad19a6715f [midend]删除了错误的sra指令生成逻辑 2025-08-10 16:57:40 +08:00
d1ba140657 [midend-llvnirprint]修改浮点为字面值打印,修复assign的类型推断 2025-08-10 16:12:09 +08:00
2c5e4cead1 [midend-llvmirprint]修复部分打印逻辑,修复生成IR时的基本块错误的前后驱关系链接 2025-08-10 15:19:24 +08:00
6b92020bc4 [midend-llvmirprint]修复全局数组打印格式问题 2025-08-09 22:41:32 +08:00
c867bda9b4 [midend]解决部分变量重命名问题 2025-08-09 22:30:09 +08:00
6b9ad0566d [midend-llvmirprint]修复进度(162/199),修复若干打印问题,修复若干ir生成逻辑问题 2025-08-09 21:28:44 +08:00
c507b98199 [midend-llvmprint]更新脚本,支持-eir执行IR测试 2025-08-07 23:45:26 +08:00
ba21bb3203 [midend]修复内存泄漏和Heap-buffer-overflow问题(getexternalfunction中及其隐秘的错误),修复全局常量标量访问的错误 2025-08-07 02:53:36 +08:00
8aa5ba692f [midend]初步修复内存泄漏问题(仍然剩余11处) 2025-08-07 01:34:00 +08:00
d732800149 [midend-llvmprint]更新脚本,禁用内存泄漏检查 2025-08-07 00:36:43 +08:00
37f2a01783 [midend-llvmirprint]修复了gep指令对不含维度信息的数组指针的处理逻辑,修复若干打印bug,在-s ir/ird -o <llvmir.ll file>的参数下最终会打印ir到file中,优化过程中的打印逻辑待更改。 2025-08-06 15:28:54 +08:00
5d343f42a5 [midend-llvmirprint]检查并修复了初始值的打印逻辑 2025-08-06 02:02:05 +08:00
a4406e0112 [midend]增加了指令重命名逻辑。 2025-08-06 01:31:23 +08:00
08fcda939b [midend-llvmirprint]实现了大部分函数的print方法,TODO:需要完善func和module的print方法以及重命名的逻辑 2025-08-06 01:02:11 +08:00
5f63554ca3 [midend]修正合并基本块链会将entry块纳入考虑范围的问题。上次commit同时修改了alloca创建的逻辑保证了alloca的声明全部在entry块中 2025-08-04 18:56:57 +08:00
4db3cc3fb5 Merge branch 'midend' into backend 2025-08-04 16:48:30 +08:00
17f1bed310 Merge branch 'backend-lag' into backend 2025-08-04 16:43:43 +08:00
b848ffca5a [midend]在生成IR时引进了简单的CSE(二元一元loadgep的cse) 2025-08-04 16:38:12 +08:00
603506d142 Merge branch 'backend' of gitee.com:lixuanwang/mysysy into backend 2025-08-04 16:34:22 +08:00
0179c13cf4 [backend]添加了一些工具函数 2025-08-04 16:32:54 +08:00
7e5f6800b7 [backend]修复寄存器分配算法死循环bug,89通过 2025-08-04 16:04:35 +08:00
64ba25a77e [backend]移除了冗余的keepalive伪指令 2025-08-04 14:11:27 +08:00
208d5528b5 Merge branch 'midend' into backend 2025-08-04 02:37:27 +08:00
a269366ac5 [backend]修复了较小全零全局数组未显示初始化导致未定义行为的问题 2025-08-04 02:31:18 +08:00
1b9a7a4827 [backend]修复了函数序言处理错误且与尾声栈不匹配的bug 2025-08-04 01:57:34 +08:00
b2c2f3289d [backend]修改了编译器后端 RISCv64ISel.cpp,在 kFtoI 的处理逻辑中,用一段指令序列模拟了正确的“向零取整”行为。95 h35 h37 h38通过。 2025-08-04 01:35:26 +08:00
0ecd47f0ac 修复IR打印器中浮点比较指令的类型错误,确保生成正确的LLVM IR代码 2025-08-04 01:35:26 +08:00
6550c8a25b [backend-LAG]添加新的LargeArrayToGlobal中端Pass,以及栈保护逻辑 2025-08-04 01:01:29 +08:00
f24cc7ec88 [midend]修复replaceAllUsesWith中由于setOperand 间接调用 removeUse 或 addUse导致的迭代器失效问题 2025-08-04 00:59:39 +08:00
c8a8bf9a37 [backend]修复了溢出位置错误的问题 2025-08-03 23:28:38 +08:00
446a6a6fcb [midend]修复phi指令接口,优化遍适配 2025-08-03 22:18:00 +08:00
d8b004e5e5 [midend]修改use关系相关的函数,使其能自动的正确维护,修改了phi指令的各种接口 2025-08-03 22:16:40 +08:00
cd814de495 Merge commit 'e4ad23a1a594a9da6b96655d4256352d5f6d277d' into midend 2025-08-03 18:37:36 +08:00
e4ad23a1a5 [backend]修复了寄存器分配器在处理全物理寄存器操作数时的bug 2025-08-03 18:37:08 +08:00
58c8cd53f5 Merge branch 'midend' of gitee.com:lixuanwang/mysysy into midend 2025-08-03 17:26:38 +08:00
ec91a4e259 [backend]更新脚本,现在会拷贝.sy文件到tmp目录 2025-08-03 17:26:09 +08:00
91f755959b [midend]修改中端流水线 2025-08-03 17:25:05 +08:00
92c89f7616 [midend]修正了脚本错误 2025-08-03 17:12:39 +08:00
66047dc6a3 Merge branch 'buildcfg' into midend 2025-08-03 16:40:48 +08:00
22cf18a1d6 [midend-BuildCFG]修复逻辑 2025-08-03 16:14:31 +08:00
19a433c94f [midend]为脚本添加了-O1参数,支持测试性能 2025-08-03 15:41:29 +08:00
45dfbc8d59 Merge branch 'backend' into midend 2025-08-03 15:25:51 +08:00
f8e423f579 合并backend、backend-IRC到midend 2025-08-03 15:18:52 +08:00
5b43f208ac Merge branch 'backend-divopt' into midend 2025-08-03 14:53:22 +08:00
845f969c2e [backend-IRC]修复了现场管理与溢出处理的栈偏移量错误问题 2025-08-03 14:42:19 +08:00
9c5d9ea78c [optimize]删除多余测试文件 2025-08-03 14:38:27 +08:00
0ce742a86e [optimize]添加更为通用的除法强度削减Pass, 不受除数限制替换div指令,不影响当前分数 2025-08-03 14:37:33 +08:00
f312792fe9 [optimze]添加基础的除法指令优化,目前只对除以2的幂数生效 2025-08-03 13:46:42 +08:00
32ea24df56 [midend]修复entryBB和funcBodyEntry的初始化,Dom计算引进逆后续遍历和LT算法,Pass先默认关掉CFGOpt 2025-08-03 00:51:49 +08:00
a1cf60c420 [midend-BuildCFG]新增BuildCFG优化通道,实现控制流图的构建与分析 2025-08-02 22:48:21 +08:00
f879a0f521 [midend]修复了后端不适配中端全局变量定义的问题 2025-08-02 22:06:37 +08:00
004ef82488 [backend-IRC]修复了后端不适配中端全局变量定义的问题 2025-08-02 15:10:19 +08:00
8f1d592d4e Merge branch 'midend' into backend-IRC 2025-08-02 12:47:27 +08:00
537533ee43 Merge branch 'midend' into backend-IRC 2025-08-02 12:43:18 +08:00
bfe218be07 [midend]非全0初始化数组情况下,检查0初始值个数,超过阈值(目前为16)则生成menset减少大量store操作 2025-08-02 02:33:25 +08:00
384f7c548b [backend-IRC]添加了三级调试打印逻辑 2025-08-01 23:18:53 +08:00
57fe17dc21 [backend-IRC]为虚拟寄存器与物理寄存器之间添加冲突 2025-08-01 21:20:04 +08:00
e48cddab9f [midend]修复多维数组维度信息的计算值(理论上计算结果一定是常量),TODO:修复类似问题 2025-08-01 19:19:05 +08:00
aef10b48e8 [midend]删除前驱后继移除时不存在的检查,phi增加llvm风格接口,重构CFGOpt特别是空块删除的逻辑(待验证) 2025-08-01 18:34:43 +08:00
373726b02f [backend-IRC]修复了极其隐蔽的寄存器分配问题 2025-08-01 17:29:18 +08:00
a0b69f20fb [midend]合并了SCCP和backend,修复了支配树的错误求解,修复了Mem2Reg的重命名alloca的栈管理 2025-08-01 15:18:33 +08:00
999f2c6615 Merge remote-tracking branch 'origin/backend' into midend 2025-08-01 14:06:20 +08:00
1eedb55ca0 Merge branch 'midend-SCCP' into midend 2025-08-01 14:02:14 +08:00
8fe9867f33 [backend-IRC]修复了keepalive伪指令处理缺失的问题 2025-08-01 12:15:03 +08:00
166d0fc372 [backend-IRC]修复了栈传递参数逻辑 2025-08-01 05:21:37 +08:00
873dbf64d0 [backend-IRC]基本构建了IRC 2025-08-01 04:44:13 +08:00
f387aecc03 [backend-IRC]进一步构建寄存器分配逻辑 2025-08-01 02:47:40 +08:00
c268191826 [midend-SCCP]修改BaiscBlock的析构逻辑,将CFG修改的职责交给优化遍,注释Mem2Reg的调试信息。 2025-08-01 01:44:33 +08:00
03e88eee70 [backend-IRC]初步构建新的寄存器分配器 2025-07-31 23:02:53 +08:00
0f1fcc835d [midend-SCCP]删除User的析构函数,usedelete增加逻辑通知inst所使用的value移除对应的use关系(一般在这之前会替换使用inst的uses为其他值),TODO:仍然存在bug需要调试 2025-07-31 22:32:04 +08:00
c5af4f1c49 [midend-SCCP]bug修复,增加不可达指令(理论来说后端不会出现这条指令,只是为了IR完整性添加),添加相关方法,phi指令方法修复;目前能够跑完所有优化,但是User的析构函数重定义导致全局析构不能正确完成,需要修复 2025-07-31 22:03:35 +08:00
9a53e1b917 [midend]适应上一次commit修改已有优化遍中相关指令删除的代码 2025-07-31 21:10:59 +08:00
ef09bc70d4 [midend]修改了removeinst方法,应对不同的使用情况,增加user析构函数使得user对象销毁顺带销毁其use关系销毁,重构usedelete方法封装指令删除和use关系删除 2025-07-31 21:10:20 +08:00
aed4577490 [midend]同上,删除了打印函数对维度信息的错误访问 2025-07-31 19:57:19 +08:00
35b421b60b [midend]修改原因同上一次commit 2025-07-31 19:38:43 +08:00
f3f603a032 [midend]消除冗余维度信息记录,适配IR生成器,TODO:其他优化遍生成指令修改,或者后端的访问 2025-07-31 19:36:39 +08:00
de0f8422e9 [midend-SCCP]没有编译报错但是Segmemtation falut 2025-07-31 17:29:34 +08:00
35691ab7bc [midend-SCCP]为跳转指令增加getSuccessors方法 2025-07-31 17:19:57 +08:00
61768fa180 [midend-SCCP]头文件构架完毕,cpp文件部分报错暂时不commit 2025-07-31 17:00:02 +08:00
520ebd96f0 [midend-SCCP]增加不可达指令,修改跳转指令参数(基本块args已弃用默认为{}) 2025-07-31 16:59:22 +08:00
6868f638d7 [midend-SCCP]增加基本块对的哈希值计算方法,增加删除use关系和指令的函数 2025-07-31 16:57:47 +08:00
e8699d6d25 [backend]更新脚本和库以支持性能测试用例 2025-07-31 16:42:41 +08:00
0727d5a6d8 Merge commit 'fc7afdbb359e71e799ea50ac71ac21ce233aeaac' into backend 2025-07-31 15:01:06 +08:00
fc7afdbb35 [midend]修复错误的RelExp类型转换 2025-07-31 13:55:59 +08:00
bfe2b248cd Merge branch 'backend-float' into backend 2025-07-31 12:16:11 +08:00
6d60522ce2 Merge branch 'midend' into backend-float 2025-07-31 12:14:38 +08:00
807fb3f560 [backend]微优化与可读性维护不影响原逻辑和分数 2025-07-31 11:23:17 +08:00
82288464c3 [midend]修复常量变量的声明逻辑同变量声明,重构表达式生成逻辑(将中缀表达式转换为后缀表达式判断类型提升后再进行统一类型转换和计算)。运行脚本通过率[117/140]。 2025-07-31 02:47:39 +08:00
7e8b90ffd4 [midend]修改全局变量,全局常量类,提供维度访问方法,消除维度信息(记录在Type中),createItoFInst命名修复,增加打印全局常量。 2025-07-31 02:45:40 +08:00
b3cf3cba29 [backend]修复了多参数传递的错误 2025-07-30 22:16:37 +08:00
03b62b138f [backend]修复了一个栈管理问题 2025-07-30 20:40:56 +08:00
8e94f89931 Merge branch 'midend' into backend 2025-07-30 18:27:42 +08:00
b388dc4542 Merge branch 'backend-float' into backend 2025-07-30 18:26:06 +08:00
48b0aec6c3 [midend][backend]修复了全局常量数组的访问错误 2025-07-30 18:23:56 +08:00
1fb5cd398d [backend]修复了多参数传递的问题 2025-07-30 17:58:39 +08:00
206a0af424 [midend-SCCP]暂存1 2025-07-30 16:33:56 +08:00
877a0f5dc2 [backend-float]修复部分问题 2025-07-30 16:00:02 +08:00
a3c4d5a2b8 [Optimize]对PreRA指令调度进行优化 2025-07-30 15:27:23 +08:00
39c13c46ec Merge branch 'midend' into backend-float 2025-07-30 15:10:38 +08:00
dd38bdc133 [backend]引入浮点数支持,但目前寄存器分配存在问题 2025-07-30 15:07:29 +08:00
38bee5d5ac [midend]IRPrinter增加了打印全局常量的功能 2025-07-30 14:46:28 +08:00
98511efd91 [midend]修改constdecl的逻辑区分局部常量和全局常量声明逻辑,提供方法访问全局变量,常量的维度信息,修改GlobalValue,ConstantVariable的继承父类(User->Value)维度信息保存在Type中。 2025-07-30 14:40:10 +08:00
507096a0f6 Merge branch 'midend' of gitee.com:lixuanwang/mysysy into midend 2025-07-30 11:31:46 +08:00
7f2e501cea [backend]修复了指令选择不支持ConstantVariable操作数的bug 2025-07-30 11:31:37 +08:00
860ebcd447 [Optimize]对PostRA指令调度进行容器/算法/缓存优化 2025-07-30 10:28:06 +08:00
31b6711d74 [midend]IR修改常量类getint和getfloat逻辑,如果类型和方法不一致那么应用强制转换返回转换后的值 2025-07-29 23:52:37 +08:00
42dce9820b Merge branch 'midend' into backend 2025-07-29 21:31:04 +08:00
09ae47924e [midend]重构了src目录 2025-07-29 21:30:30 +08:00
f5922d0178 [midend]修改类型转换判断的逻辑 2025-07-29 20:23:25 +08:00
63906d0648 [midend]修复82样例生成IR的错误(未正确初始化全局数组常量和数组常量的Type计算) 2025-07-29 19:35:39 +08:00
6ba05e0d8c [PreRA_Scheduler]添加寄存器分配前的指令调度优化 2025-07-29 17:00:27 +08:00
e4fd16e36a Merge branch 'backend' into midend 2025-07-29 16:37:11 +08:00
32bdc17dc3 [backend]调整了后端pass的顺序 2025-07-29 16:15:01 +08:00
8deb4ed076 [backend]添加了2个新的pass,用于解决大立即数加载问题 2025-07-29 15:48:37 +08:00
37e99e37a3 Merge branch 'midend-mem2reg' into midend 2025-07-29 15:48:34 +08:00
8e69992b29 [midend-mem2reg]增加说明 2025-07-29 15:47:51 +08:00
15fe69187a [midend-mem2reg]目前reg2mem仅将函数参数和phi指令及其对应指令进行reg2mem,旨在消除phi指令。 2025-07-29 15:30:28 +08:00
fff19ca1ea [midend-mem2reg]Reg2Mem建立完成runit测试127/140,reg2mem基本思路:函数参数默认降级到内存,有结果的指令被降级的内存 2025-07-29 14:34:16 +08:00
4a329eeaf2 [midend]修复return指令exp为空的判断条件错误 2025-07-29 12:16:46 +08:00
3dc4b28c92 [midend-mem2reg]dom增加访问支配树子节点求解和访问方法,修复block打印,phi指令命名,TODO:reg2membug待修复 2025-07-29 03:25:56 +08:00
202e6d7cd8 [midend-mem2reg]增加遍打印方法,修复reg2mem构造函数错误 2025-07-29 02:11:10 +08:00
3e4cac089e [midend-reg2mem]增加reg2mem遍,应用未定义值,增加inst迭代器查找方法,通过编译且脚本运行通过率不变 2025-07-29 02:01:48 +08:00
76d7b14b2e [backend]更新了测试脚本,现在的测试更准确 2025-07-29 01:04:43 +08:00
9ba08126fb Merge branch 'peephole' into backend 2025-07-28 23:46:34 +08:00
875100ec01 [backend]为单次运行脚本添加了clean参数 2025-07-28 23:41:36 +08:00
b0cecca081 Merge branch 'backend-rec' into backend 2025-07-28 23:40:58 +08:00
434bcea98e [PostRA_Scheduler]修复了超大测例卡死的bug 2025-07-28 23:17:26 +08:00
da5c2bb41d [PostRA_Scheduler]完成寄存器分配后的指令调度优化 2025-07-28 22:35:29 +08:00
fcc3806342 Merge branch 'backend-bss' into backend 2025-07-28 17:31:47 +08:00
792dc9c1f6 Merge branch 'backend-bss' into backend-rec 2025-07-28 17:31:23 +08:00
535a935bf1 [midend-mem2reg]暂存文件,思路留存 2025-07-28 14:57:15 +08:00
efe74cba6c [midend-mem2reg]mem2reg遍基本写完,编译不报错,待reg2mem写完统一测试 2025-07-28 14:28:46 +08:00
634a84f29c [peephole]Pass架构重构优化 2025-07-27 11:03:26 +08:00
2e8b564d8f [backend]修复了递归函数的调用问题,引入了新的bug? 2025-07-27 01:07:08 +08:00
2dd6a17fca [backend]saving1 2025-07-27 00:34:45 +08:00
78dee0d72a [peephole]添加7项窥孔优化规则初步测试生效成功,有待进一步检查,TODO: 指令调度优化 2025-07-26 21:48:14 +08:00
292 changed files with 625851 additions and 7456 deletions

1
.gitignore vendored
View File

@ -36,6 +36,7 @@ doxygen
!/testdata/functional/*.out
!/testdata/h_functional/*.out
!/testdata/performance/*.out
build/
.antlr
.vscode/

View File

@ -3,4 +3,244 @@
| 名称 | 优化级别 | 开发进度 |
| ------------ | ------------ | ---------- |
| CFG优化 | 函数级 | 已完成 |
| DCE | 函数级 | 待测试 |
| DCE | 函数级 | 待正确性测试 |
| Mem2Reg | 函数级 | 待正确性测试 |
| Reg2Mem | 函数级 | 待正确性测试 |
# 部分优化遍的说明
## Mem2Reg
Mem2Reg 遍的主要目标是将那些不必要的、只用于局部标量变量的内存分配 (alloca 指令) 消除,并将这些变量的值转换为 SSA 形式。这有助于减少内存访问,提高代码效率,并为后续的优化创造更好的条件。
通过Mem2Reg理解删除指令时对use关系的维护
`Mem2Reg` 优化遍中,当 `load``store` 指令被删除时,其 `use` 关系(即它们作为操作数与其他 `Value` 对象之间的连接)的正确消除是一个关键问题,尤其涉及到 `AllocaInst`
结合您提供的 `Mem2RegContext::renameVariables` 代码和我们之前讨论的 `usedelete` 逻辑,下面是 `use` 关系如何被正确消除的详细过程:
### 问题回顾:`Use` 关系的双向性
在您的 IR 设计中,`Use` 对象扮演着连接 `User`(使用者,如 `LoadInst`)和 `Value`(被使用者,如 `AllocaInst`)的双向角色:
* 一个 `User` 持有对其操作数 `Value``Use` 对象(通过 `User::operands` 列表)。
* 一个 `Value` 持有所有使用它的 `User``Use` 对象(通过 `Value::uses` 列表)。
原始问题是:当一个 `LoadInst``StoreInst` 被删除时,如果不对其作为操作数与 `AllocaInst` 之间的 `Use` 关系进行明确清理,`AllocaInst``uses` 列表中就会留下指向已删除 `LoadInst` / `StoreInst``Use` 对象,导致内部的 `User*` 指针悬空,在后续访问时引发 `segmentation fault`
### `Mem2Reg` 中 `load`/`store` 指令的删除行为
`Mem2RegContext::renameVariables` 函数中,`load``store` 指令被处理时,其行为如下:
1. **处理 `LoadInst`**
当找到一个指向可提升 `AllocaInst``LoadInst` 时,其用途会被 `replaceAllUsesWith(allocaToValueStackMap[alloca].top())` 替换。这意味着任何原本使用 `LoadInst` 本身计算结果的指令,现在都直接使用 SSA 值栈顶部的 `Value`
**重点:** 这一步处理的是 `LoadInst` 作为**被使用的值 (Value)** 时,其 `uses` 列表的清理。即,将 `LoadInst` 的所有使用者重定向到新的 SSA 值,并把这些 `Use` 对象从 `LoadInst``uses` 列表中移除。
2. **处理 `StoreInst`**
当找到一个指向可提升 `AllocaInst``StoreInst` 时,`StoreInst` 存储的值会被压入值栈。`StoreInst` 本身并不产生可被其他指令直接使用的值(其类型是 `void`),所以它没有 `uses` 列表需要替换。
**重点:** `StoreInst` 的主要作用是更新内存状态,在 SSA 形式下,它被移除后需要清理它作为**使用者 (User)** 时的操作数关系。
在这两种情况下,一旦 `load``store` 指令的 SSA 转换完成,它们都会通过 `instIter = SysYIROptUtils::usedelete(instIter)` 被显式删除。
### `SysYIROptUtils::usedelete` 如何正确消除 `Use` 关系
关键在于对 `SysYIROptUtils::usedelete` 函数的修改,使其在删除指令时,同时处理该指令作为 `User``Value` 的两种 `Use` 关系:
1. **清理指令作为 `Value` 时的 `uses` 列表 (由 `replaceAllUsesWith` 完成)**
`usedelete` 函数中,`inst->replaceAllUsesWith(UndefinedValue::get(inst->getType()))` 的调用至关重要。这确保了:
* 如果被删除的 `Instruction`(例如 `LoadInst`)产生了结果值并被其他指令使用,所有这些使用者都会被重定向到 `UndefinedValue`(或者 `Mem2Reg` 中具体的 SSA 值)。
* 这个过程会遍历 `LoadInst``uses` 列表,并将这些 `Use` 对象从 `LoadInst``uses` 列表中移除。这意味着 `LoadInst` 自己不再被任何其他指令使用。
2. **清理指令作为 `User` 时其操作数的 `uses` 列表 (由 `RemoveUserOperandUses` 完成)**
这是您提出的、并已集成到 `usedelete` 中的关键改进点。对于一个被删除的 `Instruction`(它同时也是 `User`),我们需要清理它**自己使用的操作数**所维护的 `use` 关系。
* 例如,`LoadInst %op1` 使用了 `%op1`(一个 `AllocaInst`)。当 `LoadInst` 被删除时,`AllocaInst``uses` 列表中有一个 `Use` 对象指向这个 `LoadInst`
* `RemoveUserOperandUses` 函数会遍历被删除 `User`(即 `LoadInst``StoreInst`)的 `operands` 列表。
* 对于 `operands` 列表中的每个 `std::shared_ptr<Use> use_ptr`,它会获取 `Use` 对象内部指向的 `Value`(例如 `AllocaInst*`),然后调用 `value->removeUse(use_ptr)`
* 这个 `removeUse` 调用会负责将 `use_ptr``AllocaInst``uses` 列表中删除。
### 总结
通过在 `SysYIROptUtils::usedelete` 中同时执行这两个步骤:
* `replaceAllUsesWith`:处理被删除指令**作为结果被使用**时的 `use` 关系。
* `RemoveUserOperandUses`:处理被删除指令**作为使用者User其操作数**的 `use` 关系。
这就确保了当 `Mem2Reg` 遍历并删除 `load``store` 指令时,无论是它们作为 `Value` 的使用者,还是它们作为 `User` 的操作数,所有相关的 `Use` 对象都能被正确地从 `Value``uses` 列表中移除,从而避免了悬空指针和后续的 `segmentation fault`
最后,当所有指向某个 `AllocaInst``load``store` 指令都被移除后,`AllocaInst``uses` 列表将变得干净(只包含 Phi 指令,如果它们在 SSA 转换中需要保留 Alloca 作为操作数),这时在 `Mem2RegContext::cleanup()` 阶段,`SysYIROptUtils::usedelete(alloca)` 就可以安全地删除 `AllocaInst` 本身了。
## Reg2Mem
我们的Reg2Mem 遍的主要目标是作为 Mem2Reg 的一种逆操作,但更具体是解决后端无法识别 PhiInst 指令的问题。主要的速录是将函数参数和 PhiInst 指令的结果从 SSA 形式转换回内存形式,通过插入 alloca、load 和 store 指令来实现。其他非 Phi 的指令结果将保持 SSA 形式。
## SCCP
SCCP稀疏条件常量传播是一种编译器优化技术它结合了常量传播和死代码消除。其核心思想是在程序执行过程中尝试识别并替换那些在编译时就能确定其值的变量常量同时移除那些永远不会被执行到的代码块不可达代码
以下是 SCCP 的实现思路:
1. 核心数据结构与工作列表:
Lattice 值Lattice Value: SCCP 使用三值格Three-Valued Lattice来表示变量的状态
Top (T): 初始状态,表示变量的值未知,但可能是一个常量。
Constant (C): 表示变量的值已经确定为一个具体的常量。
Bottom (⊥): 表示变量的值不确定或不是一个常量(例如,它可能在运行时有多个不同的值,或者从内存中加载)。一旦变量状态变为 Bottom它就不能再变回 Constant 或 Top。
SSAPValue: 封装了 Lattice 值和常量具体值(如果状态是 Constant
*valState (map<Value, SSAPValue>):** 存储程序中每个 Value变量、指令结果等的当前 SCCP Lattice 状态。
*ExecutableBlocks (set<BasicBlock>):** 存储在分析过程中被确定为可执行的基本块。
工作列表 (Worklists):
cfgWorkList (queue<pair<BasicBlock, BasicBlock>>):** 存储待处理的控制流图CFG边。当一个块被标记为可执行时它的后继边会被添加到这个列表。
*ssaWorkList (queue<Instruction>):** 存储待处理的 SSA (Static Single Assignment) 指令。当一个指令的任何操作数的状态发生变化时,该指令就会被添加到这个列表,需要重新评估。
2. 初始化:
所有 Value 的状态都被初始化为 Top。
所有基本块都被初始化为不可执行。
函数的入口基本块被标记为可执行,并且该块中的所有指令被添加到 ssaWorkList。
3. 迭代过程 (Fixed-Point Iteration)
SCCP 的核心是一个迭代过程,它交替处理 CFG 工作列表和 SSA 工作列表,直到达到一个不动点(即没有更多的状态变化)。
处理 cfgWorkList:
从 cfgWorkList 中取出一个边 (prev, next)。
如果 next 块之前是不可执行的,现在通过 prev 块可达,则将其标记为可执行 (markBlockExecutable)。
一旦 next 块变为可执行,其内部的所有指令(特别是 Phi 指令)都需要被重新评估,因此将它们添加到 ssaWorkList。
处理 ssaWorkList:
从 ssaWorkList 中取出一个指令 inst。
重要: 只有当 inst 所在的块是可执行的,才处理该指令。不可执行块中的指令不参与常量传播。
计算新的 Lattice 值 (computeLatticeValue): 根据指令类型和其操作数的当前 Lattice 状态,计算 inst 的新的 Lattice 状态。
常量折叠: 如果所有操作数都是常量,则可以直接执行运算并得到一个新的常量结果。
Bottom 传播: 如果任何操作数是 Bottom或者运算规则导致不确定例如除以零则结果为 Bottom。
Phi 指令的特殊处理: Phi 指令的值取决于其所有可执行的前驱块传入的值。
如果所有可执行前驱都提供了相同的常量 C则 Phi 结果为 C。
如果有任何可执行前驱提供了 Bottom或者不同的可执行前驱提供了不同的常量则 Phi 结果为 Bottom。
如果所有可执行前驱都提供了 Top则 Phi 结果仍为 Top。
更新状态: 如果 inst 的新计算出的 Lattice 值与它当前存储的值不同,则更新 valState[inst]。
传播变化: 如果 inst 的状态发生变化,那么所有使用 inst 作为操作数的指令都可能受到影响,需要重新评估。因此,将 inst 的所有使用者添加到 ssaWorkList。
处理终结符指令 (BranchInst, ReturnInst):
对于条件分支 BranchInst如果其条件操作数变为常量
如果条件为真,则只有真分支的目标块是可达的,将该边添加到 cfgWorkList。
如果条件为假,则只有假分支的目标块是可达的,将该边添加到 cfgWorkList。
如果条件不是常量Top 或 Bottom则两个分支都可能被执行将两边的边都添加到 cfgWorkList。
这会影响 CFG 的可达性分析,可能导致新的块被标记为可执行。
4. 应用优化 (Transformation)
当两个工作列表都为空,达到不动点后,程序代码开始进行实际的修改:
常量替换:
遍历所有指令。如果指令的 valState 为 Constant则用相应的 ConstantValue 替换该指令的所有用途 (replaceAllUsesWith)。
将该指令标记为待删除。
对于指令的操作数,如果其 valState 为 Constant则直接将操作数替换为对应的 ConstantValue常量折叠
删除死指令: 遍历所有标记为待删除的指令,并从其父基本块中删除它们。
删除不可达基本块: 遍历函数中的所有基本块。如果一个基本块没有被标记为可执行 (ExecutableBlocks 中不存在),则将其从函数中删除。但入口块不能删除。
简化分支指令:
遍历所有可执行的基本块的终结符指令。
对于条件分支 BranchInst如果其条件操作数在 valState 中是 Constant
如果条件为真,则将该条件分支替换为一个无条件跳转到真分支目标块的指令。
如果条件为假,则将该条件分支替换为一个无条件跳转到假分支目标块的指令。
更新 CFG移除不可达的分支边和其前驱信息。
computeLatticeValue 的具体逻辑:
这个函数是 SCCP 的核心逻辑,它定义了如何根据指令类型和操作数的当前 Lattice 状态来计算指令结果的 Lattice 状态。
二元运算 (Add, Sub, Mul, Div, Rem, ICmp, And, Or):
如果任何一个操作数是 Bottom结果就是 Bottom。
如果任何一个操作数是 Top结果就是 Top。
如果两个操作数都是 Constant执行实际的常量运算结果是一个新的 Constant。
一元运算 (Neg, Not):
如果操作数是 Bottom结果就是 Bottom。
如果操作数是 Top结果就是 Top。
如果操作数是 Constant执行实际的常量运算结果是一个新的 Constant。
Load 指令: 通常情况下Load 的结果会被标记为 Bottom因为内存内容通常在编译时无法确定。但如果加载的是已知的全局常量可能可以确定。在提供的代码中它通常返回 Bottom。
Store 指令: Store 不产生值,所以其 SSAPValue 保持 Top 或不关心。
Call 指令: 大多数 Call 指令(尤其是对外部或有副作用的函数)的结果都是 Bottom。对于纯函数如果所有参数都是常量理论上可以折叠但这需要额外的分析。
GetElementPtr (GEP) 指令: GEP 计算内存地址。如果所有索引都是常量,地址本身是常量。但 SCCP 关注的是数据值,因此这里通常返回 Bottom除非有特定的指针常量跟踪。
Phi 指令: 如上所述,基于所有可执行前驱的传入值进行聚合。
Alloc 指令: Alloc 分配内存,返回一个指针。其内容通常是 Bottom。
Branch 和 Return 指令: 这些是终结符指令,不产生一个可用于其他指令的值,通常 SSAPValue 保持 Top 或不关心。
类型转换 (ZExt, SExt, Trunc, FtoI, ItoF): 如果操作数是 Constant则执行相应的类型转换结果仍为 Constant。对于浮点数转换由于 SSAPValue 的 constantVal 为 int 类型,所以对浮点数的操作会保守地返回 Bottom。
未处理的指令: 默认情况下,任何未明确处理的指令都被保守地假定为产生 Bottom 值。
浮点数处理的注意事项:
在提供的代码中SSAPValue 的 constantVal 是 int 类型。这使得浮点数常量传播变得复杂。对于浮点数相关的指令kFAdd, kFMul, kFCmp, kFNeg, kFNot, kItoF, kFtoI 等),如果不能将浮点值准确地存储在 int 中,或者不能可靠地执行浮点运算,那么通常会保守地将结果设置为 Bottom。一个更完善的 SCCP 实现会使用 std::variant<int, float> 或独立的浮点常量存储来处理浮点数。
# 后续优化可能涉及的改动
## 1将所有的alloca集中到entryblock中
好处优化友好性方便mem2reg提升
目前没有实现这个机制,如果想要实现首先解决同一函数不同域的同名变量命名区分
需要保证符号表能正确维护域中的局部变量
# 关于中端优化提升编译器性能的TODO
## usedelete_withinstdelte方法
这个方法删除了use关系并移除了指令逻辑是根据Instruction* inst去find对应的迭代器并erase
有些情况下外部持有迭代器和inst,可以省略find过程

Binary file not shown.

View File

@ -14,6 +14,7 @@ TESTDATA_DIR="${SCRIPT_DIR}/testdata" # 用于查找 .in/.out 文件
GCC_NATIVE="gcc" # VM 内部的原生 gcc
# --- 初始化变量 ---
CLEAN_MODE=false
GCC_TIMEOUT=10 # gcc 编译超时 (秒)
EXEC_TIMEOUT=5 # 程序自动化执行超时 (秒)
MAX_OUTPUT_LINES=50 # 对比失败时显示的最大行数
@ -29,6 +30,7 @@ show_help() {
echo "如果找到对应的 .in/.out 文件,则进行自动化测试。否则,进入交互模式。"
echo ""
echo "选项:"
echo " -c, --clean 清理 tmp 临时目录下的所有文件。"
echo " -ct N 设置 gcc 编译超时为 N 秒 (默认: 10)。"
echo " -t N 设置程序自动化执行超时为 N 秒 (默认: 5)。"
echo " -ml N, --max-lines N 当输出对比失败时,最多显示 N 行内容 (默认: 50)。"
@ -57,10 +59,24 @@ display_file_content() {
fi
}
# --- 新增功能: 清理临时文件的函数 ---
clean_tmp() {
echo "正在清理临时目录: ${TMP_DIR}"
if [ -d "${TMP_DIR}" ]; then
rm -rf "${TMP_DIR}"/* 2>/dev/null
echo "清理完成。"
else
echo "临时目录 ${TMP_DIR} 不存在,无需清理。"
fi
}
# --- 参数解析 ---
# 从参数中分离出 .s 文件和选项
for arg in "$@"; do
case "$arg" in
-c|--clean)
CLEAN_MODE=true
;;
-ct|-t|-ml|--max-lines)
# 选项和其值将在下一个循环中处理
;;
@ -74,6 +90,7 @@ for arg in "$@"; do
args_processed=true # 标记已处理过参数
while [[ "$#" -gt 0 ]]; do
case "$1" in
-c|--clean) ;; # 已在外部处理
-ct) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then GCC_TIMEOUT="$2"; shift; else echo "错误: -ct 需要一个正整数参数。" >&2; exit 1; fi ;;
-t) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then EXEC_TIMEOUT="$2"; shift; else echo "错误: -t 需要一个正整数参数。" >&2; exit 1; fi ;;
-ml|--max-lines) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then MAX_OUTPUT_LINES="$2"; shift; else echo "错误: --max-lines 需要一个正整数参数。" >&2; exit 1; fi ;;
@ -95,6 +112,14 @@ for arg in "$@"; do
done
# --- 主逻辑开始 ---
if ${CLEAN_MODE}; then
clean_tmp
# 如果只提供了 -c 选项,则退出
if [ ${#S_FILES[@]} -eq 0 ]; then
exit 0
fi
fi
if [ ${#S_FILES[@]} -eq 0 ]; then
echo "错误: 未提供任何 .s 文件作为输入。"
show_help
@ -162,14 +187,17 @@ for s_file in "${S_FILES[@]}"; do
EXPECTED_STDOUT_FILE="${TMP_DIR}/${base_name_from_s_file}.expected_stdout"
head -n -1 "${output_reference_file}" > "${EXPECTED_STDOUT_FILE}"
if [ "$ACTUAL_RETURN_CODE" -ne "$EXPECTED_RETURN_CODE" ]; then echo -e "\e[31m 返回码测试失败: 期望 ${EXPECTED_RETURN_CODE}, 实际 ${ACTUAL_RETURN_CODE}\e[0m"; is_passed=0; fi
if ! diff -q <(sed ':a;N;$!ba;s/\n*$//' "${output_actual_file}") <(sed ':a;N;$!ba;s/\n*$//' "${EXPECTED_STDOUT_FILE}") >/dev/null 2>&1; then
# --- 本次修改点: 使用 tr 删除所有空白字符后再比较 ---
if ! diff -q <(tr -d '[:space:]' < "${output_actual_file}") <(tr -d '[:space:]' < "${EXPECTED_STDOUT_FILE}") >/dev/null 2>&1; then
echo -e "\e[31m 标准输出测试失败。\e[0m"; is_passed=0
display_file_content "${EXPECTED_STDOUT_FILE}" " \e[36m--- 期望输出 ---\e[0m" "${MAX_OUTPUT_LINES}"
display_file_content "${output_actual_file}" " \e[36m--- 实际输出 ---\e[0m" "${MAX_OUTPUT_LINES}"
echo -e " \e[36m----------------\e[0m"
fi
else
if ! diff -q <(sed ':a;N;$!ba;s/\n*$//' "${output_actual_file}") <(sed ':a;N;$!ba;s/\n*$//' "${output_reference_file}") >/dev/null 2>&1; then
# --- 本次修改点: 使用 tr 删除所有空白字符后再比较 ---
if diff -q <(tr -d '[:space:]' < "${output_actual_file}") <(tr -d '[:space:]' < "${output_reference_file}") >/dev/null 2>&1; then
echo -e "\e[32m 标准输出测试成功。\e[0m"
else
echo -e "\e[31m 标准输出测试失败。\e[0m"; is_passed=0

View File

@ -60,11 +60,7 @@ display_file_content() {
# 清理临时文件的函数
clean_tmp() {
echo "正在清理临时目录: ${TMP_DIR}"
rm -rf "${TMP_DIR}"/*.s \
"${TMP_DIR}"/*_sysyc_riscv64 \
"${TMP_DIR}"/*_sysyc_riscv64.actual_out \
"${TMP_DIR}"/*_sysyc_riscv64.expected_stdout \
"${TMP_DIR}"/*_sysyc_riscv64.o
rm -rf "${TMP_DIR}"/*
echo "清理完成。"
}
@ -175,7 +171,8 @@ while IFS= read -r s_file; do
is_passed=0
fi
if ! diff -q <(sed ':a;N;$!ba;s/\n*$//' "${output_actual_file}") <(sed ':a;N;$!ba;s/\n*$//' "${EXPECTED_STDOUT_FILE}") >/dev/null 2>&1; then
# --- 本次修改点: 使用 tr 删除所有空白字符后再比较 ---
if ! diff -q <(tr -d '[:space:]' < "${output_actual_file}") <(tr -d '[:space:]' < "${EXPECTED_STDOUT_FILE}") >/dev/null 2>&1; then
echo -e "\e[31m 标准输出测试失败\e[0m"
is_passed=0
display_file_content "${EXPECTED_STDOUT_FILE}" " \e[36m---------- 期望输出 ----------\e[0m" "${MAX_OUTPUT_LINES}"
@ -186,7 +183,9 @@ while IFS= read -r s_file; do
if [ $ACTUAL_RETURN_CODE -ne 0 ]; then
echo -e "\e[33m警告: 程序以非零状态 ${ACTUAL_RETURN_CODE} 退出 (纯输出比较模式)。\e[0m"
fi
if ! diff -q <(sed ':a;N;$!ba;s/\n*$//' "${output_actual_file}") <(sed ':a;N;$!ba;s/\n*$//' "${output_reference_file}") >/dev/null 2>&1; then
# --- 本次修改点: 使用 tr 删除所有空白字符后再比较 ---
if diff -q <(tr -d '[:space:]' < "${output_actual_file}") <(tr -d '[:space:]' < "${output_reference_file}") >/dev/null 2>&1; then
echo -e "\e[32m 成功: 输出与参考输出匹配\e[0m"
else
echo -e "\e[31m 失败: 输出不匹配\e[0m"

304
script/runit-single.sh Normal file
View File

@ -0,0 +1,304 @@
#!/bin/bash
# runit-single.sh - 用于编译和测试单个或少量 SysY 程序的脚本
# 模仿 runit.sh 的功能,但以具体文件路径作为输入。
# 此脚本应该位于 mysysy/script/
export ASAN_OPTIONS=detect_leaks=0
# --- 配置区 ---
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
BUILD_BIN_DIR="${SCRIPT_DIR}/../build/bin"
LIB_DIR="${SCRIPT_DIR}/../lib"
TMP_DIR="${SCRIPT_DIR}/tmp"
# 定义编译器和模拟器
SYSYC="${BUILD_BIN_DIR}/sysyc"
LLC_CMD="llc-19" # 新增
GCC_RISCV64="riscv64-linux-gnu-gcc"
QEMU_RISCV64="qemu-riscv64"
# --- 初始化变量 ---
EXECUTE_MODE=false
IR_EXECUTE_MODE=false # 新增
CLEAN_MODE=false
OPTIMIZE_FLAG=""
SYSYC_TIMEOUT=30
LLC_TIMEOUT=10 # 新增
GCC_TIMEOUT=10
EXEC_TIMEOUT=30
MAX_OUTPUT_LINES=20
SY_FILES=()
PASSED_CASES=0
FAILED_CASES_LIST=""
INTERRUPTED=false # 新增
# =================================================================
# --- 函数定义 ---
# =================================================================
show_help() {
echo "用法: $0 [文件1.sy] [文件2.sy] ... [选项]"
echo "编译并测试指定的 .sy 文件。必须提供 -e 或 -eir 之一。"
echo ""
echo "选项:"
echo " -e 通过汇编运行测试 (sysyc -> gcc -> qemu)。"
echo " -eir 通过IR运行测试 (sysyc -> llc -> gcc -> qemu)。"
echo " -c, --clean 清理 tmp 临时目录下的所有文件。"
echo " -O1 启用 sysyc 的 -O1 优化。"
echo " -sct N 设置 sysyc 编译超时为 N 秒 (默认: 30)。"
echo " -lct N 设置 llc-19 编译超时为 N 秒 (默认: 10)。"
echo " -gct N 设置 gcc 交叉编译超时为 N 秒 (默认: 10)。"
echo " -et N 设置 qemu 自动化执行超时为 N 秒 (默认: 30)。"
echo " -ml N, --max-lines N 当输出对比失败时,最多显示 N 行内容 (默认: 20)。"
echo " -h, --help 显示此帮助信息并退出。"
echo ""
echo "可在任何时候按 Ctrl+C 来中断测试并显示当前已完成的测例总结。"
}
display_file_content() {
local file_path="$1"
local title="$2"
local max_lines="$3"
if [ ! -f "$file_path" ]; then return; fi
echo -e "$title"
local line_count
line_count=$(wc -l < "$file_path")
if [ "$line_count" -gt "$max_lines" ]; then
head -n "$max_lines" "$file_path"
echo -e "\e[33m[... 输出已截断,共 ${line_count} 行 ...]\e[0m"
else
cat "$file_path"
fi
}
# --- 新增:总结报告函数 ---
print_summary() {
local total_cases=${#SY_FILES[@]}
echo ""
echo "======================================================================"
if [ "$INTERRUPTED" = true ]; then
echo -e "\e[33m测试被中断。正在汇总已完成的结果...\e[0m"
else
echo "所有测试完成"
fi
local failed_count
if [ -n "$FAILED_CASES_LIST" ]; then
failed_count=$(echo -e -n "${FAILED_CASES_LIST}" | wc -l)
else
failed_count=0
fi
local executed_count=$((PASSED_CASES + failed_count))
echo "测试结果: [通过: ${PASSED_CASES}, 失败: ${failed_count}, 已执行: ${executed_count}/${total_cases}]"
if [ -n "$FAILED_CASES_LIST" ]; then
echo ""
echo -e "\e[31m未通过的测例:\e[0m"
printf "%b" "${FAILED_CASES_LIST}"
fi
echo "======================================================================"
if [ "$failed_count" -gt 0 ]; then
exit 1
else
exit 0
fi
}
# --- 新增SIGINT 信号处理函数 ---
handle_sigint() {
INTERRUPTED=true
print_summary
}
# =================================================================
# --- 主逻辑开始 ---
# =================================================================
# --- 新增:设置 trap 来捕获 SIGINT ---
trap handle_sigint SIGINT
# --- 参数解析 ---
while [[ "$#" -gt 0 ]]; do
case "$1" in
-e|--executable) EXECUTE_MODE=true; shift ;;
-eir) IR_EXECUTE_MODE=true; shift ;; # 新增
-c|--clean) CLEAN_MODE=true; shift ;;
-O1) OPTIMIZE_FLAG="-O1"; shift ;;
-lct) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then LLC_TIMEOUT="$2"; shift 2; else echo "错误: -lct 需要一个正整数参数。" >&2; exit 1; fi ;; # 新增
-sct) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then SYSYC_TIMEOUT="$2"; shift 2; else echo "错误: -sct 需要一个正整数参数。" >&2; exit 1; fi ;;
-gct) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then GCC_TIMEOUT="$2"; shift 2; else echo "错误: -gct 需要一个正整数参数。" >&2; exit 1; fi ;;
-et) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then EXEC_TIMEOUT="$2"; shift 2; else echo "错误: -et 需要一个正整数参数。" >&2; exit 1; fi ;;
-ml|--max-lines) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then MAX_OUTPUT_LINES="$2"; shift 2; else echo "错误: --max-lines 需要一个正整数参数。" >&2; exit 1; fi ;;
-h|--help) show_help; exit 0 ;;
-*) echo "未知选项: $1"; show_help; exit 1 ;;
*)
if [[ -f "$1" && "$1" == *.sy ]]; then
SY_FILES+=("$1")
else
echo "警告: 无效文件或不是 .sy 文件,已忽略: $1"
fi
shift
;;
esac
done
if ${CLEAN_MODE}; then
echo "检测到 -c/--clean 选项,正在清空 ${TMP_DIR}..."
if [ -d "${TMP_DIR}" ]; then
rm -rf "${TMP_DIR}"/* 2>/dev/null
echo "清理完成。"
else
echo "临时目录 ${TMP_DIR} 不存在,无需清理。"
fi
if [ ${#SY_FILES[@]} -eq 0 ] && ! ${EXECUTE_MODE} && ! ${IR_EXECUTE_MODE}; then
exit 0
fi
fi
if ! ${EXECUTE_MODE} && ! ${IR_EXECUTE_MODE}; then
echo "错误: 请提供 -e 或 -eir 选项来运行测试。"
show_help
exit 1
fi
if ${EXECUTE_MODE} && ${IR_EXECUTE_MODE}; then
echo -e "\e[31m错误: -e 和 -eir 选项不能同时使用。\e[0m" >&2
exit 1
fi
if [ ${#SY_FILES[@]} -eq 0 ]; then
echo "错误: 未提供任何 .sy 文件作为输入。"
show_help
exit 1
fi
mkdir -p "${TMP_DIR}"
TOTAL_CASES=${#SY_FILES[@]}
echo "SysY 单例测试运行器启动..."
if [ -n "$OPTIMIZE_FLAG" ]; then echo "优化等级: ${OPTIMIZE_FLAG}"; fi
echo "超时设置: sysyc=${SYSYC_TIMEOUT}s, llc=${LLC_TIMEOUT}s, gcc=${GCC_TIMEOUT}s, qemu=${EXEC_TIMEOUT}s"
echo ""
for sy_file in "${SY_FILES[@]}"; do
is_passed=1
compilation_ok=1
base_name=$(basename "${sy_file}" .sy)
source_dir=$(dirname "${sy_file}")
ir_file="${TMP_DIR}/${base_name}.ll"
assembly_file="${TMP_DIR}/${base_name}.s"
executable_file="${TMP_DIR}/${base_name}"
input_file="${source_dir}/${base_name}.in"
output_reference_file="${source_dir}/${base_name}.out"
output_actual_file="${TMP_DIR}/${base_name}.actual_out"
echo "======================================================================"
echo "正在处理: ${sy_file}"
# --- 编译阶段 ---
if ${IR_EXECUTE_MODE}; then
# 路径1: sysyc -> llc -> gcc
echo " [1/3] 使用 sysyc 编译为 IR (超时 ${SYSYC_TIMEOUT}s)..."
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s ir "${sy_file}" ${OPTIMIZE_FLAG} -o "${ir_file}"
if [ $? -ne 0 ]; then echo -e "\e[31m错误: SysY (IR) 编译失败或超时。\e[0m"; compilation_ok=0; fi
if [ "$compilation_ok" -eq 1 ]; then
echo " [2/3] 使用 llc 编译为汇编 (超时 ${LLC_TIMEOUT}s)..."
timeout -s KILL ${LLC_TIMEOUT} "${LLC_CMD}" -march=riscv64 -mcpu=generic-rv64 -mattr=+m,+a,+f,+d,+c -filetype=asm "${ir_file}" -o "${assembly_file}"
if [ $? -ne 0 ]; then echo -e "\e[31m错误: llc 编译失败或超时。\e[0m"; compilation_ok=0; fi
fi
if [ "$compilation_ok" -eq 1 ]; then
echo " [3/3] 使用 gcc 编译 (超时 ${GCC_TIMEOUT}s)..."
timeout -s KILL ${GCC_TIMEOUT} "${GCC_RISCV64}" "${assembly_file}" -o "${executable_file}" -L"${LIB_DIR}" -lsysy_riscv -static
if [ $? -ne 0 ]; then echo -e "\e[31m错误: GCC 编译失败或超时。\e[0m"; compilation_ok=0; fi
fi
else # EXECUTE_MODE
# 路径2: sysyc -> gcc
echo " [1/2] 使用 sysyc 编译为汇编 (超时 ${SYSYC_TIMEOUT}s)..."
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -S "${sy_file}" ${OPTIMIZE_FLAG} -o "${assembly_file}"
if [ $? -ne 0 ]; then echo -e "\e[31m错误: SysY (汇编) 编译失败或超时。\e[0m"; compilation_ok=0; fi
if [ "$compilation_ok" -eq 1 ]; then
echo " [2/2] 使用 gcc 编译 (超时 ${GCC_TIMEOUT}s)..."
timeout -s KILL ${GCC_TIMEOUT} "${GCC_RISCV64}" "${assembly_file}" -o "${executable_file}" -L"${LIB_DIR}" -lsysy_riscv -static
if [ $? -ne 0 ]; then echo -e "\e[31m错误: GCC 编译失败或超时。\e[0m"; compilation_ok=0; fi
fi
fi
# --- 执行与测试阶段 (公共逻辑) ---
if [ "$compilation_ok" -eq 1 ]; then
if [ -f "${input_file}" ] || [ -f "${output_reference_file}" ]; then
# --- 自动化测试模式 ---
echo " 检测到 .in/.out 文件,进入自动化测试模式..."
echo " 正在执行 (超时 ${EXEC_TIMEOUT}s)..."
exec_cmd="${QEMU_RISCV64} \"${executable_file}\""
[ -f "${input_file}" ] && exec_cmd+=" < \"${input_file}\""
exec_cmd+=" > \"${output_actual_file}\""
eval "timeout -s KILL ${EXEC_TIMEOUT} ${exec_cmd}"
ACTUAL_RETURN_CODE=$?
if [ "$ACTUAL_RETURN_CODE" -eq 124 ]; then
echo -e "\e[31m 执行超时。\e[0m"
is_passed=0
else
if [ -f "${output_reference_file}" ]; then
LAST_LINE_TRIMMED=$(tail -n 1 "${output_reference_file}" | tr -d '[:space:]')
if [[ "$LAST_LINE_TRIMMED" =~ ^[-+]?[0-9]+$ ]]; then
EXPECTED_RETURN_CODE="$LAST_LINE_TRIMMED"
EXPECTED_STDOUT_FILE="${TMP_DIR}/${base_name}.expected_stdout"
head -n -1 "${output_reference_file}" > "${EXPECTED_STDOUT_FILE}"
ret_ok=1
if [ "$ACTUAL_RETURN_CODE" -ne "$EXPECTED_RETURN_CODE" ]; then echo -e "\e[31m 返回码测试失败: 期望 ${EXPECTED_RETURN_CODE}, 实际 ${ACTUAL_RETURN_CODE}\e[0m"; ret_ok=0; fi
out_ok=1
if ! diff -q <(tr -d '[:space:]' < "${output_actual_file}") <(tr -d '[:space:]' < "${EXPECTED_STDOUT_FILE}") >/dev/null 2>&1; then
echo -e "\e[31m 标准输出测试失败。\e[0m"; out_ok=0
display_file_content "${EXPECTED_STDOUT_FILE}" " \e[36m--- 期望输出 ---\e[0m" "${MAX_OUTPUT_LINES}"
display_file_content "${output_actual_file}" " \e[36m--- 实际输出 ---\e[0m" "${MAX_OUTPUT_LINES}"
fi
if [ "$ret_ok" -eq 1 ] && [ "$out_ok" -eq 1 ]; then echo -e "\e[32m 返回码与标准输出测试成功。\e[0m"; else is_passed=0; fi
else
if diff -q <(tr -d '[:space:]' < "${output_actual_file}") <(tr -d '[:space:]' < "${output_reference_file}") >/dev/null 2>&1; then
echo -e "\e[32m 标准输出测试成功。\e[0m"
else
echo -e "\e[31m 标准输出测试失败。\e[0m"; is_passed=0
display_file_content "${output_reference_file}" " \e[36m--- 期望输出 ---\e[0m" "${MAX_OUTPUT_LINES}"
display_file_content "${output_actual_file}" " \e[36m--- 实际输出 ---\e[0m" "${MAX_OUTPUT_LINES}"
fi
fi
else
echo " 无参考输出文件。程序返回码: ${ACTUAL_RETURN_CODE}"
fi
fi
else
# --- 交互模式 ---
echo -e "\e[33m\n 未找到 .in 或 .out 文件,进入交互模式...\e[0m"
"${QEMU_RISCV64}" "${executable_file}"
INTERACTIVE_RET_CODE=$?
echo -e "\e[33m\n 交互模式执行完毕,程序返回码: ${INTERACTIVE_RET_CODE} (此结果未经验证)\e[0m"
fi
else
is_passed=0
fi
# --- 状态总结 ---
if [ "$is_passed" -eq 1 ]; then
echo -e "\e[32m状态: 通过\e[0m"
((PASSED_CASES++))
else
echo -e "\e[31m状态: 失败\e[0m"
FAILED_CASES_LIST+="${sy_file}\n"
fi
done
# --- 打印最终总结 ---
print_summary

442
script/runit.sh Normal file
View File

@ -0,0 +1,442 @@
#!/bin/bash
# runit.sh - 用于编译和测试 SysY 程序的脚本
# 此脚本应该位于 mysysy/script/
export ASAN_OPTIONS=detect_leaks=0
# 定义相对于脚本位置的目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
TESTDATA_DIR="${SCRIPT_DIR}/../testdata"
BUILD_BIN_DIR="${SCRIPT_DIR}/../build/bin"
LIB_DIR="${SCRIPT_DIR}/../lib"
TMP_DIR="${SCRIPT_DIR}/tmp"
# 定义编译器和模拟器
SYSYC="${BUILD_BIN_DIR}/sysyc"
LLC_CMD="llc-19"
GCC_RISCV64="riscv64-linux-gnu-gcc"
QEMU_RISCV64="qemu-riscv64"
# --- 状态变量 ---
EXECUTE_MODE=false
IR_EXECUTE_MODE=false
OPTIMIZE_FLAG=""
SYSYC_TIMEOUT=30
LLC_TIMEOUT=10
GCC_TIMEOUT=10
EXEC_TIMEOUT=30
MAX_OUTPUT_LINES=20
TEST_SETS=()
TOTAL_CASES=0
PASSED_CASES=0
FAILED_CASES_LIST=""
INTERRUPTED=false # 新增:用于标记是否被中断
# =================================================================
# --- 函数定义 ---
# =================================================================
# 显示帮助信息的函数
show_help() {
echo "用法: $0 [选项]"
echo "此脚本用于按文件名前缀数字升序编译和测试 .sy 文件。"
echo ""
echo "选项:"
echo " -e, --executable 编译为汇编并运行测试 (sysyc -> gcc -> qemu)。"
echo " -eir 通过IR编译为可执行文件并运行测试 (sysyc -> llc -> gcc -> qemu)。"
echo " -c, --clean 清理 'tmp' 目录下的所有生成文件。"
echo " -O1 启用 sysyc 的 -O1 优化。"
echo " -set [f|h|p|all]... 指定要运行的测试集 (functional, h_functional, performance)。可多选,默认为 all。"
echo " -sct N 设置 sysyc 编译超时为 N 秒 (默认: 30)。"
echo " -lct N 设置 llc-19 编译超时为 N 秒 (默认: 10)。"
echo " -gct N 设置 gcc 交叉编译超时为 N 秒 (默认: 10)。"
echo " -et N 设置 qemu 执行超时为 N 秒 (默认: 30)。"
echo " -ml N, --max-lines N 当输出对比失败时,最多显示 N 行内容 (默认: 20)。"
echo " -h, --help 显示此帮助信息并退出。"
echo ""
echo "注意: 默认行为 (无 -e 或 -eir) 是将 .sy 文件同时编译为 .s (汇编) 和 .ll (IR),不执行。"
echo " 可在任何时候按 Ctrl+C 来中断测试并显示当前已完成的测例总结。"
}
# 显示文件内容并根据行数截断的函数
display_file_content() {
local file_path="$1"
local title="$2"
local max_lines="$3"
if [ ! -f "$file_path" ]; then return; fi
echo -e "$title"
local line_count
line_count=$(wc -l < "$file_path")
if [ "$line_count" -gt "$max_lines" ]; then
head -n "$max_lines" "$file_path"
echo -e "\e[33m[... 输出已截断,共 ${line_count} 行 ...]\e[0m"
else
cat "$file_path"
fi
}
# 清理临时文件的函数
clean_tmp() {
echo "正在清理临时目录: ${TMP_DIR}"
rm -rf "${TMP_DIR}"/*
}
# --- 新增:总结报告函数 ---
print_summary() {
echo "" # 确保从新的一行开始
echo "========================================"
if [ "$INTERRUPTED" = true ]; then
echo -e "\e[33m测试被中断。正在汇总已完成的结果...\e[0m"
else
echo "测试完成"
fi
local failed_count
if [ -n "$FAILED_CASES_LIST" ]; then
# `wc -l` 计算由换行符分隔的列表项数
failed_count=$(echo -e -n "${FAILED_CASES_LIST}" | wc -l)
else
failed_count=0
fi
local executed_count=$((PASSED_CASES + failed_count))
echo "测试结果: [通过: ${PASSED_CASES}, 失败: ${failed_count}, 已执行: ${executed_count}/${TOTAL_CASES}]"
if [ -n "$FAILED_CASES_LIST" ]; then
echo ""
echo -e "\e[31m未通过的测例:\e[0m"
# 使用 printf 保证原样输出
printf "%b" "${FAILED_CASES_LIST}"
fi
echo "========================================"
if [ "$failed_count" -gt 0 ]; then
exit 1
else
exit 0
fi
}
# --- 新增SIGINT 信号处理函数 ---
handle_sigint() {
INTERRUPTED=true
print_summary
}
# =================================================================
# --- 主逻辑开始 ---
# =================================================================
# --- 新增:设置 trap 来捕获 SIGINT ---
trap handle_sigint SIGINT
mkdir -p "${TMP_DIR}"
# 解析命令行参数
while [[ "$#" -gt 0 ]]; do
case "$1" in
-e|--executable) EXECUTE_MODE=true; shift ;;
-eir) IR_EXECUTE_MODE=true; shift ;;
-c|--clean) clean_tmp; exit 0 ;;
-O1) OPTIMIZE_FLAG="-O1"; shift ;;
-set)
shift
while [[ "$#" -gt 0 && ! "$1" =~ ^- ]]; do TEST_SETS+=("$1"); shift; done
;;
-sct) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then SYSYC_TIMEOUT="$2"; shift 2; else echo "错误: -sct 需要一个正整数参数。" >&2; exit 1; fi ;;
-lct) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then LLC_TIMEOUT="$2"; shift 2; else echo "错误: -lct 需要一个正整数参数。" >&2; exit 1; fi ;;
-gct) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then GCC_TIMEOUT="$2"; shift 2; else echo "错误: -gct 需要一个正整数参数。" >&2; exit 1; fi ;;
-et) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then EXEC_TIMEOUT="$2"; shift 2; else echo "错误: -et 需要一个正整数参数。" >&2; exit 1; fi ;;
-ml|--max-lines) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then MAX_OUTPUT_LINES="$2"; shift 2; else echo "错误: --max-lines 需要一个正整数参数。" >&2; exit 1; fi ;;
-h|--help) show_help; exit 0 ;;
*) echo "未知选项: $1"; show_help; exit 1 ;;
esac
done
if ${EXECUTE_MODE} && ${IR_EXECUTE_MODE}; then
echo -e "\e[31m错误: -e 和 -eir 选项不能同时使用。\e[0m" >&2
exit 1
fi
declare -A SET_MAP
SET_MAP[f]="functional"
SET_MAP[h]="h_functional"
SET_MAP[p]="performance"
SEARCH_PATHS=()
if [ ${#TEST_SETS[@]} -eq 0 ] || [[ " ${TEST_SETS[@]} " =~ " all " ]]; then
SEARCH_PATHS+=("${TESTDATA_DIR}")
else
for set in "${TEST_SETS[@]}"; do
if [[ -v SET_MAP[$set] ]]; then
SEARCH_PATHS+=("${TESTDATA_DIR}/${SET_MAP[$set]}")
else
echo -e "\e[33m警告: 未知的测试集 '$set',已忽略。\e[0m"
fi
done
fi
if [ ${#SEARCH_PATHS[@]} -eq 0 ]; then
echo -e "\e[31m错误: 没有找到有效的测试集目录,测试中止。\e[0m"
exit 1
fi
echo "SysY 测试运行器启动..."
if [ -n "$OPTIMIZE_FLAG" ]; then echo "优化等级: ${OPTIMIZE_FLAG}"; fi
echo "输入目录: ${SEARCH_PATHS[@]}"
echo "临时目录: ${TMP_DIR}"
RUN_MODE_INFO=""
if ${IR_EXECUTE_MODE}; then
RUN_MODE_INFO="IR执行模式 (-eir)"
TIMEOUT_INFO="超时设置: sysyc=${SYSYC_TIMEOUT}s, llc=${LLC_TIMEOUT}s, gcc=${GCC_TIMEOUT}s, qemu=${EXEC_TIMEOUT}s"
elif ${EXECUTE_MODE}; then
RUN_MODE_INFO="直接执行模式 (-e)"
TIMEOUT_INFO="超时设置: sysyc=${SYSYC_TIMEOUT}s, gcc=${GCC_TIMEOUT}s, qemu=${EXEC_TIMEOUT}s"
else
RUN_MODE_INFO="编译模式 (默认)"
TIMEOUT_INFO="超时设置: sysyc=${SYSYC_TIMEOUT}s"
fi
echo "运行模式: ${RUN_MODE_INFO}"
echo "${TIMEOUT_INFO}"
if ${EXECUTE_MODE} || ${IR_EXECUTE_MODE}; then
echo "失败输出最大行数: ${MAX_OUTPUT_LINES}"
fi
echo ""
sy_files=$(find "${SEARCH_PATHS[@]}" -name "*.sy" | sort -V)
if [ -z "$sy_files" ]; then
echo "在指定目录中未找到任何 .sy 文件。"
exit 0
fi
TOTAL_CASES=$(echo "$sy_files" | wc -w)
while IFS= read -r sy_file; do
is_passed=0 # 0 表示失败, 1 表示通过
relative_path_no_ext=$(realpath --relative-to="${TESTDATA_DIR}" "${sy_file%.*}")
output_base_name=$(echo "${relative_path_no_ext}" | tr '/' '_')
assembly_file_S="${TMP_DIR}/${output_base_name}_sysyc_S.s"
executable_file_S="${TMP_DIR}/${output_base_name}_sysyc_S"
output_actual_file_S="${TMP_DIR}/${output_base_name}_sysyc_S.actual_out"
ir_file="${TMP_DIR}/${output_base_name}_sysyc_ir.ll"
assembly_file_from_ir="${TMP_DIR}/${output_base_name}_from_ir.s"
executable_file_from_ir="${TMP_DIR}/${output_base_name}_from_ir"
output_actual_file_from_ir="${TMP_DIR}/${output_base_name}_from_ir.actual_out"
input_file="${sy_file%.*}.in"
output_reference_file="${sy_file%.*}.out"
echo "正在处理: $(basename "$sy_file") (路径: ${relative_path_no_ext}.sy)"
# --- 模式 1: IR 执行模式 (-eir) ---
if ${IR_EXECUTE_MODE}; then
step_failed=0
test_logic_passed=0
echo " [1/4] 使用 sysyc 编译为 IR (超时 ${SYSYC_TIMEOUT}s)..."
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s ir "${sy_file}" -o "${ir_file}" ${OPTIMIZE_FLAG}
SYSYC_STATUS=$?
if [ $SYSYC_STATUS -ne 0 ]; then
[ $SYSYC_STATUS -eq 124 ] && echo -e "\e[31m错误: SysY (IR) 编译超时\e[0m" || echo -e "\e[31m错误: SysY (IR) 编译失败,退出码: ${SYSYC_STATUS}\e[0m"
step_failed=1
fi
if [ "$step_failed" -eq 0 ]; then
echo " [2/4] 使用 llc-19 编译为汇编 (超时 ${LLC_TIMEOUT}s)..."
timeout -s KILL ${LLC_TIMEOUT} "${LLC_CMD}" -march=riscv64 -mcpu=generic-rv64 -mattr=+m,+a,+f,+d,+c -filetype=asm "${ir_file}" -o "${assembly_file_from_ir}"
LLC_STATUS=$?
if [ $LLC_STATUS -ne 0 ]; then
[ $LLC_STATUS -eq 124 ] && echo -e "\e[31m错误: llc-19 编译超时\e[0m" || echo -e "\e[31m错误: llc-19 编译失败,退出码: ${LLC_STATUS}\e[0m"
step_failed=1
fi
fi
if [ "$step_failed" -eq 0 ]; then
echo " [3/4] 使用 gcc 编译 (超时 ${GCC_TIMEOUT}s)..."
timeout -s KILL ${GCC_TIMEOUT} "${GCC_RISCV64}" "${assembly_file_from_ir}" -o "${executable_file_from_ir}" -L"${LIB_DIR}" -lsysy_riscv -static
GCC_STATUS=$?
if [ $GCC_STATUS -ne 0 ]; then
[ $GCC_STATUS -eq 124 ] && echo -e "\e[31m错误: GCC 编译超时\e[0m" || echo -e "\e[31m错误: GCC 编译失败,退出码: ${GCC_STATUS}\e[0m"
step_failed=1
fi
fi
if [ "$step_failed" -eq 0 ]; then
echo " [4/4] 正在执行 (超时 ${EXEC_TIMEOUT}s)..."
exec_cmd="${QEMU_RISCV64} \"${executable_file_from_ir}\""
[ -f "${input_file}" ] && exec_cmd+=" < \"${input_file}\""
exec_cmd+=" > \"${output_actual_file_from_ir}\""
eval "timeout -s KILL ${EXEC_TIMEOUT} ${exec_cmd}"
ACTUAL_RETURN_CODE=$?
if [ "$ACTUAL_RETURN_CODE" -eq 124 ]; then
echo -e "\e[31m 执行超时: 运行超过 ${EXEC_TIMEOUT} 秒\e[0m"
else
if [ -f "${output_reference_file}" ]; then
LAST_LINE_TRIMMED=$(tail -n 1 "${output_reference_file}" | tr -d '[:space:]')
test_logic_passed=1
if [[ "$LAST_LINE_TRIMMED" =~ ^[-+]?[0-9]+$ ]]; then
EXPECTED_RETURN_CODE="$LAST_LINE_TRIMMED"
EXPECTED_STDOUT_FILE="${TMP_DIR}/${output_base_name}_from_ir.expected_stdout"
head -n -1 "${output_reference_file}" > "${EXPECTED_STDOUT_FILE}"
if [ "$ACTUAL_RETURN_CODE" -eq "$EXPECTED_RETURN_CODE" ]; then
echo -e "\e[32m 返回码测试成功: (${ACTUAL_RETURN_CODE}) 与期望值 (${EXPECTED_RETURN_CODE}) 匹配\e[0m"
else
echo -e "\e[31m 返回码测试失败: 期望: ${EXPECTED_RETURN_CODE}, 实际: ${ACTUAL_RETURN_CODE}\e[0m"
test_logic_passed=0
fi
if diff -q <(tr -d '[:space:]' < "${output_actual_file_from_ir}") <(tr -d '[:space:]' < "${EXPECTED_STDOUT_FILE}") >/dev/null 2>&1; then
[ "$test_logic_passed" -eq 1 ] && echo -e "\e[32m 标准输出测试成功\e[0m"
else
echo -e "\e[31m 标准输出测试失败\e[0m"
display_file_content "${EXPECTED_STDOUT_FILE}" " \e[36m---------- 期望输出 ----------\e[0m" "${MAX_OUTPUT_LINES}"
display_file_content "${output_actual_file_from_ir}" " \e[36m---------- 实际输出 ----------\e[0m" "${MAX_OUTPUT_LINES}"
test_logic_passed=0
fi
else
if [ $ACTUAL_RETURN_CODE -ne 0 ]; then echo -e "\e[33m警告: 程序以非零状态 ${ACTUAL_RETURN_CODE} 退出 (纯输出比较模式)。\e[0m"; fi
if diff -q <(tr -d '[:space:]' < "${output_actual_file_from_ir}") <(tr -d '[:space:]' < "${output_reference_file}") >/dev/null 2>&1; then
echo -e "\e[32m 成功: 输出与参考输出匹配\e[0m"
else
echo -e "\e[31m 失败: 输出不匹配\e[0m"
display_file_content "${output_reference_file}" " \e[36m---------- 期望输出 ----------\e[0m" "${MAX_OUTPUT_LINES}"
display_file_content "${output_actual_file_from_ir}" " \e[36m---------- 实际输出 ----------\e[0m" "${MAX_OUTPUT_LINES}"
test_logic_passed=0
fi
fi
else
echo " 无参考输出文件。程序返回码: ${ACTUAL_RETURN_CODE}"
test_logic_passed=1
fi
fi
fi
[ "$step_failed" -eq 0 ] && [ "$test_logic_passed" -eq 1 ] && is_passed=1
# --- 模式 2: 直接执行模式 (-e) ---
elif ${EXECUTE_MODE}; then
step_failed=0
test_logic_passed=0
echo " [1/3] 使用 sysyc 编译为汇编 (超时 ${SYSYC_TIMEOUT}s)..."
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -S "${sy_file}" -o "${assembly_file_S}" ${OPTIMIZE_FLAG}
SYSYC_STATUS=$?
if [ $SYSYC_STATUS -ne 0 ]; then
[ $SYSYC_STATUS -eq 124 ] && echo -e "\e[31m错误: SysY (汇编) 编译超时\e[0m" || echo -e "\e[31m错误: SysY (汇编) 编译失败,退出码: ${SYSYC_STATUS}\e[0m"
step_failed=1
fi
if [ "$step_failed" -eq 0 ]; then
echo " [2/3] 使用 gcc 编译 (超时 ${GCC_TIMEOUT}s)..."
timeout -s KILL ${GCC_TIMEOUT} "${GCC_RISCV64}" "${assembly_file_S}" -o "${executable_file_S}" -L"${LIB_DIR}" -lsysy_riscv -static
GCC_STATUS=$?
if [ $GCC_STATUS -ne 0 ]; then
[ $GCC_STATUS -eq 124 ] && echo -e "\e[31m错误: GCC 编译超时\e[0m" || echo -e "\e[31m错误: GCC 编译失败,退出码: ${GCC_STATUS}\e[0m"
step_failed=1
fi
fi
if [ "$step_failed" -eq 0 ]; then
echo " [3/3] 正在执行 (超时 ${EXEC_TIMEOUT}s)..."
exec_cmd="${QEMU_RISCV64} \"${executable_file_S}\""
[ -f "${input_file}" ] && exec_cmd+=" < \"${input_file}\""
exec_cmd+=" > \"${output_actual_file_S}\""
eval "timeout -s KILL ${EXEC_TIMEOUT} ${exec_cmd}"
ACTUAL_RETURN_CODE=$?
if [ "$ACTUAL_RETURN_CODE" -eq 124 ]; then
echo -e "\e[31m 执行超时: 运行超过 ${EXEC_TIMEOUT} 秒\e[0m"
else
if [ -f "${output_reference_file}" ]; then
LAST_LINE_TRIMMED=$(tail -n 1 "${output_reference_file}" | tr -d '[:space:]')
test_logic_passed=1
if [[ "$LAST_LINE_TRIMMED" =~ ^[-+]?[0-9]+$ ]]; then
EXPECTED_RETURN_CODE="$LAST_LINE_TRIMMED"
EXPECTED_STDOUT_FILE="${TMP_DIR}/${output_base_name}_sysyc_S.expected_stdout"
head -n -1 "${output_reference_file}" > "${EXPECTED_STDOUT_FILE}"
if [ "$ACTUAL_RETURN_CODE" -eq "$EXPECTED_RETURN_CODE" ]; then
echo -e "\e[32m 返回码测试成功: (${ACTUAL_RETURN_CODE}) 与期望值 (${EXPECTED_RETURN_CODE}) 匹配\e[0m"
else
echo -e "\e[31m 返回码测试失败: 期望: ${EXPECTED_RETURN_CODE}, 实际: ${ACTUAL_RETURN_CODE}\e[0m"
test_logic_passed=0
fi
if diff -q <(tr -d '[:space:]' < "${output_actual_file_S}") <(tr -d '[:space:]' < "${EXPECTED_STDOUT_FILE}") >/dev/null 2>&1; then
[ "$test_logic_passed" -eq 1 ] && echo -e "\e[32m 标准输出测试成功\e[0m"
else
echo -e "\e[31m 标准输出测试失败\e[0m"
display_file_content "${EXPECTED_STDOUT_FILE}" " \e[36m---------- 期望输出 ----------\e[0m" "${MAX_OUTPUT_LINES}"
display_file_content "${output_actual_file_S}" " \e[36m---------- 实际输出 ----------\e[0m" "${MAX_OUTPUT_LINES}"
test_logic_passed=0
fi
else
if [ $ACTUAL_RETURN_CODE -ne 0 ]; then echo -e "\e[33m警告: 程序以非零状态 ${ACTUAL_RETURN_CODE} 退出 (纯输出比较模式)。\e[0m"; fi
if diff -q <(tr -d '[:space:]' < "${output_actual_file_S}") <(tr -d '[:space:]' < "${output_reference_file}") >/dev/null 2>&1; then
echo -e "\e[32m 成功: 输出与参考输出匹配\e[0m"
else
echo -e "\e[31m 失败: 输出不匹配\e[0m"
display_file_content "${output_reference_file}" " \e[36m---------- 期望输出 ----------\e[0m" "${MAX_OUTPUT_LINES}"
display_file_content "${output_actual_file_S}" " \e[36m---------- 实际输出 ----------\e[0m" "${MAX_OUTPUT_LINES}"
test_logic_passed=0
fi
fi
else
echo " 无参考输出文件。程序返回码: ${ACTUAL_RETURN_CODE}"
test_logic_passed=1
fi
fi
fi
[ "$step_failed" -eq 0 ] && [ "$test_logic_passed" -eq 1 ] && is_passed=1
# --- 模式 3: 默认编译模式 ---
else
s_compile_ok=0
ir_compile_ok=0
echo " [1/2] 使用 sysyc 编译为汇编 (超时 ${SYSYC_TIMEOUT}s)..."
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -S "${sy_file}" -o "${assembly_file_S}" ${OPTIMIZE_FLAG}
SYSYC_S_STATUS=$?
if [ $SYSYC_S_STATUS -eq 0 ]; then
s_compile_ok=1
echo -e " \e[32m-> ${assembly_file_S} [成功]\e[0m"
else
[ $SYSYC_S_STATUS -eq 124 ] && echo -e " \e[31m-> [编译超时]\e[0m" || echo -e " \e[31m-> [编译失败, 退出码: ${SYSYC_S_STATUS}]\e[0m"
fi
echo " [2/2] 使用 sysyc 编译为 IR (超时 ${SYSYC_TIMEOUT}s)..."
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s ir "${sy_file}" -o "${ir_file}" ${OPTIMIZE_FLAG}
SYSYC_IR_STATUS=$?
if [ $SYSYC_IR_STATUS -eq 0 ]; then
ir_compile_ok=1
echo -e " \e[32m-> ${ir_file} [成功]\e[0m"
else
[ $SYSYC_IR_STATUS -eq 124 ] && echo -e " \e[31m-> [编译超时]\e[0m" || echo -e " \e[31m-> [编译失败, 退出码: ${SYSYC_IR_STATUS}]\e[0m"
fi
if [ "$s_compile_ok" -eq 1 ] && [ "$ir_compile_ok" -eq 1 ]; then
is_passed=1
fi
fi
# --- 统计结果 ---
if [ "$is_passed" -eq 1 ]; then
((PASSED_CASES++))
else
# 确保 FAILED_CASES_LIST 的每一项都以换行符结尾
FAILED_CASES_LIST+="${relative_path_no_ext}.sy\n"
fi
echo ""
done <<< "$sy_files"
# --- 修改:调用总结函数 ---
print_summary

View File

@ -1,171 +0,0 @@
#include "AddressCalculationExpansion.h"
#include <iostream>
#include <vector>
#include "IR.h"
#include "IRBuilder.h"
extern int DEBUG;
namespace sysy {
bool AddressCalculationExpansion::run() {
bool changed = false;
for (auto& funcPair : pModule->getFunctions()) {
Function* func = funcPair.second.get();
for (auto& bb_ptr : func->getBasicBlocks()) {
BasicBlock* bb = bb_ptr.get();
for (auto it = bb->getInstructions().begin(); it != bb->getInstructions().end(); ) {
Instruction* inst = it->get();
Value* basePointer = nullptr;
Value* valueToStore = nullptr;
size_t firstIndexOperandIdx = 0;
size_t numBaseOperands = 0;
if (inst->isLoad()) {
numBaseOperands = 1;
basePointer = inst->getOperand(0);
firstIndexOperandIdx = 1;
} else if (inst->isStore()) {
numBaseOperands = 2;
valueToStore = inst->getOperand(0);
basePointer = inst->getOperand(1);
firstIndexOperandIdx = 2;
} else {
++it;
continue;
}
if (inst->getNumOperands() <= numBaseOperands) {
++it;
continue;
}
std::vector<int> dims;
if (AllocaInst* allocaInst = dynamic_cast<AllocaInst*>(basePointer)) {
for (const auto& use_ptr : allocaInst->getDims()) {
Value* dimValue = use_ptr->getValue();
if (ConstantValue* constVal = dynamic_cast<ConstantValue*>(dimValue)) {
dims.push_back(constVal->getInt());
} else {
std::cerr << "Warning: AllocaInst dimension is not a constant integer. Skipping GEP expansion for: ";
SysYPrinter::printValue(allocaInst);
std::cerr << "\n";
dims.clear();
break;
}
}
} else if (GlobalValue* globalValue = dynamic_cast<GlobalValue*>(basePointer)) {
// 遍历 GlobalValue 的所有维度操作数
for (const auto& use_ptr : globalValue->getDims()) {
Value* dimValue = use_ptr->getValue();
// 将维度值转换为常量整数
if (ConstantInteger* constVal = dynamic_cast<ConstantInteger*>(dimValue)) {
dims.push_back(constVal->getInt());
} else {
// 如果维度不是常量整数,则无法处理。
// 根据 IR.h 中 GlobalValue 的构造函数,这种情况不应发生,但作为安全检查是好的。
std::cerr << "Warning: GlobalValue dimension is not a constant integer. Skipping GEP expansion for: ";
SysYPrinter::printValue(globalValue);
std::cerr << "\n";
dims.clear(); // 清空已收集的部分维度信息
break;
}
}
} else {
std::cerr << "Warning: Base pointer is not AllocaInst/GlobalValue or its array dimensions cannot be determined for GEP expansion. Skipping GEP for: ";
SysYPrinter::printValue(basePointer);
std::cerr << " in instruction ";
SysYPrinter::printInst(inst);
std::cerr << "\n";
++it;
continue;
}
if (dims.empty() && (inst->getNumOperands() > numBaseOperands)) {
if (DEBUG) {
std::cerr << "ACE Warning: Could not get valid array dimensions for ";
SysYPrinter::printValue(basePointer);
std::cerr << " in instruction ";
SysYPrinter::printInst(inst);
std::cerr << " (expected dimensions for indices, but got none).\n";
}
++it;
continue;
}
std::vector<Value*> indexOperands;
for (size_t i = firstIndexOperandIdx; i < inst->getNumOperands(); ++i) {
indexOperands.push_back(inst->getOperand(i));
}
if (AllocaInst* allocaInst = dynamic_cast<AllocaInst*>(basePointer)) {
if (allocaInst->getNumDims() != indexOperands.size()) {
if (DEBUG) {
std::cerr << "ACE Warning: Index count (" << indexOperands.size() << ") does not match AllocaInst dimensions (" << allocaInst->getNumDims() << ") for instruction ";
SysYPrinter::printInst(inst);
std::cerr << "\n";
}
++it;
continue;
}
}
Value* totalOffset = ConstantInteger::get(0);
pBuilder->setPosition(bb, it);
for (size_t i = 0; i < indexOperands.size(); ++i) {
Value* index = indexOperands[i];
int stride = calculateStride(dims, i);
Value* strideConst = ConstantInteger::get(stride);
Type* intType = Type::getIntType();
BinaryInst* currentDimOffsetInst = pBuilder->createBinaryInst(Instruction::kMul, intType, index, strideConst);
BinaryInst* newTotalOffsetInst = pBuilder->createBinaryInst(Instruction::kAdd, intType, totalOffset, currentDimOffsetInst);
totalOffset = newTotalOffsetInst;
}
// 计算有效地址effective_address = basePointer + totalOffset
Value* effective_address = pBuilder->createBinaryInst(Instruction::kAdd, basePointer->getType(), basePointer, totalOffset);
// 创建新的 LoadInst 或 StoreInstindices 为空
Instruction* newInst = nullptr;
if (inst->isLoad()) {
newInst = pBuilder->createLoadInst(effective_address, {});
inst->replaceAllUsesWith(newInst);
} else { // StoreInst
newInst = pBuilder->createStoreInst(valueToStore, effective_address, {});
}
Instruction* oldInst = it->get();
++it;
for (size_t i = 0; i < oldInst->getNumOperands(); ++i) {
Value* operandValue = oldInst->getOperand(i);
if (operandValue) {
for (auto use_it = operandValue->getUses().begin(); use_it != operandValue->getUses().end(); ++use_it) {
if ((*use_it)->getUser() == oldInst && (*use_it)->getIndex() == i) {
operandValue->removeUse(*use_it);
break;
}
}
}
}
bb->getInstructions().erase(std::prev(it));
changed = true;
if (DEBUG) {
std::cerr << "ACE: Computed effective address:\n";
SysYPrinter::printInst(dynamic_cast<Instruction*>(effective_address));
std::cerr << "ACE: New Load/Store instruction:\n";
SysYPrinter::printInst(newInst);
std::cerr << "--------------------------------\n";
}
}
}
}
return changed;
}
} // namespace sysy

View File

@ -1,55 +1,24 @@
# 移除 ANTLR 代码生成相关配置
# list(APPEND CMAKE_MODULE_PATH "${ANTLR_RUNTIME}/cmake")
# include(FindANTLR)
# antlr_target(SysYGen SysY.g4
# LEXER PARSER
# OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
# VISITOR
# )
# src/CMakeLists.txt
# add_subdirectory 命令会负责遍历子目录并查找其内部的 CMakeLists.txt 文件
add_subdirectory(frontend)
add_subdirectory(midend)
add_subdirectory(backend/RISCv64)
# 移除 SysYParser 库的构建(如果不需要独立库)
# add_library(SysYParser SHARED ${ANTLR_SysYGen_CXX_OUTPUTS})
# target_include_directories(SysYParser PUBLIC ${ANTLR_RUNTIME}/runtime/src)
# target_link_libraries(SysYParser PUBLIC antlr4_shared)
# 构建 sysyc 可执行文件,使用手动提供的 SysYLexer.cpp、SysYParser.cpp 等文件
# 构建 sysyc 可执行文件,链接各个模块的库
add_executable(sysyc
sysyc.cpp
SysYLexer.cpp # 手动提供的文件
SysYParser.cpp # 手动提供的文件
SysYVisitor.cpp # 手动提供的文件
IR.cpp
SysYIRGenerator.cpp
SysYIRPrinter.cpp
SysYIRCFGOpt.cpp
Pass.cpp
Dom.cpp
Liveness.cpp
DCE.cpp
AddressCalculationExpansion.cpp
# Mem2Reg.cpp
# Reg2Mem.cpp
RISCv64Backend.cpp
RISCv64ISel.cpp
RISCv64RegAlloc.cpp
RISCv64AsmPrinter.cpp
RISCv64Passes.cpp
RISCv64LLIR.cpp
sysyc.cpp
)
# 设置 include 路径,包含 ANTLR 运行时库和项目头文件
# 链接各个模块的库
target_link_libraries(sysyc PRIVATE
frontend_lib
midend_lib
riscv64_backend_lib
antlr4_shared
)
# 设置 include 路径,包含项目顶层 include 目录
target_include_directories(sysyc PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include # 项目头文件目录
${ANTLR_RUNTIME}/runtime/src # ANTLR 运行时库头文件
)
# 保留 ANTLR 运行时库的链接
target_link_libraries(sysyc PRIVATE antlr4_shared)
# 保留其他编译选项
target_compile_options(sysyc PRIVATE -frtti)
# 可选:线程支持(如果需要,取消注释)
# set(THREADS_PREFER_PTHREAD_FLAG ON)
# find_package(Threads REQUIRED)
# target_link_libraries(sysyc PRIVATE Threads::Threads)
${CMAKE_CURRENT_SOURCE_DIR}/include # 项目头文件目录
${ANTLR_RUNTIME}/runtime/src # ANTLR运行时库头文件
)

View File

@ -1,180 +0,0 @@
#include "Dom.h"
#include <limits> // for std::numeric_limits
#include <queue>
namespace sysy {
// 初始化 支配树静态 ID
void *DominatorTreeAnalysisPass::ID = (void *)&DominatorTreeAnalysisPass::ID;
// ==============================================================
// DominatorTree 结果类的实现
// ==============================================================
DominatorTree::DominatorTree(Function *F) : AssociatedFunction(F) {
// 构造时可以不计算,在分析遍运行里计算并填充
}
const std::set<BasicBlock *> *DominatorTree::getDominators(BasicBlock *BB) const {
auto it = Dominators.find(BB);
if (it != Dominators.end()) {
return &(it->second);
}
return nullptr;
}
BasicBlock *DominatorTree::getImmediateDominator(BasicBlock *BB) const {
auto it = IDoms.find(BB);
if (it != IDoms.end()) {
return it->second;
}
return nullptr;
}
const std::set<BasicBlock *> *DominatorTree::getDominanceFrontier(BasicBlock *BB) const {
auto it = DominanceFrontiers.find(BB);
if (it != DominanceFrontiers.end()) {
return &(it->second);
}
return nullptr;
}
void DominatorTree::computeDominators(Function *F) {
// 经典的迭代算法计算支配者集合
// TODO: 可以替换为更高效的算法,如 Lengauer-Tarjan 算法
BasicBlock *entryBlock = F->getEntryBlock();
for (const auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *bb = bb_ptr.get();
if (bb == entryBlock) {
Dominators[bb].insert(bb);
} else {
for (const auto &all_bb_ptr : F->getBasicBlocks()) {
Dominators[bb].insert(all_bb_ptr.get());
}
}
}
bool changed = true;
while (changed) {
changed = false;
for (const auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *bb = bb_ptr.get();
if (bb == entryBlock)
continue;
std::set<BasicBlock *> newDom;
bool firstPred = true;
for (BasicBlock *pred : bb->getPredecessors()) {
if (Dominators.count(pred)) {
if (firstPred) {
newDom = Dominators[pred];
firstPred = false;
} else {
std::set<BasicBlock *> intersection;
std::set_intersection(newDom.begin(), newDom.end(), Dominators[pred].begin(), Dominators[pred].end(),
std::inserter(intersection, intersection.begin()));
newDom = intersection;
}
}
}
newDom.insert(bb);
if (newDom != Dominators[bb]) {
Dominators[bb] = newDom;
changed = true;
}
}
}
}
void DominatorTree::computeIDoms(Function *F) {
// 采用与之前类似的简化实现。TODO:Lengauer-Tarjan等算法。
BasicBlock *entryBlock = F->getEntryBlock();
IDoms[entryBlock] = nullptr;
for (const auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *bb = bb_ptr.get();
if (bb == entryBlock)
continue;
BasicBlock *currentIDom = nullptr;
const std::set<BasicBlock *> *domsOfBB = getDominators(bb);
if (!domsOfBB)
continue;
for (BasicBlock *D : *domsOfBB) {
if (D == bb)
continue;
bool isCandidateIDom = true;
for (BasicBlock *candidate : *domsOfBB) {
if (candidate == bb || candidate == D)
continue;
const std::set<BasicBlock *> *domsOfCandidate = getDominators(candidate);
if (domsOfCandidate && domsOfCandidate->count(D) == 0 && domsOfBB->count(candidate)) {
isCandidateIDom = false;
break;
}
}
if (isCandidateIDom) {
currentIDom = D;
break;
}
}
IDoms[bb] = currentIDom;
}
}
void DominatorTree::computeDominanceFrontiers(Function *F) {
// 经典的支配边界计算算法
for (const auto &bb_ptr_X : F->getBasicBlocks()) {
BasicBlock *X = bb_ptr_X.get();
DominanceFrontiers[X].clear();
for (BasicBlock *Y : X->getSuccessors()) {
const std::set<BasicBlock *> *domsOfY = getDominators(Y);
if (domsOfY && domsOfY->find(X) == domsOfY->end()) {
DominanceFrontiers[X].insert(Y);
}
}
const std::set<BasicBlock *> *domsOfX = getDominators(X);
if (!domsOfX)
continue;
for (const auto &bb_ptr_Z : F->getBasicBlocks()) {
BasicBlock *Z = bb_ptr_Z.get();
if (Z == X)
continue;
const std::set<BasicBlock *> *domsOfZ = getDominators(Z);
if (domsOfZ && domsOfZ->count(X) && Z != X) {
for (BasicBlock *Y : Z->getSuccessors()) {
const std::set<BasicBlock *> *domsOfY = getDominators(Y);
if (domsOfY && domsOfY->find(X) == domsOfY->end()) {
DominanceFrontiers[X].insert(Y);
}
}
}
}
}
}
// ==============================================================
// DominatorTreeAnalysisPass 的实现
// ==============================================================
bool DominatorTreeAnalysisPass::runOnFunction(Function* F, AnalysisManager &AM) {
CurrentDominatorTree = std::make_unique<DominatorTree>(F);
CurrentDominatorTree->computeDominators(F);
CurrentDominatorTree->computeIDoms(F);
CurrentDominatorTree->computeDominanceFrontiers(F);
return false;
}
std::unique_ptr<AnalysisResultBase> DominatorTreeAnalysisPass::getResult() {
// 返回计算好的 DominatorTree 实例,所有权转移给 AnalysisManager
return std::move(CurrentDominatorTree);
}
} // namespace sysy

View File

@ -1,742 +0,0 @@
#include "IR.h"
#include <algorithm>
#include <cassert>
#include <memory>
#include <queue>
#include <set>
#include <sstream>
#include <vector>
#include "IRBuilder.h"
/**
* @file IR.cpp
*
* @brief 定义IR相关类型与操作的源文件
*/
namespace sysy {
//===----------------------------------------------------------------------===//
// Types
//===----------------------------------------------------------------------===//
auto Type::getIntType() -> Type * {
static Type intType(kInt);
return &intType;
}
auto Type::getFloatType() -> Type * {
static Type floatType(kFloat);
return &floatType;
}
auto Type::getVoidType() -> Type * {
static Type voidType(kVoid);
return &voidType;
}
auto Type::getLabelType() -> Type * {
static Type labelType(kLabel);
return &labelType;
}
auto Type::getPointerType(Type *baseType) -> Type * {
// forward to PointerType
return PointerType::get(baseType);
}
auto Type::getFunctionType(Type *returnType, const std::vector<Type *> &paramTypes) -> Type * {
// forward to FunctionType
return FunctionType::get(returnType, paramTypes);
}
auto Type::getArrayType(Type *elementType, unsigned numElements) -> Type * {
// forward to ArrayType
return ArrayType::get(elementType, numElements);
}
auto Type::getSize() const -> unsigned {
switch (kind) {
case kInt:
case kFloat:
return 4;
case kLabel:
case kPointer:
case kFunction:
return 8;
case Kind::kArray: {
const ArrayType* arrType = static_cast<const ArrayType*>(this);
return arrType->getElementType()->getSize() * arrType->getNumElements();
}
case kVoid:
return 0;
}
return 0;
}
PointerType* PointerType::get(Type *baseType) {
static std::map<Type *, std::unique_ptr<PointerType>> pointerTypes;
auto iter = pointerTypes.find(baseType);
if (iter != pointerTypes.end()) {
return iter->second.get();
}
auto type = new PointerType(baseType);
assert(type);
auto result = pointerTypes.emplace(baseType, type);
return result.first->second.get();
}
FunctionType*FunctionType::get(Type *returnType, const std::vector<Type *> &paramTypes) {
static std::set<std::unique_ptr<FunctionType>> functionTypes;
auto iter =
std::find_if(functionTypes.begin(), functionTypes.end(), [&](const std::unique_ptr<FunctionType> &type) -> bool {
if (returnType != type->getReturnType() ||
paramTypes.size() != static_cast<size_t>(type->getParamTypes().size())) {
return false;
}
return std::equal(paramTypes.begin(), paramTypes.end(), type->getParamTypes().begin());
});
if (iter != functionTypes.end()) {
return iter->get();
}
auto type = new FunctionType(returnType, paramTypes);
assert(type);
auto result = functionTypes.emplace(type);
return result.first->get();
}
ArrayType *ArrayType::get(Type *elementType, unsigned numElements) {
static std::set<std::unique_ptr<ArrayType>> arrayTypes;
auto iter = std::find_if(arrayTypes.begin(), arrayTypes.end(), [&](const std::unique_ptr<ArrayType> &type) -> bool {
return elementType == type->getElementType() && numElements == type->getNumElements();
});
if (iter != arrayTypes.end()) {
return iter->get();
}
auto type = new ArrayType(elementType, numElements);
assert(type);
auto result = arrayTypes.emplace(type);
return result.first->get();
}
void Value::replaceAllUsesWith(Value *value) {
for (auto &use : uses) {
use->getUser()->setOperand(use->getIndex(), value);
}
uses.clear();
}
// Implementations for static members
std::unordered_map<ConstantValueKey, ConstantValue*, ConstantValueHash, ConstantValueEqual> ConstantValue::mConstantPool;
std::unordered_map<Type*, UndefinedValue*> UndefinedValue::UndefValues;
ConstantValue* ConstantValue::get(Type* type, ConstantValVariant val) {
ConstantValueKey key = {type, val};
auto it = mConstantPool.find(key);
if (it != mConstantPool.end()) {
return it->second;
}
ConstantValue* newConstant = nullptr;
if (std::holds_alternative<int>(val)) {
newConstant = new ConstantInteger(type, std::get<int>(val));
} else if (std::holds_alternative<float>(val)) {
newConstant = new ConstantFloating(type, std::get<float>(val));
} else {
assert(false && "Unsupported ConstantValVariant type");
}
mConstantPool[key] = newConstant;
return newConstant;
}
ConstantInteger* ConstantInteger::get(Type* type, int val) {
return dynamic_cast<ConstantInteger*>(ConstantValue::get(type, val));
}
ConstantFloating* ConstantFloating::get(Type* type, float val) {
return dynamic_cast<ConstantFloating*>(ConstantValue::get(type, val));
}
UndefinedValue* UndefinedValue::get(Type* type) {
assert(!type->isVoid() && "Cannot get UndefinedValue of void type!");
auto it = UndefValues.find(type);
if (it != UndefValues.end()) {
return it->second;
}
UndefinedValue* newUndef = new UndefinedValue(type);
UndefValues[type] = newUndef;
return newUndef;
}
auto Function::getCalleesWithNoExternalAndSelf() -> std::set<Function *> {
std::set<Function *> result;
for (auto callee : callees) {
if (parent->getExternalFunctions().count(callee->getName()) == 0U && callee != this) {
result.insert(callee);
}
}
return result;
}
// 函数克隆,后续函数级优化(内联等)需要用到
Function * Function::clone(const std::string &suffix) const {
std::stringstream ss;
std::map<BasicBlock *, BasicBlock *> oldNewBlockMap;
IRBuilder builder;
auto newFunction = new Function(parent, type, name);
newFunction->getEntryBlock()->setName(blocks.front()->getName());
oldNewBlockMap.emplace(blocks.front().get(), newFunction->getEntryBlock());
auto oldBlockListIter = std::next(blocks.begin());
while (oldBlockListIter != blocks.end()) {
auto newBlock = newFunction->addBasicBlock(oldBlockListIter->get()->getName());
oldNewBlockMap.emplace(oldBlockListIter->get(), newBlock);
oldBlockListIter++;
}
for (const auto &oldNewBlockItem : oldNewBlockMap) {
auto oldBlock = oldNewBlockItem.first;
auto newBlock = oldNewBlockItem.second;
for (const auto &oldPred : oldBlock->getPredecessors()) {
newBlock->addPredecessor(oldNewBlockMap.at(oldPred));
}
for (const auto &oldSucc : oldBlock->getSuccessors()) {
newBlock->addSuccessor(oldNewBlockMap.at(oldSucc));
}
}
std::map<Value *, Value *> oldNewValueMap;
std::map<Value *, bool> isAddedToCreate;
std::map<Value *, bool> isCreated;
std::queue<Value *> toCreate;
for (const auto &oldBlock : blocks) {
for (const auto &inst : oldBlock->getInstructions()) {
isAddedToCreate.emplace(inst.get(), false);
isCreated.emplace(inst.get(), false);
}
}
for (const auto &oldBlock : blocks) {
for (const auto &inst : oldBlock->getInstructions()) {
for (const auto &valueUse : inst->getOperands()) {
auto value = valueUse->getValue();
if (oldNewValueMap.find(value) == oldNewValueMap.end()) {
auto oldAllocInst = dynamic_cast<AllocaInst *>(value);
if (oldAllocInst != nullptr) {
std::vector<Value *> dims;
for (const auto &dim : oldAllocInst->getDims()) {
dims.emplace_back(dim->getValue());
}
ss << oldAllocInst->getName() << suffix;
auto newAllocInst =
new AllocaInst(oldAllocInst->getType(), dims, oldNewBlockMap.at(oldAllocInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldAllocInst, newAllocInst);
if (isAddedToCreate.find(oldAllocInst) == isAddedToCreate.end()) {
isAddedToCreate.emplace(oldAllocInst, true);
} else {
isAddedToCreate.at(oldAllocInst) = true;
}
if (isCreated.find(oldAllocInst) == isCreated.end()) {
isCreated.emplace(oldAllocInst, true);
} else {
isCreated.at(oldAllocInst) = true;
}
}
}
}
if (inst->getKind() == Instruction::kAlloca) {
if (oldNewValueMap.find(inst.get()) == oldNewValueMap.end()) {
auto oldAllocInst = dynamic_cast<AllocaInst *>(inst.get());
std::vector<Value *> dims;
for (const auto &dim : oldAllocInst->getDims()) {
dims.emplace_back(dim->getValue());
}
ss << oldAllocInst->getName() << suffix;
auto newAllocInst =
new AllocaInst(oldAllocInst->getType(), dims, oldNewBlockMap.at(oldAllocInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldAllocInst, newAllocInst);
if (isAddedToCreate.find(oldAllocInst) == isAddedToCreate.end()) {
isAddedToCreate.emplace(oldAllocInst, true);
} else {
isAddedToCreate.at(oldAllocInst) = true;
}
if (isCreated.find(oldAllocInst) == isCreated.end()) {
isCreated.emplace(oldAllocInst, true);
} else {
isCreated.at(oldAllocInst) = true;
}
}
}
}
}
for (const auto &oldBlock : blocks) {
for (const auto &inst : oldBlock->getInstructions()) {
for (const auto &valueUse : inst->getOperands()) {
auto value = valueUse->getValue();
if (oldNewValueMap.find(value) == oldNewValueMap.end()) {
auto globalValue = dynamic_cast<GlobalValue *>(value);
auto constVariable = dynamic_cast<ConstantVariable *>(value);
auto constantValue = dynamic_cast<ConstantValue *>(value);
auto functionValue = dynamic_cast<Function *>(value);
if (globalValue != nullptr || constantValue != nullptr || constVariable != nullptr ||
functionValue != nullptr) {
if (functionValue == this) {
oldNewValueMap.emplace(value, newFunction);
} else {
oldNewValueMap.emplace(value, value);
}
isCreated.emplace(value, true);
isAddedToCreate.emplace(value, true);
}
}
}
}
}
for (const auto &oldBlock : blocks) {
for (const auto &inst : oldBlock->getInstructions()) {
if (inst->getKind() != Instruction::kAlloca) {
bool isReady = true;
for (const auto &use : inst->getOperands()) {
auto value = use->getValue();
if (dynamic_cast<BasicBlock *>(value) == nullptr && !isCreated.at(value)) {
isReady = false;
break;
}
}
if (isReady) {
toCreate.push(inst.get());
isAddedToCreate.at(inst.get()) = true;
}
}
}
}
while (!toCreate.empty()) {
auto inst = dynamic_cast<Instruction *>(toCreate.front());
toCreate.pop();
bool isReady = true;
for (const auto &valueUse : inst->getOperands()) {
auto value = dynamic_cast<Instruction *>(valueUse->getValue());
if (value != nullptr && !isCreated.at(value)) {
isReady = false;
break;
}
}
if (!isReady) {
toCreate.push(inst);
continue;
}
isCreated.at(inst) = true;
switch (inst->getKind()) {
case Instruction::kAdd:
case Instruction::kSub:
case Instruction::kMul:
case Instruction::kDiv:
case Instruction::kRem:
case Instruction::kICmpEQ:
case Instruction::kICmpNE:
case Instruction::kICmpLT:
case Instruction::kICmpGT:
case Instruction::kICmpLE:
case Instruction::kICmpGE:
case Instruction::kAnd:
case Instruction::kOr:
case Instruction::kFAdd:
case Instruction::kFSub:
case Instruction::kFMul:
case Instruction::kFDiv:
case Instruction::kFCmpEQ:
case Instruction::kFCmpNE:
case Instruction::kFCmpLT:
case Instruction::kFCmpGT:
case Instruction::kFCmpLE:
case Instruction::kFCmpGE: {
auto oldBinaryInst = dynamic_cast<BinaryInst *>(inst);
auto lhs = oldBinaryInst->getLhs();
auto rhs = oldBinaryInst->getRhs();
Value *newLhs;
Value *newRhs;
newLhs = oldNewValueMap[lhs];
newRhs = oldNewValueMap[rhs];
ss << oldBinaryInst->getName() << suffix;
auto newBinaryInst = new BinaryInst(oldBinaryInst->getKind(), oldBinaryInst->getType(), newLhs, newRhs,
oldNewBlockMap.at(oldBinaryInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldBinaryInst, newBinaryInst);
break;
}
case Instruction::kNeg:
case Instruction::kNot:
case Instruction::kFNeg:
case Instruction::kFNot:
case Instruction::kItoF:
case Instruction::kFtoI: {
auto oldUnaryInst = dynamic_cast<UnaryInst *>(inst);
auto hs = oldUnaryInst->getOperand();
Value *newHs;
newHs = oldNewValueMap.at(hs);
ss << oldUnaryInst->getName() << suffix;
auto newUnaryInst = new UnaryInst(oldUnaryInst->getKind(), oldUnaryInst->getType(), newHs,
oldNewBlockMap.at(oldUnaryInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldUnaryInst, newUnaryInst);
break;
}
case Instruction::kCall: {
auto oldCallInst = dynamic_cast<CallInst *>(inst);
std::vector<Value *> newArgumnts;
for (const auto &arg : oldCallInst->getArguments()) {
newArgumnts.emplace_back(oldNewValueMap.at(arg->getValue()));
}
ss << oldCallInst->getName() << suffix;
CallInst *newCallInst;
newCallInst =
new CallInst(oldCallInst->getCallee(), newArgumnts, oldNewBlockMap.at(oldCallInst->getParent()), ss.str());
ss.str("");
// if (oldCallInst->getCallee() != this) {
// newCallInst = new CallInst(oldCallInst->getCallee(), newArgumnts,
// oldNewBlockMap.at(oldCallInst->getParent()),
// oldCallInst->getName());
// } else {
// newCallInst = new CallInst(newFunction, newArgumnts, oldNewBlockMap.at(oldCallInst->getParent()),
// oldCallInst->getName());
// }
oldNewValueMap.emplace(oldCallInst, newCallInst);
break;
}
case Instruction::kCondBr: {
auto oldCondBrInst = dynamic_cast<CondBrInst *>(inst);
auto oldCond = oldCondBrInst->getCondition();
Value *newCond;
newCond = oldNewValueMap.at(oldCond);
auto newCondBrInst = new CondBrInst(newCond, oldNewBlockMap.at(oldCondBrInst->getThenBlock()),
oldNewBlockMap.at(oldCondBrInst->getElseBlock()), {}, {},
oldNewBlockMap.at(oldCondBrInst->getParent()));
oldNewValueMap.emplace(oldCondBrInst, newCondBrInst);
break;
}
case Instruction::kBr: {
auto oldBrInst = dynamic_cast<UncondBrInst *>(inst);
auto newBrInst =
new UncondBrInst(oldNewBlockMap.at(oldBrInst->getBlock()), {}, oldNewBlockMap.at(oldBrInst->getParent()));
oldNewValueMap.emplace(oldBrInst, newBrInst);
break;
}
case Instruction::kReturn: {
auto oldReturnInst = dynamic_cast<ReturnInst *>(inst);
auto oldRval = oldReturnInst->getReturnValue();
Value *newRval = nullptr;
if (oldRval != nullptr) {
newRval = oldNewValueMap.at(oldRval);
}
auto newReturnInst =
new ReturnInst(newRval, oldNewBlockMap.at(oldReturnInst->getParent()), oldReturnInst->getName());
oldNewValueMap.emplace(oldReturnInst, newReturnInst);
break;
}
case Instruction::kAlloca: {
assert(false);
}
case Instruction::kLoad: {
auto oldLoadInst = dynamic_cast<LoadInst *>(inst);
auto oldPointer = oldLoadInst->getPointer();
Value *newPointer;
newPointer = oldNewValueMap.at(oldPointer);
std::vector<Value *> newIndices;
for (const auto &index : oldLoadInst->getIndices()) {
newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
}
ss << oldLoadInst->getName() << suffix;
auto newLoadInst = new LoadInst(newPointer, newIndices, oldNewBlockMap.at(oldLoadInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldLoadInst, newLoadInst);
break;
}
case Instruction::kStore: {
auto oldStoreInst = dynamic_cast<StoreInst *>(inst);
auto oldPointer = oldStoreInst->getPointer();
auto oldValue = oldStoreInst->getValue();
Value *newPointer;
Value *newValue;
std::vector<Value *> newIndices;
newPointer = oldNewValueMap.at(oldPointer);
newValue = oldNewValueMap.at(oldValue);
for (const auto &index : oldStoreInst->getIndices()) {
newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
}
auto newStoreInst = new StoreInst(newValue, newPointer, newIndices,
oldNewBlockMap.at(oldStoreInst->getParent()), oldStoreInst->getName());
oldNewValueMap.emplace(oldStoreInst, newStoreInst);
break;
}
// TODO复制GEP指令
case Instruction::kMemset: {
auto oldMemsetInst = dynamic_cast<MemsetInst *>(inst);
auto oldPointer = oldMemsetInst->getPointer();
auto oldValue = oldMemsetInst->getValue();
Value *newPointer;
Value *newValue;
newPointer = oldNewValueMap.at(oldPointer);
newValue = oldNewValueMap.at(oldValue);
auto newMemsetInst = new MemsetInst(newPointer, oldMemsetInst->getBegin(), oldMemsetInst->getSize(), newValue,
oldNewBlockMap.at(oldMemsetInst->getParent()), oldMemsetInst->getName());
oldNewValueMap.emplace(oldMemsetInst, newMemsetInst);
break;
}
case Instruction::kInvalid:
case Instruction::kPhi: {
break;
}
default:
assert(false);
}
for (const auto &userUse : inst->getUses()) {
auto user = userUse->getUser();
if (!isAddedToCreate.at(user)) {
toCreate.push(user);
isAddedToCreate.at(user) = true;
}
}
}
for (const auto &oldBlock : blocks) {
auto newBlock = oldNewBlockMap.at(oldBlock.get());
builder.setPosition(newBlock, newBlock->end());
for (const auto &inst : oldBlock->getInstructions()) {
builder.insertInst(dynamic_cast<Instruction *>(oldNewValueMap.at(inst.get())));
}
}
// for (const auto &param : blocks.front()->getArguments()) {
// newFunction->getEntryBlock()->insertArgument(dynamic_cast<AllocaInst *>(oldNewValueMap.at(param)));
// }
for (const auto &arg : arguments) {
auto newArg = dynamic_cast<Argument *>(oldNewValueMap.at(arg));
if (newArg != nullptr) {
newFunction->insertArgument(newArg);
}
}
return newFunction;
}
/**
* 设置操作数
*/
void User::setOperand(unsigned index, Value *value) {
assert(index < getNumOperands());
operands[index]->setValue(value);
value->addUse(operands[index]);
}
/**
* 替换操作数
*/
void User::replaceOperand(unsigned index, Value *value) {
assert(index < getNumOperands());
auto &use = operands[index];
use->getValue()->removeUse(use);
use->setValue(value);
value->addUse(use);
}
/**
* phi相关函数
*/
Value* PhiInst::getvalfromBlk(BasicBlock* blk){
refreshB2VMap();
if( blk2val.find(blk) != blk2val.end()) {
return blk2val.at(blk);
}
return nullptr;
}
BasicBlock* PhiInst::getBlkfromVal(Value* val){
// 返回第一个值对应的基本块
for(unsigned i = 0; i < vsize; i++) {
if(getValue(i) == val) {
return getBlock(i);
}
}
return nullptr;
}
void PhiInst::delValue(Value* val){
//根据value删除对应的基本块和值
unsigned i = 0;
BasicBlock* blk = getBlkfromVal(val);
for(i = 0; i < vsize; i++) {
if(getValue(i) == val) {
break;
}
}
removeOperand(2 * i + 1); // 删除blk
removeOperand(2 * i); // 删除val
vsize--;
blk2val.erase(blk); // 删除blk2val映射
}
void PhiInst::delBlk(BasicBlock* blk){
//根据Blk删除对应的基本块和值
unsigned i = 0;
Value* val = getvalfromBlk(blk);
for(i = 0; i < vsize; i++) {
if(getBlock(i) == blk) {
break;
}
}
removeOperand(2 * i + 1); // 删除blk
removeOperand(2 * i); // 删除val
vsize--;
blk2val.erase(blk); // 删除blk2val映射
}
void PhiInst::replaceBlk(BasicBlock* newBlk, unsigned k){
refreshB2VMap();
Value* val = blk2val.at(getBlock(k));
// 替换基本块
setOperand(2 * k + 1, newBlk);
// 替换blk2val映射
blk2val.erase(getBlock(k));
blk2val.emplace(newBlk, val);
}
void PhiInst::replaceold2new(BasicBlock* oldBlk, BasicBlock* newBlk){
refreshB2VMap();
Value* val = blk2val.at(oldBlk);
// 替换基本块
delBlk(oldBlk);
addIncoming(val, newBlk);
}
void PhiInst::refreshB2VMap(){
blk2val.clear();
for(unsigned i = 0; i < vsize; i++) {
blk2val.emplace(getBlock(i), getValue(i));
}
}
CallInst::CallInst(Function *callee, const std::vector<Value *> &args, BasicBlock *parent, const std::string &name)
: Instruction(kCall, callee->getReturnType(), parent, name) {
addOperand(callee);
for (auto arg : args) {
addOperand(arg);
}
}
/**
* 获取被调用函数的指针
*/
Function * CallInst::getCallee() const { return dynamic_cast<Function *>(getOperand(0)); }
/**
* 获取变量指针
*/
auto SymbolTable::getVariable(const std::string &name) const -> Value * {
auto node = curNode;
while (node != nullptr) {
auto iter = node->varList.find(name);
if (iter != node->varList.end()) {
return iter->second;
}
node = node->pNode;
}
return nullptr;
}
/**
* 添加变量到符号表
*/
auto SymbolTable::addVariable(const std::string &name, Value *variable) -> Value * {
Value *result = nullptr;
if (curNode != nullptr) {
std::stringstream ss;
auto iter = variableIndex.find(name);
if (iter != variableIndex.end()) {
ss << name << iter->second ;
iter->second += 1;
} else {
variableIndex.emplace(name, 1);
ss << name << 0 ;
}
variable->setName(ss.str());
curNode->varList.emplace(name, variable);
auto global = dynamic_cast<GlobalValue *>(variable);
auto constvar = dynamic_cast<ConstantVariable *>(variable);
if (global != nullptr) {
globals.emplace_back(global);
} else if (constvar != nullptr) {
consts.emplace_back(constvar);
}
result = variable;
}
return result;
}
/**
* 获取全局变量
*/
auto SymbolTable::getGlobals() -> std::vector<std::unique_ptr<GlobalValue>> & { return globals; }
/**
* 获取常量
*/
auto SymbolTable::getConsts() const -> const std::vector<std::unique_ptr<ConstantVariable>> & { return consts; }
/**
* 进入新的作用域
*/
void SymbolTable::enterNewScope() {
auto newNode = new SymbolTableNode;
nodeList.emplace_back(newNode);
if (curNode != nullptr) {
curNode->children.emplace_back(newNode);
}
newNode->pNode = curNode;
curNode = newNode;
}
/**
* 进入全局作用域
*/
void SymbolTable::enterGlobalScope() { curNode = nodeList.front().get(); }
/**
* 离开作用域
*/
void SymbolTable::leaveScope() { curNode = curNode->pNode; }
/**
* 是否位于全局作用域
*/
auto SymbolTable::isInGlobalScope() const -> bool { return curNode->pNode == nullptr; }
/**
*移动指令
*/
auto BasicBlock::moveInst(iterator sourcePos, iterator targetPos, BasicBlock *block) -> iterator {
auto inst = sourcePos->release();
inst->setParent(block);
block->instructions.emplace(targetPos, inst);
return instructions.erase(sourcePos);
}
} // namespace sysy

View File

@ -1,142 +0,0 @@
#include "RISCv64Backend.h"
#include "RISCv64ISel.h"
#include "RISCv64RegAlloc.h"
#include "RISCv64AsmPrinter.h"
#include "RISCv64Passes.h" // 包含优化Pass的头文件
#include <sstream>
namespace sysy {
// 顶层入口
std::string RISCv64CodeGen::code_gen() {
return module_gen();
}
// 模块级代码生成
std::string RISCv64CodeGen::module_gen() {
std::stringstream ss;
// --- [新逻辑] 步骤1将全局变量分为.data和.bss两组 ---
std::vector<GlobalValue*> data_globals;
std::vector<GlobalValue*> bss_globals;
for (const auto& global_ptr : module->getGlobals()) {
GlobalValue* global = global_ptr.get();
const auto& init_values = global->getInitValues();
// 判断是否为大型零初始化数组,以便放入.bss段
bool is_large_zero_array = false;
// 规则初始化列表只有一项且该项是值为0的整数且数量大于一个阈值例如16
if (init_values.getValues().size() == 1) {
if (auto const_val = dynamic_cast<ConstantValue*>(init_values.getValues()[0])) {
if (const_val->isInt() && const_val->getInt() == 0 && init_values.getNumbers()[0] > 16) {
is_large_zero_array = true;
}
}
}
if (is_large_zero_array) {
bss_globals.push_back(global);
} else {
data_globals.push_back(global);
}
}
// --- [新逻辑] 步骤2生成 .bss 段的代码 ---
if (!bss_globals.empty()) {
ss << ".bss\n"; // 切换到 .bss 段
for (GlobalValue* global : bss_globals) {
// 获取数组总大小(元素个数 * 元素大小)
// 在SysY中我们假设元素都是4字节int或float
unsigned count = global->getInitValues().getNumbers()[0];
unsigned total_size = count * 4;
ss << " .align 3\n"; // 8字节对齐 (2^3)
ss << ".globl " << global->getName() << "\n";
ss << ".type " << global->getName() << ", @object\n";
ss << ".size " << global->getName() << ", " << total_size << "\n";
ss << global->getName() << ":\n";
// 使用 .space 指令来预留指定大小的零填充空间
ss << " .space " << total_size << "\n";
}
}
// --- [旧逻辑保留] 步骤3生成 .data 段的代码 ---
if (!data_globals.empty()) {
ss << ".data\n"; // 切换到 .data 段
for (GlobalValue* global : data_globals) {
ss << ".globl " << global->getName() << "\n";
ss << global->getName() << ":\n";
const auto& init_values = global->getInitValues();
// 使用您原有的逻辑来处理显式初始化的值
for (size_t i = 0; i < init_values.getValues().size(); ++i) {
auto val = init_values.getValues()[i];
auto count = init_values.getNumbers()[i];
if (auto constant = dynamic_cast<ConstantValue*>(val)) {
for (unsigned j = 0; j < count; ++j) {
if (constant->isInt()) {
ss << " .word " << constant->getInt() << "\n";
} else {
float f = constant->getFloat();
uint32_t float_bits = *(uint32_t*)&f;
ss << " .word " << float_bits << "\n";
}
}
}
}
}
}
// --- 处理函数 (.text段) 的逻辑保持不变 ---
if (!module->getFunctions().empty()) {
ss << ".text\n";
for (const auto& func_pair : module->getFunctions()) {
if (func_pair.second.get()) {
ss << function_gen(func_pair.second.get());
}
}
}
return ss.str();
}
// function_gen 现在是包含具体优化名称的、完整的处理流水线
std::string RISCv64CodeGen::function_gen(Function* func) {
// === 完整的后端处理流水线 ===
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
RISCv64ISel isel;
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
std::stringstream ss1;
RISCv64AsmPrinter printer1(mfunc.get());
printer1.run(ss1, true);
// 阶段 2: 指令调度 (Instruction Scheduling)
PreRA_Scheduler scheduler;
scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3: 物理寄存器分配 (Register Allocation)
RISCv64RegAlloc reg_alloc(mfunc.get());
reg_alloc.run();
// 阶段 3.5: 处理被调用者保存寄存器
CalleeSavedHandler callee_handler;
callee_handler.runOnMachineFunction(mfunc.get());
// 阶段 4: 窥孔优化 (Peephole Optimization)
PeepholeOptimizer peephole;
peephole.runOnMachineFunction(mfunc.get());
// 阶段 5: 局部指令调度 (Local Scheduling)
PostRA_Scheduler local_scheduler;
local_scheduler.runOnMachineFunction(mfunc.get());
// 阶段 6: 代码发射 (Code Emission)
std::stringstream ss;
RISCv64AsmPrinter printer(mfunc.get());
printer.run(ss);
if (DEBUG) ss << "\n" << ss1.str(); // 将指令选择阶段的结果也包含在最终输出中
return ss.str();
}
} // namespace sysy

View File

@ -1,6 +0,0 @@
#include "RISCv64LLIR.h"
#include <vector>
namespace sysy {
}

View File

@ -1,149 +0,0 @@
#include "RISCv64Passes.h"
#include <iostream>
namespace sysy {
// --- 寄存器分配前优化 ---
void PreRA_Scheduler::runOnMachineFunction(MachineFunction* mfunc) {
// TODO: 在此实现寄存器分配前的指令调度。
// 遍历mfunc中的每一个MachineBasicBlock。
// 对每个基本块内的MachineInstr列表进行重排。
//
// 实现思路:
// 1. 分析每个基本块内指令的数据依赖关系,构建依赖图(DAG)。
// 2. 根据目标处理器的流水线特性(指令延迟等),使用列表调度等算法对指令进行重排。
// 3. 此时操作的是虚拟寄存器,只存在真依赖,调度自由度最大。
//
// std::cout << "Running Pre-RA Instruction Scheduler..." << std::endl;
}
// --- 寄存器分配后优化 ---
void PeepholeOptimizer::runOnMachineFunction(MachineFunction* mfunc) {
// TODO: 在此实现窥孔优化。
// 遍历mfunc中的每一个MachineBasicBlock。
// 对每个基本块内的MachineInstr列表进行扫描和替换。
//
// 实现思路:
// 1. 维护一个大小固定例如3-5条指令的滑动窗口。
// 2. 识别特定的冗余模式,例如:
// - `mv a0, a1` 后紧跟 `mv a1, a0` (可消除的交换)
// - `sw t0, 12(s0)` 后紧跟 `lw t1, 12(s0)` (冗余加载)
// - 强度削减: `mul x, x, 2` -> `slli x, x, 1`
// 3. 识别后直接修改MachineInstr列表删除、替换或插入指令
//
// std::cout << "Running Post-RA Peephole Optimizer..." << std::endl;
}
void PostRA_Scheduler::runOnMachineFunction(MachineFunction* mfunc) {
// TODO: 在此实现寄存器分配后的局部指令调度。
// 遍历mfunc中的每一个MachineBasicBlock。
// 重点关注由寄存器分配器插入的spill/fill代码。
//
// 实现思路:
// 1. 识别出用于spill/fill的lw/sw指令。
// 2. 在不违反数据依赖(包括物理寄存器引入的伪依赖)的前提下,
// 尝试将lw指令向上移动使其与使用它的指令之间有足够的距离以隐藏访存延迟。
// 3. 同样可以尝试将sw指令向下移动。
//
// std::cout << "Running Post-RA Local Scheduler..." << std::endl;
}
void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
StackFrameInfo& frame_info = mfunc->getFrameInfo();
std::set<PhysicalReg> used_callee_saved;
// 1. 扫描所有指令找出被使用的s寄存器
for (auto& mbb : mfunc->getBlocks()) {
for (auto& instr : mbb->getInstructions()) {
for (auto& op : instr->getOperands()) {
// 辅助Lambda用于检查和插入寄存器
auto check_and_insert_reg = [&](RegOperand* reg_op) {
if (!reg_op->isVirtual()) {
PhysicalReg preg = reg_op->getPReg();
// --- 关键检查点 ---
// 必须严格判断是否在 s0-s11 的范围内。
// a0, t0 等寄存器绝对不应被视为被调用者保存寄存器。
if (preg >= PhysicalReg::S0 && preg <= PhysicalReg::S11) {
used_callee_saved.insert(preg);
}
}
};
if (op->getKind() == MachineOperand::KIND_REG) {
check_and_insert_reg(static_cast<RegOperand*>(op.get()));
} else if (op->getKind() == MachineOperand::KIND_MEM) {
check_and_insert_reg(static_cast<MemOperand*>(op.get())->getBase());
}
}
}
}
// 如果没有使用s寄存器除了可能作为帧指针的s0则无需操作
if (used_callee_saved.empty() || (used_callee_saved.size() == 1 && used_callee_saved.count(PhysicalReg::S0))) {
return;
}
// 将结果存入StackFrameInfo供后续使用
frame_info.used_callee_saved_regs = used_callee_saved;
// 2. 在函数序言插入保存指令
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
auto& entry_instrs = entry_block->getInstructions();
auto prologue_end = entry_instrs.begin();
// 找到序言结束的位置通常是addi s0, sp, size之后
for (auto it = entry_instrs.begin(); it != entry_instrs.end(); ++it) {
if ((*it)->getOpcode() == RVOpcodes::ADDI &&
(*it)->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
static_cast<RegOperand*>((*it)->getOperands()[0].get())->getPReg() == PhysicalReg::S0)
{
prologue_end = std::next(it);
break;
}
}
// 为了栈帧布局确定性,对寄存器进行排序
std::vector<PhysicalReg> sorted_regs(used_callee_saved.begin(), used_callee_saved.end());
std::sort(sorted_regs.begin(), sorted_regs.end());
int current_offset = -16; // ra和s0已经占用了-8和-16的位置
for (PhysicalReg reg : sorted_regs) {
if (reg == PhysicalReg::S0) continue; // s0已经在序言中处理
current_offset -= 8;
auto sd = std::make_unique<MachineInstr>(RVOpcodes::SD);
sd->addOperand(std::make_unique<RegOperand>(reg));
sd->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0), // 假设s0是帧指针
std::make_unique<ImmOperand>(current_offset)
));
entry_instrs.insert(prologue_end, std::move(sd));
}
// 3. 在函数结尾ret之前插入恢复指令
for (auto& mbb : mfunc->getBlocks()) {
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
if ((*it)->getOpcode() == RVOpcodes::RET) {
// 以相反的顺序恢复
current_offset = -16;
for (PhysicalReg reg : sorted_regs) {
if (reg == PhysicalReg::S0) continue;
current_offset -= 8;
auto ld = std::make_unique<MachineInstr>(RVOpcodes::LD);
ld->addOperand(std::make_unique<RegOperand>(reg));
ld->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(current_offset)
));
mbb->getInstructions().insert(it, std::move(ld));
}
break; // 处理完一个基本块的ret即可
}
}
}
}
} // namespace sysy

View File

@ -1,595 +0,0 @@
#include "RISCv64RegAlloc.h"
#include "RISCv64ISel.h"
#include <algorithm>
#include <vector>
#include <iostream> // For DEBUG output
#include <cassert> // For assert
namespace sysy {
RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc) : MFunc(mfunc) {
allocable_int_regs = {
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3,
PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6,
PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3,
PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7,
PhysicalReg::S0, PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3,
PhysicalReg::S4, PhysicalReg::S5, PhysicalReg::S6, PhysicalReg::S7,
PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11,
};
// 映射物理寄存器到特殊的虚拟寄存器ID用于干扰图中的物理寄存器节点
// 确保这些特殊ID不会与vreg_counter生成的常规虚拟寄存器ID冲突
for (PhysicalReg preg : allocable_int_regs) {
preg_to_vreg_id_map[preg] = static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID) + static_cast<unsigned>(preg);
}
}
// 寄存器分配的主入口点
void RISCv64RegAlloc::run() {
// 阶段 1: 处理函数调用约定(参数寄存器预着色)
handleCallingConvention();
// 阶段 2: 消除帧索引(为局部变量和栈参数分配栈偏移)
eliminateFrameIndices();
// 阶段 3: 活跃性分析
analyzeLiveness();
// 阶段 4: 构建干扰图包含CALL指令对调用者保存寄存器的影响
buildInterferenceGraph();
// 阶段 5: 图着色算法分配物理寄存器
colorGraph();
// 阶段 6: 重写函数(插入溢出/填充代码,替换虚拟寄存器为物理寄存器)
rewriteFunction();
}
/**
* @brief 处理调用约定,预先为函数参数分配物理寄存器。
*/
void RISCv64RegAlloc::handleCallingConvention() {
Function* F = MFunc->getFunc();
RISCv64ISel* isel = MFunc->getISel();
// 获取函数的Argument对象列表
if (F) {
auto& args = F->getArguments();
// RISC-V RV64G调用约定前8个整型/指针参数通过 a0-a7 传递
int arg_idx = 0;
// 遍历 AllocaInst* 列表
for (Argument* arg : args) {
if (arg_idx >= 8) {
break;
}
// 获取该 Argument 对象对应的虚拟寄存器ID
// 通过 MachineFunction -> RISCv64ISel -> vreg_map 来获取
const auto& vreg_map_from_isel = MFunc->getISel()->getVRegMap();
assert(vreg_map_from_isel.count(arg) && "Argument not found in ISel's vreg_map!");
// 1. 获取该 Argument 对象对应的虚拟寄存器
unsigned vreg = isel->getVReg(arg);
// 2. 根据参数索引,确定对应的物理寄存器 (a0, a1, ...)
auto preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + arg_idx);
// 3. 在 color_map 中,将 vreg "预着色" 为对应的物理寄存器
color_map[vreg] = preg;
arg_idx++;
}
}
}
/**
* @brief 消除帧索引,为局部变量和栈参数分配栈偏移量,并展开伪指令。
*/
void RISCv64RegAlloc::eliminateFrameIndices() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
// 初始偏移量为保存ra和s0留出空间。
// 假设序言是 addi sp, sp, -stack_size; sd ra, stack_size-8(sp); sd s0, stack_size-16(sp);
int current_offset = 16;
Function* F = MFunc->getFunc();
RISCv64ISel* isel = MFunc->getISel();
// 在处理局部变量前,首先为栈参数计算偏移量。
if (F) {
int arg_idx = 0;
for (Argument* arg : F->getArguments()) {
// 我们只关心第8个索引及之后的参数即第9个参数开始
if (arg_idx >= 8) {
// 计算偏移量:第一个栈参数(idx=8)在0(s0),第二个(idx=9)在8(s0),以此类推。
int offset = (arg_idx - 8) * 8;
unsigned vreg = isel->getVReg(arg);
// 将这个vreg和它的栈偏移存入map。
// 我们可以复用alloca_offsets因为它们都代表“vreg到栈偏移”的映射。
frame_info.alloca_offsets[vreg] = offset;
}
arg_idx++;
}
}
// 处理局部变量
// 遍历AllocaInst来计算局部变量所需的总空间
for (auto& bb : F->getBasicBlocks()) {
for (auto& inst : bb->getInstructions()) {
if (auto alloca = dynamic_cast<AllocaInst*>(inst.get())) {
// 获取Alloca指令指向的类型 (例如 alloca i32* 中,获取 i32)
Type* allocated_type = alloca->getType()->as<PointerType>()->getBaseType();
int size = getTypeSizeInBytes(allocated_type);
// RISC-V要求栈地址8字节对齐
size = (size + 7) & ~7;
if (size == 0) size = 8; // 至少分配8字节
current_offset += size;
unsigned alloca_vreg = isel->getVReg(alloca);
// 局部变量使用相对于s0的负向偏移
frame_info.alloca_offsets[alloca_vreg] = -current_offset;
}
}
}
frame_info.locals_size = current_offset;
// 遍历所有机器指令,将伪指令展开为真实指令
for (auto& mbb : MFunc->getBlocks()) {
std::vector<std::unique_ptr<MachineInstr>> new_instructions;
for (auto& instr_ptr : mbb->getInstructions()) {
RVOpcodes opcode = instr_ptr->getOpcode();
// --- MODIFICATION START: 处理区分宽度的伪指令 ---
if (opcode == RVOpcodes::FRAME_LOAD_W || opcode == RVOpcodes::FRAME_LOAD_D) {
// 确定要生成的真实加载指令是 lw 还是 ld
RVOpcodes real_load_op = (opcode == RVOpcodes::FRAME_LOAD_W) ? RVOpcodes::LW : RVOpcodes::LD;
auto& operands = instr_ptr->getOperands();
unsigned dest_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
int offset = frame_info.alloca_offsets.at(alloca_vreg);
auto addr_vreg = isel->getNewVReg();
// 展开为: addi addr_vreg, s0, offset
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
addi->addOperand(std::make_unique<RegOperand>(addr_vreg));
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
addi->addOperand(std::make_unique<ImmOperand>(offset));
new_instructions.push_back(std::move(addi));
// 展开为: lw/ld dest_vreg, 0(addr_vreg)
auto load_instr = std::make_unique<MachineInstr>(real_load_op);
load_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
load_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)));
new_instructions.push_back(std::move(load_instr));
} else if (opcode == RVOpcodes::FRAME_STORE_W || opcode == RVOpcodes::FRAME_STORE_D) {
// 确定要生成的真实存储指令是 sw 还是 sd
RVOpcodes real_store_op = (opcode == RVOpcodes::FRAME_STORE_W) ? RVOpcodes::SW : RVOpcodes::SD;
auto& operands = instr_ptr->getOperands();
unsigned src_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
int offset = frame_info.alloca_offsets.at(alloca_vreg);
auto addr_vreg = isel->getNewVReg();
// 展开为: addi addr_vreg, s0, offset
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
addi->addOperand(std::make_unique<RegOperand>(addr_vreg));
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
addi->addOperand(std::make_unique<ImmOperand>(offset));
new_instructions.push_back(std::move(addi));
// 展开为: sw/sd src_vreg, 0(addr_vreg)
auto store_instr = std::make_unique<MachineInstr>(real_store_op);
store_instr->addOperand(std::make_unique<RegOperand>(src_vreg));
store_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)));
new_instructions.push_back(std::move(store_instr));
} else if (instr_ptr->getOpcode() == RVOpcodes::FRAME_ADDR) {
auto& operands = instr_ptr->getOperands();
unsigned dest_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
int offset = frame_info.alloca_offsets.at(alloca_vreg);
// 将 `frame_addr rd, rs` 展开为 `addi rd, s0, offset`
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
addi->addOperand(std::make_unique<RegOperand>(dest_vreg));
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
addi->addOperand(std::make_unique<ImmOperand>(offset));
new_instructions.push_back(std::move(addi));
} else {
new_instructions.push_back(std::move(instr_ptr));
}
// --- MODIFICATION END ---
}
mbb->getInstructions() = std::move(new_instructions);
}
}
/**
* @brief 计算给定 MachineInstr 的 Use (读取) 和 Def (写入) 寄存器集合。
* 这是活跃性分析的基础。
* @param instr 要分析的机器指令。
* @param use 存储 Use 寄存器(虚拟寄存器 ID的集合。
* @param def 存储 Def 寄存器(虚拟寄存器 ID的集合。
*/
void RISCv64RegAlloc::getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet& def) {
bool first_reg_is_def = true; // 默认情况下,指令的第一个寄存器操作数是定义 (def)
auto opcode = instr->getOpcode();
// 1. 特殊指令的 `is_def` 标志调整
// 这些指令的第一个寄存器操作数是源操作数 (use),而不是目标操作数 (def)。
if (opcode == RVOpcodes::SW || opcode == RVOpcodes::SD ||
opcode == RVOpcodes::BEQ || opcode == RVOpcodes::BNE ||
opcode == RVOpcodes::BLT || opcode == RVOpcodes::BGE ||
opcode == RVOpcodes::BLTU || opcode == RVOpcodes::BGEU ||
opcode == RVOpcodes::RET || opcode == RVOpcodes::J) {
first_reg_is_def = false;
}
// JAL 和 JALR 指令定义 ra (x1)
if (opcode == RVOpcodes::JAL || opcode == RVOpcodes::JALR) {
// 使用 ra 对应的特殊虚拟寄存器ID
def.insert(static_cast<unsigned>(PhysicalReg::RA));
first_reg_is_def = false; // JAL/JALR 的第一个操作数是 ra已经处理为 def
}
// 2. CALL 指令的特殊处理
if (opcode == RVOpcodes::CALL) {
// 1.1 处理返回值 (def)
// 约定如果CALL指令有返回值IR阶段会将返回值vreg作为指令的第一个操作数。
if (!instr->getOperands().empty() && instr->getOperands().front()->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand*>(instr->getOperands().front().get());
if (reg_op->isVirtual()) {
def.insert(reg_op->getVRegNum());
}
}
// 1.2 处理参数 (use)
// 参数通常是指令的后续操作数
bool first_operand_processed = false; // 用于跳过已作为def处理的返回值
for (const auto& op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) {
if (!first_operand_processed) { // 如果是第一个操作数
first_operand_processed = true;
// 如果第一个操作数是返回值已被加入def则跳过
if (def.count(static_cast<RegOperand*>(op.get())->getVRegNum())) {
continue;
}
}
// 否则,该寄存器是 use
auto reg_op = static_cast<RegOperand*>(op.get());
if (reg_op->isVirtual()) {
use.insert(reg_op->getVRegNum());
}
}
}
// **重要**: CALL指令隐式定义杀死了所有调用者保存的寄存器。
// **这部分逻辑不在getInstrUseDef中直接处理**。
// 而是通过`buildInterferenceGraph`中添加物理寄存器节点与活跃虚拟寄存器之间的干扰边来完成。
// 这样 Liveness Analysis 可以在虚拟寄存器层面进行,而物理寄存器干扰的复杂性则留给干扰图。
return; // CALL 指令处理完毕,直接返回
}
// 3. 对其他所有指令的通用处理逻辑
for (const auto& op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand*>(op.get());
if (reg_op->isVirtual()) { // 只有虚拟寄存器才需要处理 Use/Def
// 如果是第一个寄存器操作数,且指令类型表明它是定义 (def),则加入 def 集合
// 否则,它是 use (读取)
if (first_reg_is_def) {
def.insert(reg_op->getVRegNum());
first_reg_is_def = false; // 确保每条指令只定义一个目标寄存器
} else {
use.insert(reg_op->getVRegNum());
}
}
} else if (op->getKind() == MachineOperand::KIND_MEM) {
// 内存操作数 `offset(base)` 中的 `base` 寄存器是 `use`
auto mem_op = static_cast<MemOperand*>(op.get());
if (mem_op->getBase()->isVirtual()) {
use.insert(mem_op->getBase()->getVRegNum());
}
// 对于存储内存指令 (SW, SD),要存储的值(第一个操作数)也是 `use`
if ((opcode == RVOpcodes::SW || opcode == RVOpcodes::SD) &&
!instr->getOperands().empty() && // 确保有操作数
instr->getOperands().front()->getKind() == MachineOperand::KIND_REG) { // 且第一个操作数是寄存器
auto src_reg_op = static_cast<RegOperand*>(instr->getOperands().front().get());
if (src_reg_op->isVirtual()) {
use.insert(src_reg_op->getVRegNum());
}
}
}
}
}
/**
* @brief 计算一个类型在内存中占用的字节数。
* @param type 需要计算大小的IR类型。
* @return 该类型占用的字节数。
*/
unsigned RISCv64RegAlloc::getTypeSizeInBytes(Type* type) {
if (!type) {
assert(false && "Cannot get size of a null type.");
return 0;
}
switch (type->getKind()) {
// 对于SysY语言基本类型int和float都占用4字节
case Type::kInt:
case Type::kFloat:
return 4;
// 指针类型在RISC-V 64位架构下占用8字节
// 虽然SysY没有'int*'语法但数组变量在IR层面本身就是指针类型
case Type::kPointer:
return 8;
// 数组类型的总大小 = 元素数量 * 单个元素的大小
case Type::kArray: {
auto arrayType = type->as<ArrayType>();
// 递归调用以计算元素大小
return arrayType->getNumElements() * getTypeSizeInBytes(arrayType->getElementType());
}
// 其他类型如Void, Label等不占用栈空间或者不应该出现在这里
default:
// 如果遇到未处理的类型,触发断言,方便调试
assert(false && "Unsupported type for size calculation.");
return 0;
}
}
void RISCv64RegAlloc::analyzeLiveness() {
bool changed = true;
while (changed) {
changed = false;
for (auto it = MFunc->getBlocks().rbegin(); it != MFunc->getBlocks().rend(); ++it) {
auto& mbb = *it;
LiveSet live_out;
for (auto succ : mbb->successors) {
if (!succ->getInstructions().empty()) {
auto first_instr = succ->getInstructions().front().get();
if (live_in_map.count(first_instr)) {
live_out.insert(live_in_map.at(first_instr).begin(), live_in_map.at(first_instr).end());
}
}
}
for (auto instr_it = mbb->getInstructions().rbegin(); instr_it != mbb->getInstructions().rend(); ++instr_it) {
MachineInstr* instr = instr_it->get();
LiveSet old_live_in = live_in_map[instr];
live_out_map[instr] = live_out;
LiveSet use, def;
getInstrUseDef(instr, use, def);
LiveSet live_in = use;
LiveSet diff = live_out;
for (auto vreg : def) {
diff.erase(vreg);
}
live_in.insert(diff.begin(), diff.end());
live_in_map[instr] = live_in;
live_out = live_in;
if (live_in_map[instr] != old_live_in) {
changed = true;
}
}
}
}
}
void RISCv64RegAlloc::buildInterferenceGraph() {
std::set<unsigned> all_vregs;
// 收集所有虚拟寄存器和物理寄存器在干扰图中的节点ID
for (auto& mbb : MFunc->getBlocks()) {
for(auto& instr : mbb->getInstructions()) {
LiveSet use, def;
getInstrUseDef(instr.get(), use, def);
for(auto u : use) all_vregs.insert(u);
for(auto d : def) all_vregs.insert(d);
}
}
// 添加所有物理寄存器对应的特殊虚拟寄存器ID到all_vregs作为干扰图节点
for (auto preg : allocable_int_regs) {
all_vregs.insert(preg_to_vreg_id_map.at(preg));
}
for (auto vreg : all_vregs) { interference_graph[vreg] = {}; }
for (auto& mbb : MFunc->getBlocks()) {
for (auto& instr : mbb->getInstructions()) {
LiveSet def, use;
getInstrUseDef(instr.get(), use, def);
const LiveSet& live_out = live_out_map.at(instr.get());
// 标准干扰图构建def 与 live_out 中的其他变量干扰
for (unsigned d : def) {
for (unsigned l : live_out) {
if (d != l) {
interference_graph[d].insert(l);
interference_graph[l].insert(d);
}
}
}
// *** 核心修改点:处理 CALL 指令的隐式 def ***
if (instr->getOpcode() == RVOpcodes::CALL) {
// CALL 指令会定义(杀死)所有调用者保存的寄存器。
// 因此,所有调用者保存的物理寄存器都与 CALL 指令的 live_out 中的所有变量冲突。
const std::vector<PhysicalReg>& caller_saved_regs = getCallerSavedIntRegs();
for (PhysicalReg cs_reg : caller_saved_regs) {
unsigned cs_vreg_id = preg_to_vreg_id_map.at(cs_reg); // 获取物理寄存器对应的特殊vreg ID
// 将这个物理寄存器节点与 CALL 指令的 live_out 中的所有虚拟寄存器添加干扰边。
for (unsigned live_vreg_out : live_out) {
if (cs_vreg_id != live_vreg_out) { // 避免自己和自己干扰
interference_graph[cs_vreg_id].insert(live_vreg_out);
interference_graph[live_vreg_out].insert(cs_vreg_id);
}
}
}
}
}
}
}
void RISCv64RegAlloc::colorGraph() {
std::vector<unsigned> sorted_vregs;
for (auto const& [vreg, neighbors] : interference_graph) {
if (color_map.find(vreg) == color_map.end()) {
sorted_vregs.push_back(vreg);
}
}
// 排序
std::sort(sorted_vregs.begin(), sorted_vregs.end(), [&](unsigned a, unsigned b) {
return interference_graph[a].size() > interference_graph[b].size();
});
// 着色
for (unsigned vreg : sorted_vregs) {
std::set<PhysicalReg> used_colors;
for (unsigned neighbor : interference_graph.at(vreg)) {
if (color_map.count(neighbor)) {
used_colors.insert(color_map.at(neighbor));
}
}
bool colored = false;
for (PhysicalReg preg : allocable_int_regs) {
if (used_colors.find(preg) == used_colors.end()) {
color_map[vreg] = preg;
colored = true;
break;
}
}
if (!colored) {
spilled_vregs.insert(vreg);
}
}
}
void RISCv64RegAlloc::rewriteFunction() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
int current_offset = frame_info.locals_size;
// --- FIX 1: 动态计算溢出槽大小 ---
// 根据溢出虚拟寄存器的真实类型,为其在栈上分配正确大小的空间。
for (unsigned vreg : spilled_vregs) {
// 从反向映射中查找 vreg 对应的 IR Value
assert(vreg_to_value_map.count(vreg) && "Spilled vreg not found in map!");
Value* val = vreg_to_value_map.at(vreg);
// 使用辅助函数获取类型大小
int size = getTypeSizeInBytes(val->getType());
// 保持栈8字节对齐
current_offset += size;
current_offset = (current_offset + 7) & ~7;
frame_info.spill_offsets[vreg] = -current_offset;
}
frame_info.spill_size = current_offset - frame_info.locals_size;
for (auto& mbb : MFunc->getBlocks()) {
std::vector<std::unique_ptr<MachineInstr>> new_instructions;
for (auto& instr_ptr : mbb->getInstructions()) {
LiveSet use, def;
getInstrUseDef(instr_ptr.get(), use, def);
// --- FIX 2: 为溢出的 'use' 操作数插入正确的加载指令 ---
for (unsigned vreg : use) {
if (spilled_vregs.count(vreg)) {
// 同样地,根据 vreg 的类型决定使用 lw 还是 ld
assert(vreg_to_value_map.count(vreg));
Value* val = vreg_to_value_map.at(vreg);
RVOpcodes load_op = val->getType()->isPointer() ? RVOpcodes::LD : RVOpcodes::LW;
int offset = frame_info.spill_offsets.at(vreg);
auto load = std::make_unique<MachineInstr>(load_op);
load->addOperand(std::make_unique<RegOperand>(vreg));
load->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(offset)
));
new_instructions.push_back(std::move(load));
}
}
new_instructions.push_back(std::move(instr_ptr));
// --- FIX 3: 为溢出的 'def' 操作数插入正确的存储指令 ---
for (unsigned vreg : def) {
if (spilled_vregs.count(vreg)) {
// 根据 vreg 的类型决定使用 sw 还是 sd
assert(vreg_to_value_map.count(vreg));
Value* val = vreg_to_value_map.at(vreg);
RVOpcodes store_op = val->getType()->isPointer() ? RVOpcodes::SD : RVOpcodes::SW;
int offset = frame_info.spill_offsets.at(vreg);
auto store = std::make_unique<MachineInstr>(store_op);
store->addOperand(std::make_unique<RegOperand>(vreg));
store->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(offset)
));
new_instructions.push_back(std::move(store));
}
}
}
mbb->getInstructions() = std::move(new_instructions);
}
// 最后的虚拟寄存器到物理寄存器的替换过程保持不变
for (auto& mbb : MFunc->getBlocks()) {
for (auto& instr_ptr : mbb->getInstructions()) {
for (auto& op_ptr : instr_ptr->getOperands()) {
// 情况一:操作数本身就是一个寄存器 (例如 add rd, rs1, rs2 中的所有操作数)
if(op_ptr->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand*>(op_ptr.get());
if (reg_op->isVirtual()) {
unsigned vreg = reg_op->getVRegNum();
if (color_map.count(vreg)) {
PhysicalReg preg = color_map.at(vreg);
reg_op->setPReg(preg);
} else if (spilled_vregs.count(vreg)) {
// 如果vreg被溢出替换为专用的溢出物理寄存器t6
reg_op->setPReg(PhysicalReg::T6);
}
}
}
// 情况二:操作数是一个内存地址 (例如 lw rd, offset(rs1) 中的 offset(rs1))
else if (op_ptr->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand*>(op_ptr.get());
// 获取内存操作数内部的“基址寄存器”
auto base_reg_op = mem_op->getBase();
// 对这个基址寄存器,执行与情况一完全相同的替换逻辑
if(base_reg_op->isVirtual()){
unsigned vreg = base_reg_op->getVRegNum();
if(color_map.count(vreg)) {
// 如果基址vreg被成功着色替换
PhysicalReg preg = color_map.at(vreg);
base_reg_op->setPReg(preg);
} else if (spilled_vregs.count(vreg)) {
// 如果基址vreg被溢出替换为t6
base_reg_op->setPReg(PhysicalReg::T6);
}
}
}
}
}
}
}
} // namespace sysy

View File

@ -1,529 +0,0 @@
#include "SysYIRAnalyser.h"
#include <iostream>
namespace sysy {
void ControlFlowAnalysis::init() {
// 初始化分析器
auto &functions = pModule->getFunctions();
for (const auto &function : functions) {
auto func = function.second.get();
auto basicBlocks = func->getBasicBlocks();
for (auto &basicBlock : basicBlocks) {
blockAnalysisInfo[basicBlock.get()] = new BlockAnalysisInfo();
blockAnalysisInfo[basicBlock.get()]->clear();
}
functionAnalysisInfo[func] = new FunctionAnalysisInfo();
functionAnalysisInfo[func]->clear();
}
}
void ControlFlowAnalysis::runControlFlowAnalysis() {
// 运行控制流分析
clear(); // 清空之前的分析结果
init(); // 初始化分析器
computeDomNode();
computeDomTree();
computeDomFrontierAllBlk();
}
void ControlFlowAnalysis::intersectOP4Dom(std::unordered_set<BasicBlock *> &dom, const std::unordered_set<BasicBlock *> &other) {
// 计算交集
for (auto it = dom.begin(); it != dom.end();) {
if (other.find(*it) == other.end()) {
// 如果other中没有这个基本块则从dom中删除
it = dom.erase(it);
} else {
++it;
}
}
}
auto ControlFlowAnalysis::findCommonDominator(BasicBlock *a, BasicBlock *b) -> BasicBlock * {
// 查找两个基本块的共同支配结点
while (a != b) {
BlockAnalysisInfo* infoA = blockAnalysisInfo[a];
BlockAnalysisInfo* infoB = blockAnalysisInfo[b];
// 如果深度不同,则向上移动到直接支配结点
// TODO空间换时间倍增优化优先级较低
while (infoA->getDomDepth() > infoB->getDomDepth()) {
a = const_cast<BasicBlock*>(infoA->getIdom());
infoA = blockAnalysisInfo[a];
}
while (infoB->getDomDepth() > infoA->getDomDepth()) {
b = const_cast<BasicBlock*>(infoB->getIdom());
infoB = blockAnalysisInfo[b];
}
if (a == b) break;
a = const_cast<BasicBlock*>(infoA->getIdom());
b = const_cast<BasicBlock*>(infoB->getIdom());
}
return a;
}
void ControlFlowAnalysis::computeDomNode(){
auto &functions = pModule->getFunctions();
// 分析每个函数内的基本块
for (const auto &function : functions) {
auto func = function.second.get();
auto basicBlocks = func->getBasicBlocks();
std::unordered_set<BasicBlock *> domSetTmp;
// 一开始把domSetTmp置为所有block
auto entry_block = func->getEntryBlock();
entry_block->setName("Entry");
blockAnalysisInfo[entry_block]->addDominants(entry_block);
for (auto &basicBlock : basicBlocks) {
domSetTmp.emplace(basicBlock.get());
}
// 初始化
for (auto &basicBlock : basicBlocks) {
if (basicBlock.get() != entry_block) {
blockAnalysisInfo[basicBlock.get()]->setDominants(domSetTmp);
// 先把所有block的必经结点都设为N
}
}
// 支配节点计算公式
//DOM[B]={B} {⋂P∈pred(B) DOM[P]}
// 其中pred(B)是B的所有前驱结点
// 迭代计算支配结点,直到不再变化
// 这里使用迭代法,直到支配结点不再变化
// TODOLengauer-Tarjan 算法可以更高效地计算支配结点
// 或者按照CFG拓扑序遍历效率更高
bool changed = true;
while (changed) {
changed = false;
// 循环非start结点
for (auto &basicBlock : basicBlocks) {
if (basicBlock.get() != entry_block) {
auto olddom =
blockAnalysisInfo[basicBlock.get()]->getDominants();
std::unordered_set<BasicBlock *> dom =
blockAnalysisInfo[basicBlock->getPredecessors().front()]->getDominants();
// 对于每个基本块,计算其支配结点
// 取其前驱结点的支配结点的交集和自己
for (auto pred : basicBlock->getPredecessors()) {
intersectOP4Dom(dom, blockAnalysisInfo[pred]->getDominants());
}
dom.emplace(basicBlock.get());
blockAnalysisInfo[basicBlock.get()]->setDominants(dom);
if (dom != olddom) {
changed = true;
}
}
}
}
}
}
// TODO SEMI-NCA算法改进
void ControlFlowAnalysis::computeDomTree() {
// 构造支配树
auto &functions = pModule->getFunctions();
for (const auto &function : functions) {
auto func = function.second.get();
auto basicBlocks = func->getBasicBlocks();
auto entry_block = func->getEntryBlock();
blockAnalysisInfo[entry_block]->setIdom(entry_block);
blockAnalysisInfo[entry_block]->setDomDepth(0); // 入口块深度为0
bool changed = true;
while (changed) {
changed = false;
for (auto &basicBlock : basicBlocks) {
if (basicBlock.get() == entry_block) continue;
BasicBlock *new_idom = nullptr;
for (auto pred : basicBlock->getPredecessors()) {
// 跳过未处理的前驱
if (blockAnalysisInfo[pred]->getIdom() == nullptr) continue;
// new_idom = (new_idom == nullptr) ? pred : findCommonDominator(new_idom, pred);
if (new_idom == nullptr)
new_idom = pred;
else
new_idom = findCommonDominator(new_idom, pred);
}
// 更新直接支配节点
if (new_idom && new_idom != blockAnalysisInfo[basicBlock.get()]->getIdom()) {
// 移除旧的支配关系
if (blockAnalysisInfo[basicBlock.get()]->getIdom()) {
blockAnalysisInfo[const_cast<BasicBlock*>(blockAnalysisInfo[basicBlock.get()]->getIdom())]->removeSdoms(basicBlock.get());
}
// 设置新的支配关系
// std::cout << "Block: " << basicBlock->getName()
// << " New Idom: " << new_idom->getName() << std::endl;
blockAnalysisInfo[basicBlock.get()]->setIdom(new_idom);
blockAnalysisInfo[new_idom]->addSdoms(basicBlock.get());
// 更新深度 = 直接支配节点深度 + 1
blockAnalysisInfo[basicBlock.get()]->setDomDepth(
blockAnalysisInfo[new_idom]->getDomDepth() + 1);
changed = true;
}
}
}
}
// for (auto &basicBlock : basicBlocks) {
// if (basicBlock.get() != func->getEntryBlock()) {
// auto dominats =
// blockAnalysisInfo[basicBlock.get()]->getDominants();
// bool found = false;
// // 从前驱结点开始寻找直接支配结点
// std::queue<BasicBlock *> q;
// for (auto pred : basicBlock->getPredecessors()) {
// q.push(pred);
// }
// // BFS遍历前驱结点直到找到直接支配结点
// while (!found && !q.empty()) {
// auto curr = q.front();
// q.pop();
// if (curr == basicBlock.get())
// continue;
// if (dominats.count(curr) != 0U) {
// blockAnalysisInfo[basicBlock.get()]->setIdom(curr);
// blockAnalysisInfo[curr]->addSdoms(basicBlock.get());
// found = true;
// } else {
// for (auto pred : curr->getPredecessors()) {
// q.push(pred);
// }
// }
// }
// }
// }
}
// std::unordered_set<BasicBlock *> ControlFlowAnalysis::computeDomFrontier(BasicBlock *block) {
// std::unordered_set<BasicBlock *> ret_list;
// // 计算 localDF
// for (auto local_successor : block->getSuccessors()) {
// if (local_successor->getIdom() != block) {
// ret_list.emplace(local_successor);
// }
// }
// // 计算 upDF
// for (auto up_successor : block->getSdoms()) {
// auto childrenDF = computeDF(up_successor);
// for (auto w : childrenDF) {
// if (block != w->getIdom() || block == w) {
// ret_list.emplace(w);
// }
// }
// }
// return ret_list;
// }
void ControlFlowAnalysis::computeDomFrontierAllBlk() {
auto &functions = pModule->getFunctions();
for (const auto &function : functions) {
auto func = function.second.get();
auto basicBlocks = func->getBasicBlocks();
// 按支配树深度排序(从深到浅)
std::vector<BasicBlock *> orderedBlocks;
for (auto &bb : basicBlocks) {
orderedBlocks.push_back(bb.get());
}
std::sort(orderedBlocks.begin(), orderedBlocks.end(),
[this](BasicBlock *a, BasicBlock *b) {
return blockAnalysisInfo[a]->getDomDepth() > blockAnalysisInfo[b]->getDomDepth();
});
// 计算支配边界
for (auto block : orderedBlocks) {
std::unordered_set<BasicBlock *> df;
// Local DF: 直接后继中不被当前块支配的
for (auto succ : block->getSuccessors()) {
// 当前块不支配该后继(即不是其直接支配节点)
if (blockAnalysisInfo[succ]->getIdom() != block) {
df.insert(succ);
}
}
// Up DF: 从支配子树中继承
for (auto child : blockAnalysisInfo[block]->getSdoms()) {
for (auto w : blockAnalysisInfo[child]->getDomFrontiers()) {
// 如果w不被当前块支配
if (block != blockAnalysisInfo[w]->getIdom()) {
df.insert(w);
}
}
}
blockAnalysisInfo[block]->setDomFrontiers(df);
}
}
}
// ==========================
// dataflow analysis utils
// ==========================
// 先引用学长的代码
// TODO: Worklist 增加逆后序遍历机制
void DataFlowAnalysisUtils::forwardAnalyze(Module *pModule){
std::map<DataFlowAnalysis *, bool> workAnalysis;
for (auto &dataflow : forwardAnalysisList) {
dataflow->init(pModule);
}
for (const auto &function : pModule->getFunctions()) {
for (auto &dataflow : forwardAnalysisList) {
workAnalysis.emplace(dataflow, false);
}
while (!workAnalysis.empty()) {
for (const auto &block : function.second->getBasicBlocks()) {
for (auto &elem : workAnalysis) {
if (elem.first->analyze(pModule, block.get())) {
elem.second = true;
}
}
}
std::map<DataFlowAnalysis *, bool> tmp;
std::remove_copy_if(workAnalysis.begin(), workAnalysis.end(), std::inserter(tmp, tmp.end()),
[](const std::pair<DataFlowAnalysis *, bool> &elem) -> bool { return !elem.second; });
workAnalysis.swap(tmp);
for (auto &elem : workAnalysis) {
elem.second = false;
}
}
}
}
void DataFlowAnalysisUtils::backwardAnalyze(Module *pModule) {
std::map<DataFlowAnalysis *, bool> workAnalysis;
for (auto &dataflow : backwardAnalysisList) {
dataflow->init(pModule);
}
for (const auto &function : pModule->getFunctions()) {
for (auto &dataflow : backwardAnalysisList) {
workAnalysis.emplace(dataflow, false);
}
while (!workAnalysis.empty()) {
for (const auto &block : function.second->getBasicBlocks()) {
for (auto &elem : workAnalysis) {
if (elem.first->analyze(pModule, block.get())) {
elem.second = true;
}
}
}
std::map<DataFlowAnalysis *, bool> tmp;
std::remove_copy_if(workAnalysis.begin(), workAnalysis.end(), std::inserter(tmp, tmp.end()),
[](const std::pair<DataFlowAnalysis *, bool> &elem) -> bool { return !elem.second; });
workAnalysis.swap(tmp);
for (auto &elem : workAnalysis) {
elem.second = false;
}
}
}
}
std::set<User *> ActiveVarAnalysis::getUsedSet(Instruction *inst) {
using Kind = Instruction::Kind;
std::vector<User *> operands;
for (const auto &operand : inst->getOperands()) {
operands.emplace_back(dynamic_cast<User *>(operand->getValue()));
}
std::set<User *> result;
switch (inst->getKind()) {
// phi op
case Kind::kPhi:
case Kind::kCall:
result.insert(std::next(operands.begin()), operands.end());
break;
case Kind::kCondBr:
result.insert(operands[0]);
break;
case Kind::kBr:
case Kind::kAlloca:
break;
// mem op
case Kind::kStore:
// StoreInst 的第一个操作数是被存储的值,第二个操作数是存储的变量
// 后续的是可能的数组维度
result.insert(operands[0]);
result.insert(operands.begin() + 2, operands.end());
break;
case Kind::kLoad:
case Kind::kLa: {
auto variable = dynamic_cast<AllocaInst *>(operands[0]);
auto global = dynamic_cast<GlobalValue *>(operands[0]);
auto constArray = dynamic_cast<ConstantVariable *>(operands[0]);
if ((variable != nullptr && variable->getNumDims() == 0) || (global != nullptr && global->getNumDims() == 0) ||
(constArray != nullptr && constArray->getNumDims() == 0)) {
result.insert(operands[0]);
}
result.insert(std::next(operands.begin()), operands.end());
break;
}
case Kind::kGetSubArray: {
for (unsigned i = 2; i < operands.size(); i++) {
// 数组的维度信息
result.insert(operands[i]);
}
break;
}
case Kind::kMemset: {
result.insert(std::next(operands.begin()), operands.end());
break;
}
case Kind::kInvalid:
// Binary
case Kind::kAdd:
case Kind::kSub:
case Kind::kMul:
case Kind::kDiv:
case Kind::kRem:
case Kind::kICmpEQ:
case Kind::kICmpNE:
case Kind::kICmpLT:
case Kind::kICmpLE:
case Kind::kICmpGT:
case Kind::kICmpGE:
case Kind::kFAdd:
case Kind::kFSub:
case Kind::kFMul:
case Kind::kFDiv:
case Kind::kFCmpEQ:
case Kind::kFCmpNE:
case Kind::kFCmpLT:
case Kind::kFCmpLE:
case Kind::kFCmpGT:
case Kind::kFCmpGE:
case Kind::kAnd:
case Kind::kOr:
// Unary
case Kind::kNeg:
case Kind::kNot:
case Kind::kFNot:
case Kind::kFNeg:
case Kind::kFtoI:
case Kind::kItoF:
// terminator
case Kind::kReturn:
result.insert(operands.begin(), operands.end());
break;
default:
assert(false);
break;
}
result.erase(nullptr);
return result;
}
User * ActiveVarAnalysis::getDefine(Instruction *inst) {
User *result = nullptr;
if (inst->isStore()) {
StoreInst* store = dynamic_cast<StoreInst *>(inst);
auto operand = store->getPointer();
AllocaInst* variable = dynamic_cast<AllocaInst *>(operand);
GlobalValue* global = dynamic_cast<GlobalValue *>(operand);
if ((variable != nullptr && variable->getNumDims() != 0) || (global != nullptr && global->getNumDims() != 0)) {
// 如果是数组变量或者全局变量,则不返回定义
// TODO兼容数组变量
result = nullptr;
} else {
result = dynamic_cast<User *>(operand);
}
} else if (inst->isPhi()) {
result = dynamic_cast<User *>(inst->getOperand(0));
} else if (inst->isBinary() || inst->isUnary() || inst->isCall() ||
inst->isLoad() || inst->isLa()) {
result = dynamic_cast<User *>(inst);
}
return result;
}
void ActiveVarAnalysis::init(Module *pModule) {
for (const auto &function : pModule->getFunctions()) {
for (const auto &block : function.second->getBasicBlocks()) {
activeTable.emplace(block.get(), std::vector<std::set<User *>>{});
for (unsigned i = 0; i < block->getNumInstructions() + 1; i++)
activeTable.at(block.get()).emplace_back();
}
}
}
// 活跃变量分析公式 每个块内的分析动作供分析器调用
bool ActiveVarAnalysis::analyze(Module *pModule, BasicBlock *block) {
bool changed = false; // 标记数据流结果是否有变化
std::set<User *> activeSet{}; // 当前计算的活跃变量集合
// 步骤1: 计算基本块出口的活跃变量集 (OUT[B])
// 公式: OUT[B] = _{S ∈ succ(B)} IN[S]
for (const auto &succ : block->getSuccessors()) {
// 获取后继块入口的活跃变量集 (IN[S])
auto succActiveSet = activeTable.at(succ).front();
// 合并所有后继块的入口活跃变量
activeSet.insert(succActiveSet.begin(), succActiveSet.end());
}
// 步骤2: 处理基本块出口处的活跃变量集
const auto &instructions = block->getInstructions();
const auto numInstructions = instructions.size();
// 获取旧的出口活跃变量集 (block出口对应索引numInstructions)
const auto &oldEndActiveSet = activeTable.at(block)[numInstructions];
// 检查出口活跃变量集是否有变化
if (!std::equal(activeSet.begin(), activeSet.end(),
oldEndActiveSet.begin(), oldEndActiveSet.end()))
{
changed = true; // 标记变化
activeTable.at(block)[numInstructions] = activeSet; // 更新出口活跃变量集
}
// 步骤3: 逆序遍历基本块中的指令
// 从最后一条指令开始向前计算每个程序点的活跃变量
auto instructionIter = instructions.end();
instructionIter--; // 指向最后一条指令
// 从出口向入口遍历 (索引从numInstructions递减到1)
for (unsigned i = numInstructions; i > 0; i--) {
auto inst = instructionIter->get(); // 当前指令
auto used = getUsedSet(inst);
User *defined = getDefine(inst);
// 步骤3.3: 计算指令入口的活跃变量 (IN[i])
// 公式: IN[i] = use_i (OUT[i] - def_i)
activeSet.erase(defined); // 移除被定义的变量 (OUT[i] - def_i)
activeSet.insert(used.begin(), used.end()); // 添加使用的变量
// 获取旧的入口活跃变量集 (位置i-1对应当前指令的入口)
const auto &oldActiveSet = activeTable.at(block)[i - 1];
// 检查活跃变量集是否有变化
if (!std::equal(activeSet.begin(), activeSet.end(),
oldActiveSet.begin(), oldActiveSet.end()))
{
changed = true; // 标记变化
activeTable.at(block)[i - 1] = activeSet; // 更新入口活跃变量集
}
instructionIter--; // 移动到前一条指令
}
return changed; // 返回数据流结果是否变化
}
} // namespace sysy

View File

@ -1,600 +0,0 @@
#include "SysYIRCFGOpt.h"
#include "SysYIROptUtils.h"
#include <cassert>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <iostream>
#include <queue> // 引入队列SysYDelNoPreBLock需要
namespace sysy {
// 定义静态ID
void *SysYDelInstAfterBrPass::ID = (void *)&SysYDelInstAfterBrPass::ID;
void *SysYDelEmptyBlockPass::ID = (void *)&SysYDelEmptyBlockPass::ID;
void *SysYDelNoPreBLockPass::ID = (void *)&SysYDelNoPreBLockPass::ID;
void *SysYBlockMergePass::ID = (void *)&SysYBlockMergePass::ID;
void *SysYAddReturnPass::ID = (void *)&SysYAddReturnPass::ID;
void *SysYCondBr2BrPass::ID = (void *)&SysYCondBr2BrPass::ID;
// ======================================================================
// SysYCFGOptUtils: 辅助工具类包含实际的CFG优化逻辑
// ======================================================================
// 删除br后的无用指令
bool SysYCFGOptUtils::SysYDelInstAfterBr(Function *func) {
bool changed = false;
auto basicBlocks = func->getBasicBlocks();
for (auto &basicBlock : basicBlocks) {
bool Branch = false;
auto &instructions = basicBlock->getInstructions();
auto Branchiter = instructions.end();
for (auto iter = instructions.begin(); iter != instructions.end(); ++iter) {
if ((*iter)->isTerminator()){
Branch = true;
Branchiter = iter;
break;
}
}
if (Branchiter != instructions.end()) ++Branchiter;
while (Branchiter != instructions.end()) {
changed = true;
Branchiter = instructions.erase(Branchiter);
}
if (Branch) { // 更新前驱后继关系
auto thelastinstinst = basicBlock->getInstructions().end();
--thelastinstinst;
auto &Successors = basicBlock->getSuccessors();
for (auto iterSucc = Successors.begin(); iterSucc != Successors.end();) {
(*iterSucc)->removePredecessor(basicBlock.get());
basicBlock->removeSuccessor(*iterSucc);
}
if (thelastinstinst->get()->isUnconditional()) {
BasicBlock* branchBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(0));
basicBlock->addSuccessor(branchBlock);
branchBlock->addPredecessor(basicBlock.get());
} else if (thelastinstinst->get()->isConditional()) {
BasicBlock* thenBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(1));
BasicBlock* elseBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(2));
basicBlock->addSuccessor(thenBlock);
basicBlock->addSuccessor(elseBlock);
thenBlock->addPredecessor(basicBlock.get());
elseBlock->addPredecessor(basicBlock.get());
}
}
}
return changed;
}
// 合并基本块
bool SysYCFGOptUtils::SysYBlockMerge(Function *func) {
bool changed = false;
for (auto blockiter = func->getBasicBlocks().begin();
blockiter != func->getBasicBlocks().end();) {
if (blockiter->get()->getNumSuccessors() == 1) {
// 如果当前块只有一个后继块
// 且后继块只有一个前驱块
// 则将当前块和后继块合并
if (((blockiter->get())->getSuccessors()[0])->getNumPredecessors() == 1) {
// std::cout << "merge block: " << blockiter->get()->getName() << std::endl;
BasicBlock* block = blockiter->get();
BasicBlock* nextBlock = blockiter->get()->getSuccessors()[0];
// auto nextarguments = nextBlock->getArguments();
// 删除br指令
if (block->getNumInstructions() != 0) {
auto thelastinstinst = block->end();
(--thelastinstinst);
if (thelastinstinst->get()->isUnconditional()) {
SysYIROptUtils::usedelete(thelastinstinst->get());
thelastinstinst = block->getInstructions().erase(thelastinstinst);
} else if (thelastinstinst->get()->isConditional()) {
// 如果是条件分支,判断条件是否相同,主要优化相同布尔表达式
if (thelastinstinst->get()->getOperand(1)->getName() == thelastinstinst->get()->getOperand(1)->getName()) {
SysYIROptUtils::usedelete(thelastinstinst->get());
thelastinstinst = block->getInstructions().erase(thelastinstinst);
}
}
}
// 将后继块的指令移动到当前块
// 并将后继块的父指针改为当前块
for (auto institer = nextBlock->begin(); institer != nextBlock->end();) {
institer->get()->setParent(block);
block->getInstructions().emplace_back(institer->release());
institer = nextBlock->getInstructions().erase(institer);
}
// 更新前驱后继关系,类似树节点操作
block->removeSuccessor(nextBlock);
nextBlock->removePredecessor(block);
std::list<BasicBlock *> succshoulddel;
for (auto &succ : nextBlock->getSuccessors()) {
block->addSuccessor(succ);
succ->replacePredecessor(nextBlock, block);
succshoulddel.push_back(succ);
}
for (auto del : succshoulddel) {
nextBlock->removeSuccessor(del);
}
func->removeBasicBlock(nextBlock);
changed = true;
} else {
blockiter++;
}
} else {
blockiter++;
}
}
return changed;
}
// 删除无前驱块兼容SSA后的处理
bool SysYCFGOptUtils::SysYDelNoPreBLock(Function *func) {
bool changed = false;
for (auto &block : func->getBasicBlocks()) {
block->setreachableFalse();
}
// 对函数基本块做一个拓扑排序,排查不可达基本块
auto entryBlock = func->getEntryBlock();
entryBlock->setreachableTrue();
std::queue<BasicBlock *> blockqueue;
blockqueue.push(entryBlock);
while (!blockqueue.empty()) {
auto block = blockqueue.front();
blockqueue.pop();
for (auto &succ : block->getSuccessors()) {
if (!succ->getreachable()) {
succ->setreachableTrue();
blockqueue.push(succ);
}
}
}
// 删除不可达基本块指令
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end(); blockIter++) {
if (!blockIter->get()->getreachable()) {
for (auto instIter = blockIter->get()->getInstructions().begin();
instIter != blockIter->get()->getInstructions().end();) {
SysYIROptUtils::usedelete(instIter->get());
instIter = blockIter->get()->getInstructions().erase(instIter);
}
}
}
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();) {
if (!blockIter->get()->getreachable()) {
for (auto succblock : blockIter->get()->getSuccessors()) {
for (auto &phiinst : succblock->getInstructions()) {
if (phiinst->getKind() != Instruction::kPhi) {
break;
}
// 使用 delBlk 方法正确地删除对应于被删除基本块的传入值
dynamic_cast<PhiInst *>(phiinst.get())->delBlk(blockIter->get());
}
}
// 删除不可达基本块,注意迭代器不可达问题
func->removeBasicBlock((blockIter++)->get());
changed = true;
} else {
blockIter++;
}
}
return changed;
}
// 删除空块
bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder) {
bool changed = false;
// 收集不可达基本块
// 这里的不可达基本块是指没有实际指令的基本块
// 当一个基本块没有实际指令例如只有phi指令和一个uncondbr指令时也会被视作不可达
auto basicBlocks = func->getBasicBlocks();
std::map<sysy::BasicBlock *, BasicBlock *> EmptyBlocks;
// 空块儿和后继的基本块的映射
for (auto &basicBlock : basicBlocks) {
if (basicBlock->getNumInstructions() == 0) {
if (basicBlock->getNumSuccessors() == 1) {
EmptyBlocks[basicBlock.get()] = basicBlock->getSuccessors().front();
}
}
else{
// 如果只有phi指令和一个uncondbr。(phi)*(uncondbr)?
// 判断除了最后一个指令之外是不是只有phi指令
bool onlyPhi = true;
for (auto &inst : basicBlock->getInstructions()) {
if (!inst->isPhi() && !inst->isUnconditional()) {
onlyPhi = false;
break;
}
}
if(onlyPhi && basicBlock->getNumSuccessors() == 1) // 确保有后继且只有一个
EmptyBlocks[basicBlock.get()] = basicBlock->getSuccessors().front();
}
}
// 更新基本块信息,增加必要指令
for (auto &basicBlock : basicBlocks) {
// 把空块转换成只有跳转指令的不可达块 (这段逻辑在优化遍中可能需要调整,这里是原样保留)
// 通常DelEmptyBlock 应该在BlockMerge之后运行如果存在完全空块它会尝试填充一个Br指令。
// 但是,它主要目的是重定向跳转。
if (distance(basicBlock->begin(), basicBlock->end()) == 0) {
if (basicBlock->getNumSuccessors() == 0) {
continue;
}
if (basicBlock->getNumSuccessors() > 1) {
// 如果一个空块有多个后继说明CFG结构有问题或者需要特殊处理这里简单assert
assert(false && "Empty block with multiple successors found during SysYDelEmptyBlock");
}
// 这里的逻辑有点问题,如果一个块是空的,且只有一个后继,应该直接跳转到后继。
// 如果这个块最终被删除了,那么其前驱也需要重定向。
// 这个循环的目的是重定向现有的跳转指令,而不是创建新的。
// 所以下面的逻辑才是核心。
// pBuilder->setPosition(basicBlock.get(), basicBlock->end());
// pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {});
continue;
}
auto thelastinst = basicBlock->getInstructions().end();
--thelastinst;
// 根据br指令传递的后继块信息跳过空块链
if (thelastinst->get()->isUnconditional()) {
BasicBlock* OldBrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
BasicBlock *thelastBlockOld = nullptr;
// 如果空块链表为多个块
while (EmptyBlocks.count(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)))) {
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
thelastinst->get()->replaceOperand(0, EmptyBlocks[thelastBlockOld]);
}
// 如果有重定向发生
if (thelastBlockOld != nullptr) {
basicBlock->removeSuccessor(OldBrBlock);
OldBrBlock->removePredecessor(basicBlock.get());
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)));
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->addPredecessor(basicBlock.get());
changed = true; // 标记IR被修改
}
if (thelastBlockOld != nullptr) {
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getInstructions()) {
if (InstInNew->isPhi()) {
// 使用 delBlk 方法删除 oldBlock 对应的传入值
dynamic_cast<PhiInst *>(InstInNew.get())->delBlk(thelastBlockOld);
} else {
break;
}
}
}
} else if (thelastinst->get()->getKind() == Instruction::kCondBr) {
auto OldThenBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
auto OldElseBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2));
bool thenChanged = false;
bool elseChanged = false;
BasicBlock *thelastBlockOld = nullptr;
while (EmptyBlocks.count(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)))) {
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
thelastinst->get()->replaceOperand(
1, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))]);
thenChanged = true;
}
if (thenChanged) {
basicBlock->removeSuccessor(OldThenBlock);
OldThenBlock->removePredecessor(basicBlock.get());
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)));
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))->addPredecessor(basicBlock.get());
changed = true; // 标记IR被修改
}
// 处理 then 和 else 分支合并的情况
if (dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)) ==
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))) {
auto thebrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
SysYIROptUtils::usedelete(thelastinst->get());
thelastinst = basicBlock->getInstructions().erase(thelastinst);
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(thebrBlock, {});
changed = true; // 标记IR被修改
continue;
}
if (thelastBlockOld != nullptr) {
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))->getInstructions()) {
if (InstInNew->isPhi()) {
// 使用 delBlk 方法删除 oldBlock 对应的传入值
dynamic_cast<PhiInst *>(InstInNew.get())->delBlk(thelastBlockOld);
} else {
break;
}
}
}
thelastBlockOld = nullptr;
while (EmptyBlocks.count(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2)))) {
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2));
thelastinst->get()->replaceOperand(
2, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))]);
elseChanged = true;
}
if (elseChanged) {
basicBlock->removeSuccessor(OldElseBlock);
OldElseBlock->removePredecessor(basicBlock.get());
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2)));
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))->addPredecessor(basicBlock.get());
changed = true; // 标记IR被修改
}
// 处理 then 和 else 分支合并的情况
if (dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)) ==
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))) {
auto thebrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
SysYIROptUtils::usedelete(thelastinst->get());
thelastinst = basicBlock->getInstructions().erase(thelastinst);
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(thebrBlock, {});
changed = true; // 标记IR被修改
continue;
}
// 如果有重定向发生
// 需要更新后继块的前驱关系
if (thelastBlockOld != nullptr) {
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))->getInstructions()) {
if (InstInNew->isPhi()) {
// 使用 delBlk 方法删除 oldBlock 对应的传入值
dynamic_cast<PhiInst *>(InstInNew.get())->delBlk(thelastBlockOld);
} else {
break;
}
}
}
} else {
// 如果不是终止指令,但有后继 (例如,末尾没有显式终止指令的块)
// 这段逻辑可能需要更严谨的CFG检查来确保正确性
if (basicBlock->getNumSuccessors() == 1) {
// 这里的逻辑似乎是想为没有terminator的块添加一个但通常这应该在CFG构建阶段完成。
// 如果这里仍然执行,确保它符合预期。
// pBuilder->setPosition(basicBlock.get(), basicBlock->end());
// pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {});
// auto thelastinst = basicBlock->getInstructions().end();
// (--thelastinst);
// auto OldBrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
// sysy::BasicBlock *thelastBlockOld = nullptr;
// while (EmptyBlocks.find(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))) !=
// EmptyBlocks.end()) {
// thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
// thelastinst->get()->replaceOperand(
// 0, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))]);
// }
// basicBlock->removeSuccessor(OldBrBlock);
// OldBrBlock->removePredecessor(basicBlock.get());
// basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)));
// dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->addPredecessor(basicBlock.get());
// changed = true; // 标记IR被修改
// if (thelastBlockOld != nullptr) {
// int indexphi = 0;
// for (auto &pred : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getPredecessors()) {
// if (pred == thelastBlockOld) {
// break;
// }
// indexphi++;
// }
// for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getInstructions()) {
// if (InstInNew->isPhi()) {
// dynamic_cast<PhiInst *>(InstInNew.get())->removeOperand(indexphi + 1);
// } else {
// break;
// }
// }
// }
}
}
}
// 真正的删除空块
for (auto iter = func->getBasicBlocks().begin(); iter != func->getBasicBlocks().end();) {
if (EmptyBlocks.count(iter->get())) {
// EntryBlock跳过
if (iter->get() == func->getEntryBlock()) {
++iter;
continue;
}
for (auto instIter = iter->get()->getInstructions().begin();
instIter != iter->get()->getInstructions().end();) {
SysYIROptUtils::usedelete(instIter->get()); // 仅删除 use 关系
// 显式地从基本块中删除指令并更新迭代器
instIter = iter->get()->getInstructions().erase(instIter);
}
// 删除不可达基本块的phi指令的操作数
for (auto &succ : iter->get()->getSuccessors()) {
for (auto &instinsucc : succ->getInstructions()) {
if (instinsucc->isPhi()) {
// iter->get() 就是当前被删除的空基本块它作为前驱连接到这里的Phi指令
dynamic_cast<PhiInst *>(instinsucc.get())->delBlk(iter->get());
} else {
// Phi 指令通常在基本块的开头,如果不是 Phi 指令就停止检查
break;
}
}
}
func->removeBasicBlock((iter++)->get());
changed = true;
} else {
++iter;
}
}
return changed;
}
// 如果函数没有返回指令,则添加一个默认返回指令(主要解决void函数没有返回指令的问题)
bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder* pBuilder) {
bool changed = false;
auto basicBlocks = func->getBasicBlocks();
for (auto &block : basicBlocks) {
if (block->getNumSuccessors() == 0) {
// 如果基本块没有后继块,则添加一个返回指令
if (block->getNumInstructions() == 0) {
pBuilder->setPosition(block.get(), block->end());
pBuilder->createReturnInst();
changed = true; // 标记IR被修改
} else {
auto thelastinst = block->getInstructions().end();
--thelastinst;
if (thelastinst->get()->getKind() != Instruction::kReturn) {
// std::cout << "Warning: Function " << func->getName() << " has no return instruction, adding default return." << std::endl;
pBuilder->setPosition(block.get(), block->end());
// TODO: 如果int float函数缺少返回值是否需要报错
if (func->getReturnType()->isInt()) {
pBuilder->createReturnInst(ConstantInteger::get(0));
} else if (func->getReturnType()->isFloat()) {
pBuilder->createReturnInst(ConstantFloating::get(0.0F));
} else {
pBuilder->createReturnInst();
}
changed = true; // 标记IR被修改
}
}
}
}
return changed;
}
// 条件分支转换为无条件分支
// 主要针对已知条件值的分支转换为无条件分支
// 例如 if (cond) { ... } else { ... } 中的 cond 已经
// 确定为 true 或 false 的情况
bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) {
bool changed = false;
for (auto &basicblock : func->getBasicBlocks()) {
if (basicblock->getNumInstructions() == 0)
continue;
auto thelast = basicblock->getInstructions().end();
--thelast;
if (thelast->get()->isConditional()){
ConstantValue *constOperand = dynamic_cast<ConstantValue *>(thelast->get()->getOperand(0));
std::string opname;
int constint = 0;
float constfloat = 0.0F;
bool constint_Use = false;
bool constfloat_Use = false;
if (constOperand != nullptr) {
if (constOperand->isFloat()) {
constfloat = constOperand->getFloat();
constfloat_Use = true;
} else {
constint = constOperand->getInt();
constint_Use = true;
}
}
// 如果可以计算
if (constfloat_Use || constint_Use) {
changed = true;
auto thenBlock = dynamic_cast<BasicBlock *>(thelast->get()->getOperand(1));
auto elseBlock = dynamic_cast<BasicBlock *>(thelast->get()->getOperand(2));
SysYIROptUtils::usedelete(thelast->get());
thelast = basicblock->getInstructions().erase(thelast);
if ((constfloat_Use && constfloat == 1.0F) || (constint_Use && constint == 1)) {
// cond为true或非0
pBuilder->setPosition(basicblock.get(), basicblock->end());
pBuilder->createUncondBrInst(thenBlock, {});
// 更新CFG关系
basicblock->removeSuccessor(elseBlock);
elseBlock->removePredecessor(basicblock.get());
// 删除elseBlock的phi指令中对应的basicblock.get()的传入值
for (auto &phiinst : elseBlock->getInstructions()) {
if (phiinst->getKind() != Instruction::kPhi) {
break;
}
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值
dynamic_cast<PhiInst *>(phiinst.get())->delBlk(basicblock.get());
}
} else { // cond为false或0
pBuilder->setPosition(basicblock.get(), basicblock->end());
pBuilder->createUncondBrInst(elseBlock, {});
// 更新CFG关系
basicblock->removeSuccessor(thenBlock);
thenBlock->removePredecessor(basicblock.get());
// 删除thenBlock的phi指令中对应的basicblock.get()的传入值
for (auto &phiinst : thenBlock->getInstructions()) {
if (phiinst->getKind() != Instruction::kPhi) {
break;
}
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值
dynamic_cast<PhiInst *>(phiinst.get())->delBlk(basicblock.get());
}
}
}
}
}
return changed;
}
// ======================================================================
// 独立的CFG优化遍的实现
// ======================================================================
bool SysYDelInstAfterBrPass::runOnFunction(Function *F, AnalysisManager& AM) {
return SysYCFGOptUtils::SysYDelInstAfterBr(F);
}
bool SysYDelEmptyBlockPass::runOnFunction(Function *F, AnalysisManager& AM) {
return SysYCFGOptUtils::SysYDelEmptyBlock(F, pBuilder);
}
bool SysYDelNoPreBLockPass::runOnFunction(Function *F, AnalysisManager& AM) {
return SysYCFGOptUtils::SysYDelNoPreBLock(F);
}
bool SysYBlockMergePass::runOnFunction(Function *F, AnalysisManager& AM) {
return SysYCFGOptUtils::SysYBlockMerge(F);
}
bool SysYAddReturnPass::runOnFunction(Function *F, AnalysisManager& AM) {
return SysYCFGOptUtils::SysYAddReturn(F, pBuilder);
}
bool SysYCondBr2BrPass::runOnFunction(Function *F, AnalysisManager& AM) {
return SysYCFGOptUtils::SysYCondBr2Br(F, pBuilder);
}
} // namespace sysy

File diff suppressed because it is too large Load Diff

View File

@ -1,36 +0,0 @@
// PassManager.cpp
#include "SysYIRPassManager.h"
#include <iostream>
namespace sysy {
void PassManager::run(Module& M) {
// 首先运行Module级别的Pass
for (auto& pass : modulePasses) {
std::cout << "Running Module Pass: " << pass->getPassName() << std::endl;
pass->runOnModule(M);
}
// 然后对每个函数运行Function级别的Pass
auto& functions = M.getFunctions();
for (auto& pair : functions) {
Function& F = *(pair.second); // 获取Function的引用
std::cout << " Processing Function: " << F.getName() << std::endl;
// 在每个函数上运行FunctionPasses
bool changedInFunction;
do {
changedInFunction = false;
for (auto& pass : functionPasses) {
// 对于FunctionPasses可以考虑一个迭代执行的循环直到稳定
std::cout << " Running Function Pass: " << pass->getPassName() << std::endl;
changedInFunction |= pass->runOnFunction(F);
}
} while (changedInFunction); // 循环直到函数稳定这模拟了您SysYCFGOpt的while(changed)逻辑
}
// 分析Pass的运行可以在其他Pass需要时触发或者在特定的PassManager阶段触发
// 对于依赖于分析结果的Pass可以在其run方法中通过PassManager::getAnalysis()来获取
}
} // namespace sysy

View File

@ -0,0 +1,25 @@
# src/backend/RISCv64/CMakeLists.txt
add_library(riscv64_backend_lib STATIC
RISCv64AsmPrinter.cpp
RISCv64Backend.cpp
RISCv64ISel.cpp
RISCv64LLIR.cpp
RISCv64RegAlloc.cpp
Handler/CalleeSavedHandler.cpp
Handler/LegalizeImmediates.cpp
Handler/PrologueEpilogueInsertion.cpp
Handler/EliminateFrameIndices.cpp
Optimize/Peephole.cpp
Optimize/PostRA_Scheduler.cpp
Optimize/PreRA_Scheduler.cpp
Optimize/DivStrengthReduction.cpp
)
# 包含后端模块所需的头文件路径
target_include_directories(riscv64_backend_lib PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../../include/backend/RISCv64 # 后端顶层头文件
${CMAKE_CURRENT_SOURCE_DIR}/../../include/backend/RISCv64/Handler # 增加 Handler 头文件路径
${CMAKE_CURRENT_SOURCE_DIR}/../../include/backend/RISCv64/Optimize # 增加 Optimize 头文件路径
${CMAKE_CURRENT_SOURCE_DIR}/../../include/midend # 增加 midend 头文件路径 (已存在)
${CMAKE_CURRENT_SOURCE_DIR}/../../include/midend/Pass # 增加 midend 头文件路径 (已存在)
)

View File

@ -0,0 +1,51 @@
#include "CalleeSavedHandler.h"
#include <set>
#include <vector>
#include <algorithm>
#include <iterator>
namespace sysy {
char CalleeSavedHandler::ID = 0;
bool CalleeSavedHandler::runOnFunction(Function *F, AnalysisManager& AM) {
// This pass works on MachineFunction level, not IR level
return false;
}
void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
StackFrameInfo& frame_info = mfunc->getFrameInfo();
const std::set<PhysicalReg>& used_callee_saved = frame_info.used_callee_saved_regs;
if (used_callee_saved.empty()) {
frame_info.callee_saved_size = 0;
frame_info.callee_saved_regs_to_store.clear();
return;
}
// 1. 计算被调用者保存寄存器所需的总空间大小
// s0 总是由 PEI Pass 单独处理,这里不计入大小,但要确保它在列表中
int size = 0;
std::set<PhysicalReg> regs_to_save = used_callee_saved;
if (regs_to_save.count(PhysicalReg::S0)) {
regs_to_save.erase(PhysicalReg::S0);
}
size = regs_to_save.size() * 8; // 每个寄存器占8字节 (64-bit)
frame_info.callee_saved_size = size;
// 2. 创建一个有序的、需要保存的寄存器列表,以便后续 Pass 确定地生成代码
// s0 不应包含在此列表中,因为它由 PEI Pass 特殊处理
std::vector<PhysicalReg> sorted_regs(regs_to_save.begin(), regs_to_save.end());
std::sort(sorted_regs.begin(), sorted_regs.end(), [](PhysicalReg a, PhysicalReg b){
return static_cast<int>(a) < static_cast<int>(b);
});
frame_info.callee_saved_regs_to_store = sorted_regs;
// 3. 更新栈帧总大小。
// 这是初步计算PEI Pass 会进行最终的对齐。
frame_info.total_size = frame_info.locals_size +
frame_info.spill_size +
frame_info.callee_saved_size;
}
} // namespace sysy

View File

@ -0,0 +1,235 @@
#include "EliminateFrameIndices.h"
#include "RISCv64ISel.h"
#include <cassert>
#include <vector>
namespace sysy {
// getTypeSizeInBytes 是一个通用辅助函数,保持不变
unsigned EliminateFrameIndicesPass::getTypeSizeInBytes(Type* type) {
if (!type) {
assert(false && "Cannot get size of a null type.");
return 0;
}
switch (type->getKind()) {
case Type::kInt:
case Type::kFloat:
return 4;
case Type::kPointer:
return 8;
case Type::kArray: {
auto arrayType = type->as<ArrayType>();
return arrayType->getNumElements() * getTypeSizeInBytes(arrayType->getElementType());
}
default:
assert(false && "Unsupported type for size calculation.");
return 0;
}
}
void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) {
StackFrameInfo& frame_info = mfunc->getFrameInfo();
Function* F = mfunc->getFunc();
RISCv64ISel* isel = mfunc->getISel();
// 在这里处理栈传递的参数以便在寄存器分配前就将数据流显式化修复溢出逻辑的BUG。
// 2. 只为局部变量(AllocaInst)分配栈空间和计算偏移量
// 局部变量从 s0 下方(负偏移量)开始分配,紧接着为 ra 和 s0 预留的16字节之后
int local_var_offset = 16;
if(F) { // 确保函数指针有效
for (auto& bb : F->getBasicBlocks()) {
for (auto& inst : bb->getInstructions()) {
if (auto alloca = dynamic_cast<AllocaInst*>(inst.get())) {
Type* allocated_type = alloca->getType()->as<PointerType>()->getBaseType();
int size = getTypeSizeInBytes(allocated_type);
// 优化栈帧大小对于大数组使用4字节对齐小对象使用8字节对齐
if (size >= 256) { // 大数组优化
size = (size + 3) & ~3; // 4字节对齐
} else {
size = (size + 7) & ~7; // 8字节对齐
}
if (size == 0) size = 4; // 最小4字节
local_var_offset += size;
unsigned alloca_vreg = isel->getVReg(alloca);
// 局部变量使用相对于s0的负向偏移
frame_info.alloca_offsets[alloca_vreg] = -local_var_offset;
}
}
}
}
// 记录仅由AllocaInst分配的局部变量的总大小
frame_info.locals_size = local_var_offset - 16;
// 记录局部变量区域分配结束的最终偏移量
frame_info.locals_end_offset = -local_var_offset;
// 在函数入口为所有栈传递的参数插入load指令
// 这个步骤至关重要它在寄存器分配之前为这些参数的vreg创建了明确的“定义(def)”指令。
// 这解决了在高寄存器压力下当这些vreg被溢出时`rewriteProgram`找不到其定义点而崩溃的问题。
if (F && isel && !mfunc->getBlocks().empty()) {
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
std::vector<std::unique_ptr<MachineInstr>> arg_load_instrs;
// 步骤 3.1: 生成所有加载栈参数的指令,暂存起来
int arg_idx = 0;
for (Argument* arg : F->getArguments()) {
// 根据ABI前8个整型/指针参数通过寄存器传递,这里只处理超出部分。
if (arg_idx >= 8) {
// 计算参数在调用者栈帧中的位置该位置相对于被调用者的帧指针s0是正向偏移。
// 第9个参数(arg_idx=8)位于 0(s0)第10个(arg_idx=9)位于 8(s0),以此类推。
int offset = (arg_idx - 8) * 8;
unsigned arg_vreg = isel->getVReg(arg);
Type* arg_type = arg->getType();
// 根据参数类型选择正确的加载指令
RVOpcodes load_op;
if (arg_type->isFloat()) {
load_op = RVOpcodes::FLW; // 单精度浮点
} else if (arg_type->isPointer()) {
load_op = RVOpcodes::LD; // 64位指针
} else {
load_op = RVOpcodes::LW; // 32位整数
}
// 创建加载指令: lw/ld/flw vreg, offset(s0)
auto load_instr = std::make_unique<MachineInstr>(load_op);
load_instr->addOperand(std::make_unique<RegOperand>(arg_vreg));
load_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0), // 基址为帧指针
std::make_unique<ImmOperand>(offset)
));
arg_load_instrs.push_back(std::move(load_instr));
}
arg_idx++;
}
//仅当有需要加载的栈参数时,才执行插入逻辑
if (!arg_load_instrs.empty()) {
auto& entry_instrs = entry_block->getInstructions();
auto insertion_point = entry_instrs.begin(); // 默认插入点为块的开头
auto last_arg_save_it = entry_instrs.end();
// 步骤 3.2: 寻找一个安全的插入点。
// 遍历入口块的指令,找到最后一条保存“寄存器传递参数”的伪指令。
// 这样可以确保我们在所有 a0-a7 参数被保存之后,才执行可能覆盖它们的加载指令。
for (auto it = entry_instrs.begin(); it != entry_instrs.end(); ++it) {
MachineInstr* instr = it->get();
// 寻找代表保存参数到栈的伪指令
if (instr->getOpcode() == RVOpcodes::FRAME_STORE_W ||
instr->getOpcode() == RVOpcodes::FRAME_STORE_D ||
instr->getOpcode() == RVOpcodes::FRAME_STORE_F) {
// 检查被保存的值是否是寄存器参数 (arg_no < 8)
auto& operands = instr->getOperands();
if (operands.empty() || operands[0]->getKind() != MachineOperand::KIND_REG) continue;
unsigned src_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
Value* ir_value = isel->getVRegValueMap().count(src_vreg) ? isel->getVRegValueMap().at(src_vreg) : nullptr;
if (auto ir_arg = dynamic_cast<Argument*>(ir_value)) {
if (ir_arg->getIndex() < 8) {
last_arg_save_it = it; // 找到了一个保存寄存器参数的指令,更新位置
}
}
}
}
// 如果找到了这样的保存指令,我们的插入点就在它之后
if (last_arg_save_it != entry_instrs.end()) {
insertion_point = std::next(last_arg_save_it);
}
// 步骤 3.3: 在计算出的安全位置,一次性插入所有新创建的参数加载指令
entry_instrs.insert(insertion_point,
std::make_move_iterator(arg_load_instrs.begin()),
std::make_move_iterator(arg_load_instrs.end()));
}
}
// 4. 遍历所有机器指令,将访问局部变量的伪指令展开为真实指令
for (auto& mbb : mfunc->getBlocks()) {
std::vector<std::unique_ptr<MachineInstr>> new_instructions;
for (auto& instr_ptr : mbb->getInstructions()) {
RVOpcodes opcode = instr_ptr->getOpcode();
if (opcode == RVOpcodes::FRAME_LOAD_W || opcode == RVOpcodes::FRAME_LOAD_D || opcode == RVOpcodes::FRAME_LOAD_F) {
RVOpcodes real_load_op;
if (opcode == RVOpcodes::FRAME_LOAD_W) real_load_op = RVOpcodes::LW;
else if (opcode == RVOpcodes::FRAME_LOAD_D) real_load_op = RVOpcodes::LD;
else real_load_op = RVOpcodes::FLW;
auto& operands = instr_ptr->getOperands();
unsigned dest_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
int offset = frame_info.alloca_offsets.at(alloca_vreg);
auto addr_vreg = isel->getNewVReg(Type::getPointerType(Type::getIntType()));
// 展开为: addi addr_vreg, s0, offset
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
addi->addOperand(std::make_unique<RegOperand>(addr_vreg));
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
addi->addOperand(std::make_unique<ImmOperand>(offset));
new_instructions.push_back(std::move(addi));
// 展开为: lw/ld/flw dest_vreg, 0(addr_vreg)
auto load_instr = std::make_unique<MachineInstr>(real_load_op);
load_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
load_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)));
new_instructions.push_back(std::move(load_instr));
} else if (opcode == RVOpcodes::FRAME_STORE_W || opcode == RVOpcodes::FRAME_STORE_D || opcode == RVOpcodes::FRAME_STORE_F) {
RVOpcodes real_store_op;
if (opcode == RVOpcodes::FRAME_STORE_W) real_store_op = RVOpcodes::SW;
else if (opcode == RVOpcodes::FRAME_STORE_D) real_store_op = RVOpcodes::SD;
else real_store_op = RVOpcodes::FSW;
auto& operands = instr_ptr->getOperands();
unsigned src_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
int offset = frame_info.alloca_offsets.at(alloca_vreg);
auto addr_vreg = isel->getNewVReg(Type::getPointerType(Type::getIntType()));
// 展开为: addi addr_vreg, s0, offset
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
addi->addOperand(std::make_unique<RegOperand>(addr_vreg));
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
addi->addOperand(std::make_unique<ImmOperand>(offset));
new_instructions.push_back(std::move(addi));
// 展开为: sw/sd/fsw src_vreg, 0(addr_vreg)
auto store_instr = std::make_unique<MachineInstr>(real_store_op);
store_instr->addOperand(std::make_unique<RegOperand>(src_vreg));
store_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)));
new_instructions.push_back(std::move(store_instr));
} else if (instr_ptr->getOpcode() == RVOpcodes::FRAME_ADDR) {
auto& operands = instr_ptr->getOperands();
unsigned dest_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
int offset = frame_info.alloca_offsets.at(alloca_vreg);
// 将 `frame_addr rd, rs` 展开为 `addi rd, s0, offset`
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
addi->addOperand(std::make_unique<RegOperand>(dest_vreg));
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
addi->addOperand(std::make_unique<ImmOperand>(offset));
new_instructions.push_back(std::move(addi));
} else {
new_instructions.push_back(std::move(instr_ptr));
}
}
mbb->getInstructions() = std::move(new_instructions);
}
}
} // namespace sysy

View File

@ -0,0 +1,171 @@
#include "LegalizeImmediates.h"
#include "RISCv64ISel.h" // 需要包含它以调用 getNewVReg()
#include "RISCv64AsmPrinter.h"
#include <vector>
#include <iostream>
// 声明外部调试控制变量
extern int DEBUG;
extern int DEEPDEBUG;
namespace sysy {
char LegalizeImmediatesPass::ID = 0;
// 辅助函数检查一个立即数是否在RISC-V的12位有符号范围内
static bool isLegalImmediate(int64_t imm) {
return imm >= -2048 && imm <= 2047;
}
void LegalizeImmediatesPass::runOnMachineFunction(MachineFunction* mfunc) {
if (DEBUG) {
std::cerr << "===== Running Legalize Immediates Pass on function: " << mfunc->getName() << " =====\n";
}
// 定义我们保留的、用于暂存的物理寄存器
const PhysicalReg TEMP_REG = PhysicalReg::T5;
// 创建一个临时的AsmPrinter用于打印指令方便调试
RISCv64AsmPrinter temp_printer(mfunc);
if (DEEPDEBUG) {
temp_printer.setStream(std::cerr);
}
for (auto& mbb : mfunc->getBlocks()) {
if (DEEPDEBUG) {
std::cerr << "--- Processing Basic Block: " << mbb->getName() << " ---\n";
}
// 创建一个新的指令列表,用于存放合法化后的指令
std::vector<std::unique_ptr<MachineInstr>> new_instructions;
for (auto& instr_ptr : mbb->getInstructions()) {
if (DEEPDEBUG) {
std::cerr << " Checking: ";
// 打印指令时末尾会带换行符,所以这里不用 std::endl
temp_printer.printInstruction(instr_ptr.get(), true);
}
bool legalized = false; // 标记当前指令是否已被展开处理
switch (instr_ptr->getOpcode()) {
case RVOpcodes::ADDI:
case RVOpcodes::ADDIW: {
auto& operands = instr_ptr->getOperands();
// 确保操作数足够多,以防万一
if (operands.size() < 3) break;
auto imm_op = static_cast<ImmOperand*>(operands.back().get());
if (!isLegalImmediate(imm_op->getValue())) {
if (DEEPDEBUG) {
std::cerr << " >> ILLEGAL immediate (" << imm_op->getValue() << "). Expanding...\n";
}
// 立即数超出范围,需要展开
auto rd_op = std::make_unique<RegOperand>(*static_cast<RegOperand*>(operands[0].get()));
auto rs1_op = std::make_unique<RegOperand>(*static_cast<RegOperand*>(operands[1].get()));
// 1. li t5, immediate
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(TEMP_REG));
li->addOperand(std::make_unique<ImmOperand>(imm_op->getValue()));
// 2. add/addw rd, rs1, t5
auto new_op = (instr_ptr->getOpcode() == RVOpcodes::ADDI) ? RVOpcodes::ADD : RVOpcodes::ADDW;
auto add = std::make_unique<MachineInstr>(new_op);
add->addOperand(std::move(rd_op));
add->addOperand(std::move(rs1_op));
add->addOperand(std::make_unique<RegOperand>(TEMP_REG));
if (DEEPDEBUG) {
std::cerr << " New sequence:\n ";
temp_printer.printInstruction(li.get(), true);
std::cerr << " ";
temp_printer.printInstruction(add.get(), true);
}
new_instructions.push_back(std::move(li));
new_instructions.push_back(std::move(add));
legalized = true;
}
break;
}
// 处理所有内存加载/存储指令
case RVOpcodes::LB: case RVOpcodes::LH: case RVOpcodes::LW: case RVOpcodes::LD:
case RVOpcodes::LBU: case RVOpcodes::LHU: case RVOpcodes::LWU:
case RVOpcodes::SB: case RVOpcodes::SH: case RVOpcodes::SW: case RVOpcodes::SD:
case RVOpcodes::FLW: case RVOpcodes::FSW: {
auto& operands = instr_ptr->getOperands();
auto mem_op = static_cast<MemOperand*>(operands.back().get());
auto offset_op = mem_op->getOffset();
if (!isLegalImmediate(offset_op->getValue())) {
if (DEEPDEBUG) {
std::cerr << " >> ILLEGAL immediate offset (" << offset_op->getValue() << "). Expanding...\n";
}
// 偏移量超出范围,需要展开
auto data_reg_op = std::make_unique<RegOperand>(*static_cast<RegOperand*>(operands[0].get()));
auto base_reg_op = std::make_unique<RegOperand>(*mem_op->getBase());
// 1. li t5, offset
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(TEMP_REG));
li->addOperand(std::make_unique<ImmOperand>(offset_op->getValue()));
// 2. add t5, base_reg, t5 (计算最终地址结果也放在t5)
auto add = std::make_unique<MachineInstr>(RVOpcodes::ADD);
add->addOperand(std::make_unique<RegOperand>(TEMP_REG));
add->addOperand(std::move(base_reg_op));
add->addOperand(std::make_unique<RegOperand>(TEMP_REG));
// 3. lw/sw data_reg, 0(t5)
auto mem_instr = std::make_unique<MachineInstr>(instr_ptr->getOpcode());
mem_instr->addOperand(std::move(data_reg_op));
mem_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(TEMP_REG),
std::make_unique<ImmOperand>(0)
));
if (DEEPDEBUG) {
std::cerr << " New sequence:\n ";
temp_printer.printInstruction(li.get(), true);
std::cerr << " ";
temp_printer.printInstruction(add.get(), true);
std::cerr << " ";
temp_printer.printInstruction(mem_instr.get(), true);
}
new_instructions.push_back(std::move(li));
new_instructions.push_back(std::move(add));
new_instructions.push_back(std::move(mem_instr));
legalized = true;
}
break;
}
default:
// 其他指令不需要处理
break;
}
if (!legalized) {
if (DEEPDEBUG) {
std::cerr << " -- Immediate is legal. Skipping.\n";
}
// 如果当前指令不需要合法化,直接将其移动到新列表中
new_instructions.push_back(std::move(instr_ptr));
}
}
// 用新的、已合法化的指令列表替换旧的列表
mbb->getInstructions() = std::move(new_instructions);
}
if (DEBUG) {
std::cerr << "===== Finished Legalize Immediates Pass =====\n\n";
}
}
} // namespace sysy

View File

@ -0,0 +1,182 @@
#include "PrologueEpilogueInsertion.h"
#include "RISCv64LLIR.h" // 假设包含了 PhysicalReg, RVOpcodes 等定义
#include "RISCv64ISel.h"
#include <algorithm>
#include <vector>
#include <set>
namespace sysy {
char PrologueEpilogueInsertionPass::ID = 0;
void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) {
StackFrameInfo& frame_info = mfunc->getFrameInfo();
Function* F = mfunc->getFunc();
RISCv64ISel* isel = mfunc->getISel();
// 1. 清理 KEEPALIVE 伪指令
for (auto& mbb : mfunc->getBlocks()) {
auto& instrs = mbb->getInstructions();
instrs.erase(
std::remove_if(instrs.begin(), instrs.end(),
[](const std::unique_ptr<MachineInstr>& instr) {
return instr->getOpcode() == RVOpcodes::PSEUDO_KEEPALIVE;
}
),
instrs.end()
);
}
// 2. 确定需要保存的被调用者保存寄存器 (callee-saved)
auto& vreg_to_preg_map = frame_info.vreg_to_preg_map;
std::set<PhysicalReg> used_callee_saved_regs_set;
const auto& callee_saved_int = getCalleeSavedIntRegs();
const auto& callee_saved_fp = getCalleeSavedFpRegs();
for (const auto& pair : vreg_to_preg_map) {
PhysicalReg preg = pair.second;
bool is_int_cs = std::find(callee_saved_int.begin(), callee_saved_int.end(), preg) != callee_saved_int.end();
bool is_fp_cs = std::find(callee_saved_fp.begin(), callee_saved_fp.end(), preg) != callee_saved_fp.end();
if ((is_int_cs && preg != PhysicalReg::S0) || is_fp_cs) {
used_callee_saved_regs_set.insert(preg);
}
}
frame_info.callee_saved_regs_to_store.assign(
used_callee_saved_regs_set.begin(), used_callee_saved_regs_set.end()
);
std::sort(frame_info.callee_saved_regs_to_store.begin(), frame_info.callee_saved_regs_to_store.end());
frame_info.callee_saved_size = frame_info.callee_saved_regs_to_store.size() * 8;
// 3. 计算最终的栈帧总大小,包含栈溢出保护
int total_stack_size = frame_info.locals_size +
frame_info.spill_size +
frame_info.callee_saved_size +
16;
// 栈溢出保护:增加最大栈帧大小以容纳大型数组
const int MAX_STACK_FRAME_SIZE = 8192; // 8KB to handle large arrays like 256*4*2 = 2048 bytes
if (total_stack_size > MAX_STACK_FRAME_SIZE) {
// 如果仍然超过限制,尝试优化对齐方式
std::cerr << "Warning: Stack frame size " << total_stack_size
<< " exceeds recommended limit " << MAX_STACK_FRAME_SIZE << " for function "
<< mfunc->getName() << std::endl;
}
// 优化减少对齐开销使用16字节对齐而非更大的对齐
int aligned_stack_size = (total_stack_size + 15) & ~15;
frame_info.total_size = aligned_stack_size;
if (aligned_stack_size > 0) {
// --- 4. 插入完整的序言 ---
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
auto& entry_instrs = entry_block->getInstructions();
std::vector<std::unique_ptr<MachineInstr>> prologue_instrs;
// 4.1. 分配栈帧
auto alloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
alloc_stack->addOperand(std::make_unique<ImmOperand>(-aligned_stack_size));
prologue_instrs.push_back(std::move(alloc_stack));
// 4.2. 保存 ra 和 s0
auto save_ra = std::make_unique<MachineInstr>(RVOpcodes::SD);
save_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
save_ra->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>(aligned_stack_size - 8)
));
prologue_instrs.push_back(std::move(save_ra));
auto save_fp = std::make_unique<MachineInstr>(RVOpcodes::SD);
save_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
save_fp->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>(aligned_stack_size - 16)
));
prologue_instrs.push_back(std::move(save_fp));
// 4.3. 设置新的帧指针 s0
auto set_fp = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
set_fp->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
prologue_instrs.push_back(std::move(set_fp));
// 4.4. 保存所有使用到的被调用者保存寄存器
int next_available_offset = -(16 + frame_info.locals_size + frame_info.spill_size);
for (const auto& reg : frame_info.callee_saved_regs_to_store) {
// 改为“先更新,后使用”逻辑
next_available_offset -= 8; // 先为当前寄存器分配下一个可用槽位
RVOpcodes store_op = isFPR(reg) ? RVOpcodes::FSD : RVOpcodes::SD;
auto save_cs_reg = std::make_unique<MachineInstr>(store_op);
save_cs_reg->addOperand(std::make_unique<RegOperand>(reg));
save_cs_reg->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(next_available_offset) // 使用新计算出的正确偏移
));
prologue_instrs.push_back(std::move(save_cs_reg));
// 不再需要在循环末尾递减
}
// 4.5. 将所有生成的序言指令一次性插入到函数入口
entry_instrs.insert(entry_instrs.begin(),
std::make_move_iterator(prologue_instrs.begin()),
std::make_move_iterator(prologue_instrs.end()));
// --- 5. 插入完整的尾声 ---
for (auto& mbb : mfunc->getBlocks()) {
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
if ((*it)->getOpcode() == RVOpcodes::RET) {
std::vector<std::unique_ptr<MachineInstr>> epilogue_instrs;
// 5.1. 恢复被调用者保存寄存器
int next_available_offset_restore = -(16 + frame_info.locals_size + frame_info.spill_size);
for (const auto& reg : frame_info.callee_saved_regs_to_store) {
next_available_offset_restore -= 8; // 为下一个寄存器准备偏移
RVOpcodes load_op = isFPR(reg) ? RVOpcodes::FLD : RVOpcodes::LD;
auto restore_cs_reg = std::make_unique<MachineInstr>(load_op);
restore_cs_reg->addOperand(std::make_unique<RegOperand>(reg));
restore_cs_reg->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(next_available_offset_restore) // 使用当前偏移
));
epilogue_instrs.push_back(std::move(restore_cs_reg));
}
// 5.2. 恢复 ra 和 s0
auto restore_ra = std::make_unique<MachineInstr>(RVOpcodes::LD);
restore_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
restore_ra->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>(aligned_stack_size - 8)
));
epilogue_instrs.push_back(std::move(restore_ra));
auto restore_fp = std::make_unique<MachineInstr>(RVOpcodes::LD);
restore_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
restore_fp->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>(aligned_stack_size - 16)
));
epilogue_instrs.push_back(std::move(restore_fp));
// 5.3. 释放栈帧
auto dealloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
dealloc_stack->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
epilogue_instrs.push_back(std::move(dealloc_stack));
// 将尾声指令插入到 RET 指令之前
mbb->getInstructions().insert(it,
std::make_move_iterator(epilogue_instrs.begin()),
std::make_move_iterator(epilogue_instrs.end()));
goto next_block;
}
}
next_block:;
}
}
}
} // namespace sysy

View File

@ -0,0 +1,282 @@
#include "DivStrengthReduction.h"
#include <cmath>
#include <cstdint>
namespace sysy {
char DivStrengthReduction::ID = 0;
bool DivStrengthReduction::runOnFunction(Function *F, AnalysisManager& AM) {
// This pass works on MachineFunction level, not IR level
return false;
}
void DivStrengthReduction::runOnMachineFunction(MachineFunction *mfunc) {
if (!mfunc)
return;
bool debug = false; // Set to true for debugging
if (debug)
std::cout << "Running DivStrengthReduction optimization..." << std::endl;
int next_temp_reg = 1000;
auto createTempReg = [&]() -> int {
return next_temp_reg++;
};
struct MagicInfo {
int64_t magic;
int shift;
};
auto computeMagic = [](int64_t d, bool is_32bit) -> MagicInfo {
int word_size = is_32bit ? 32 : 64;
uint64_t ad = std::abs(d);
if (ad == 0) return {0, 0};
int l = std::floor(std::log2(ad));
if ((ad & (ad - 1)) == 0) { // power of 2
l = 0; // special case for power of 2, shift will be calculated differently
}
__int128_t one = 1;
__int128_t num;
int total_shift;
if (is_32bit) {
total_shift = 31 + l;
num = one << total_shift;
} else {
total_shift = 63 + l;
num = one << total_shift;
}
__int128_t den = ad;
int64_t magic = (num / den) + 1;
return {magic, total_shift};
};
auto isPowerOfTwo = [](int64_t n) -> bool {
return n > 0 && (n & (n - 1)) == 0;
};
auto getPowerOfTwoExponent = [](int64_t n) -> int {
if (n <= 0 || (n & (n - 1)) != 0) return -1;
int shift = 0;
while (n > 1) {
n >>= 1;
shift++;
}
return shift;
};
struct InstructionReplacement {
size_t index;
size_t count_to_erase;
std::vector<std::unique_ptr<MachineInstr>> newInstrs;
};
for (auto &mbb_uptr : mfunc->getBlocks()) {
auto &mbb = *mbb_uptr;
auto &instrs = mbb.getInstructions();
std::vector<InstructionReplacement> replacements;
for (size_t i = 0; i < instrs.size(); ++i) {
auto *instr = instrs[i].get();
bool is_32bit = (instr->getOpcode() == RVOpcodes::DIVW);
if (instr->getOpcode() != RVOpcodes::DIV && !is_32bit) {
continue;
}
if (instr->getOperands().size() != 3) {
continue;
}
auto *dst_op = instr->getOperands()[0].get();
auto *src1_op = instr->getOperands()[1].get();
auto *src2_op = instr->getOperands()[2].get();
int64_t divisor = 0;
bool const_divisor_found = false;
size_t instructions_to_replace = 1;
if (src2_op->getKind() == MachineOperand::KIND_IMM) {
divisor = static_cast<ImmOperand *>(src2_op)->getValue();
const_divisor_found = true;
} else if (src2_op->getKind() == MachineOperand::KIND_REG) {
if (i > 0) {
auto *prev_instr = instrs[i - 1].get();
if (prev_instr->getOpcode() == RVOpcodes::LI && prev_instr->getOperands().size() == 2) {
auto *li_dst_op = prev_instr->getOperands()[0].get();
auto *li_imm_op = prev_instr->getOperands()[1].get();
if (li_dst_op->getKind() == MachineOperand::KIND_REG && li_imm_op->getKind() == MachineOperand::KIND_IMM) {
auto *div_reg_op = static_cast<RegOperand *>(src2_op);
auto *li_dst_reg_op = static_cast<RegOperand *>(li_dst_op);
if (div_reg_op->isVirtual() && li_dst_reg_op->isVirtual() &&
div_reg_op->getVRegNum() == li_dst_reg_op->getVRegNum()) {
divisor = static_cast<ImmOperand *>(li_imm_op)->getValue();
const_divisor_found = true;
instructions_to_replace = 2;
}
}
}
}
}
if (!const_divisor_found) {
continue;
}
auto *dst_reg = static_cast<RegOperand *>(dst_op);
auto *src1_reg = static_cast<RegOperand *>(src1_op);
if (divisor == 0) continue;
std::vector<std::unique_ptr<MachineInstr>> newInstrs;
if (divisor == 1) {
auto moveInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::ADDW : RVOpcodes::ADD);
moveInstr->addOperand(std::make_unique<RegOperand>(*dst_reg));
moveInstr->addOperand(std::make_unique<RegOperand>(*src1_reg));
moveInstr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
newInstrs.push_back(std::move(moveInstr));
}
else if (divisor == -1) {
auto negInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SUBW : RVOpcodes::SUB);
negInstr->addOperand(std::make_unique<RegOperand>(*dst_reg));
negInstr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
negInstr->addOperand(std::make_unique<RegOperand>(*src1_reg));
newInstrs.push_back(std::move(negInstr));
}
else if (isPowerOfTwo(std::abs(divisor))) {
int shift = getPowerOfTwoExponent(std::abs(divisor));
int temp_reg = createTempReg();
auto sraSignInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SRAIW : RVOpcodes::SRAI);
sraSignInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
sraSignInstr->addOperand(std::make_unique<RegOperand>(*src1_reg));
sraSignInstr->addOperand(std::make_unique<ImmOperand>(is_32bit ? 31 : 63));
newInstrs.push_back(std::move(sraSignInstr));
auto srlInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SRLIW : RVOpcodes::SRLI);
srlInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
srlInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
srlInstr->addOperand(std::make_unique<ImmOperand>((is_32bit ? 32 : 64) - shift));
newInstrs.push_back(std::move(srlInstr));
auto addInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::ADDW : RVOpcodes::ADD);
addInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
addInstr->addOperand(std::make_unique<RegOperand>(*src1_reg));
addInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
newInstrs.push_back(std::move(addInstr));
auto sraInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SRAIW : RVOpcodes::SRAI);
sraInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
sraInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
sraInstr->addOperand(std::make_unique<ImmOperand>(shift));
newInstrs.push_back(std::move(sraInstr));
if (divisor < 0) {
auto negInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SUBW : RVOpcodes::SUB);
negInstr->addOperand(std::make_unique<RegOperand>(*dst_reg));
negInstr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
negInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
newInstrs.push_back(std::move(negInstr));
} else {
auto moveInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::ADDW : RVOpcodes::ADD);
moveInstr->addOperand(std::make_unique<RegOperand>(*dst_reg));
moveInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
moveInstr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
newInstrs.push_back(std::move(moveInstr));
}
}
else {
auto magic_info = computeMagic(divisor, is_32bit);
int magic_reg = createTempReg();
int temp_reg = createTempReg();
auto loadInstr = std::make_unique<MachineInstr>(RVOpcodes::LI);
loadInstr->addOperand(std::make_unique<RegOperand>(magic_reg));
loadInstr->addOperand(std::make_unique<ImmOperand>(magic_info.magic));
newInstrs.push_back(std::move(loadInstr));
if (is_32bit) {
auto mulInstr = std::make_unique<MachineInstr>(RVOpcodes::MUL);
mulInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
mulInstr->addOperand(std::make_unique<RegOperand>(*src1_reg));
mulInstr->addOperand(std::make_unique<RegOperand>(magic_reg));
newInstrs.push_back(std::move(mulInstr));
auto sraInstr = std::make_unique<MachineInstr>(RVOpcodes::SRAI);
sraInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
sraInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
sraInstr->addOperand(std::make_unique<ImmOperand>(magic_info.shift));
newInstrs.push_back(std::move(sraInstr));
} else {
auto mulhInstr = std::make_unique<MachineInstr>(RVOpcodes::MULH);
mulhInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
mulhInstr->addOperand(std::make_unique<RegOperand>(*src1_reg));
mulhInstr->addOperand(std::make_unique<RegOperand>(magic_reg));
newInstrs.push_back(std::move(mulhInstr));
int post_shift = magic_info.shift - 63;
if (post_shift > 0) {
auto sraInstr = std::make_unique<MachineInstr>(RVOpcodes::SRAI);
sraInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
sraInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
sraInstr->addOperand(std::make_unique<ImmOperand>(post_shift));
newInstrs.push_back(std::move(sraInstr));
}
}
int sign_reg = createTempReg();
auto sraSignInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SRAIW : RVOpcodes::SRAI);
sraSignInstr->addOperand(std::make_unique<RegOperand>(sign_reg));
sraSignInstr->addOperand(std::make_unique<RegOperand>(*src1_reg));
sraSignInstr->addOperand(std::make_unique<ImmOperand>(is_32bit ? 31 : 63));
newInstrs.push_back(std::move(sraSignInstr));
auto subInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SUBW : RVOpcodes::SUB);
subInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
subInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
subInstr->addOperand(std::make_unique<RegOperand>(sign_reg));
newInstrs.push_back(std::move(subInstr));
if (divisor < 0) {
auto negInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SUBW : RVOpcodes::SUB);
negInstr->addOperand(std::make_unique<RegOperand>(*dst_reg));
negInstr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
negInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
newInstrs.push_back(std::move(negInstr));
} else {
auto moveInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::ADDW : RVOpcodes::ADD);
moveInstr->addOperand(std::make_unique<RegOperand>(*dst_reg));
moveInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
moveInstr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
newInstrs.push_back(std::move(moveInstr));
}
}
if (!newInstrs.empty()) {
size_t start_index = i;
if (instructions_to_replace == 2) {
start_index = i - 1;
}
replacements.push_back({start_index, instructions_to_replace, std::move(newInstrs)});
}
}
for (auto it = replacements.rbegin(); it != replacements.rend(); ++it) {
instrs.erase(instrs.begin() + it->index, instrs.begin() + it->index + it->count_to_erase);
instrs.insert(instrs.begin() + it->index,
std::make_move_iterator(it->newInstrs.begin()),
std::make_move_iterator(it->newInstrs.end()));
}
}
}
} // namespace sysy

View File

@ -0,0 +1,652 @@
#include "Peephole.h"
#include <functional>
namespace sysy {
char PeepholeOptimizer::ID = 0;
bool PeepholeOptimizer::runOnFunction(Function *F, AnalysisManager& AM) {
// This pass works on MachineFunction level, not IR level
return false;
}
void PeepholeOptimizer::runOnMachineFunction(MachineFunction *mfunc) {
if (!mfunc)
return;
using namespace sysy;
// areRegsEqual: 检查两个寄存器操作数是否相等(考虑虚拟和物理寄存器)。
auto areRegsEqual = [](RegOperand *r1, RegOperand *r2) {
if (!r1 || !r2 || r1->isVirtual() != r2->isVirtual()) {
return false;
}
if (r1->isVirtual()) {
return r1->getVRegNum() == r2->getVRegNum();
} else {
return r1->getPReg() == r2->getPReg();
}
};
// 改进的 isRegUsedLater 函数 - 更完整和准确的实现
auto isRegUsedLater =
[&](const std::vector<std::unique_ptr<MachineInstr>> &instrs,
RegOperand *reg, size_t start_idx) -> bool {
for (size_t j = start_idx; j < instrs.size(); ++j) {
auto *instr = instrs[j].get();
auto opcode = instr->getOpcode();
// 检查所有操作数
for (size_t k = 0; k < instr->getOperands().size(); ++k) {
bool isDefOperand = false;
// 更完整的定义操作数判断逻辑
if (k == 0) { // 第一个操作数通常是目标寄存器
switch (opcode) {
// 算术和逻辑指令 - 第一个操作数是定义
case RVOpcodes::MV:
case RVOpcodes::ADDI:
case RVOpcodes::SLLI:
case RVOpcodes::SRLI:
case RVOpcodes::SRAI:
case RVOpcodes::SLTI:
case RVOpcodes::SLTIU:
case RVOpcodes::XORI:
case RVOpcodes::ORI:
case RVOpcodes::ANDI:
case RVOpcodes::ADD:
case RVOpcodes::SUB:
case RVOpcodes::SLL:
case RVOpcodes::SLT:
case RVOpcodes::SLTU:
case RVOpcodes::XOR:
case RVOpcodes::SRL:
case RVOpcodes::SRA:
case RVOpcodes::OR:
case RVOpcodes::AND:
case RVOpcodes::MUL:
case RVOpcodes::DIV:
case RVOpcodes::REM:
case RVOpcodes::LW:
case RVOpcodes::LH:
case RVOpcodes::LB:
case RVOpcodes::LHU:
case RVOpcodes::LBU:
// 存储指令 - 第一个操作数是使用(要存储的值)
case RVOpcodes::SW:
case RVOpcodes::SH:
case RVOpcodes::SB:
// 分支指令 - 第一个操作数是使用
case RVOpcodes::BEQ:
case RVOpcodes::BNE:
case RVOpcodes::BLT:
case RVOpcodes::BGE:
case RVOpcodes::BLTU:
case RVOpcodes::BGEU:
// 跳转指令 - 可能使用寄存器
case RVOpcodes::JALR:
isDefOperand = false;
break;
default:
// 对于未知指令,保守地假设第一个操作数可能是使用
isDefOperand = false;
break;
}
}
// 如果不是定义操作数,检查是否使用了目标寄存器
if (!isDefOperand) {
if (instr->getOperands()[k]->getKind() == MachineOperand::KIND_REG) {
auto *use_reg =
static_cast<RegOperand *>(instr->getOperands()[k].get());
if (areRegsEqual(reg, use_reg))
return true;
}
// 检查内存操作数中的基址寄存器
if (instr->getOperands()[k]->getKind() == MachineOperand::KIND_MEM) {
auto *mem =
static_cast<MemOperand *>(instr->getOperands()[k].get());
if (areRegsEqual(reg, mem->getBase()))
return true;
}
}
}
}
return false;
};
// 检查寄存器是否在指令中被重新定义(用于更精确的分析)
auto isRegRedefinedAt =
[](MachineInstr *instr, RegOperand *reg,
const std::function<bool(RegOperand *, RegOperand *)> &areRegsEqual)
-> bool {
if (instr->getOperands().empty())
return false;
auto opcode = instr->getOpcode();
// 只有当第一个操作数是定义操作数时才检查
switch (opcode) {
case RVOpcodes::MV:
case RVOpcodes::ADDI:
case RVOpcodes::ADD:
case RVOpcodes::SUB:
case RVOpcodes::MUL:
case RVOpcodes::LW:
// ... 其他定义指令
if (instr->getOperands()[0]->getKind() == MachineOperand::KIND_REG) {
auto *def_reg =
static_cast<RegOperand *>(instr->getOperands()[0].get());
return areRegsEqual(reg, def_reg);
}
break;
default:
break;
}
return false;
};
// 检查是否为存储-加载模式,支持不同大小的访问
auto isStoreLoadPattern = [](MachineInstr *store_instr,
MachineInstr *load_instr) -> bool {
auto store_op = store_instr->getOpcode();
auto load_op = load_instr->getOpcode();
// 检查存储-加载对应关系
return (store_op == RVOpcodes::SW && load_op == RVOpcodes::LW) || // 32位
(store_op == RVOpcodes::SH &&
load_op == RVOpcodes::LH) || // 16位有符号
(store_op == RVOpcodes::SH &&
load_op == RVOpcodes::LHU) || // 16位无符号
(store_op == RVOpcodes::SB &&
load_op == RVOpcodes::LB) || // 8位有符号
(store_op == RVOpcodes::SB &&
load_op == RVOpcodes::LBU) || // 8位无符号
(store_op == RVOpcodes::SD && load_op == RVOpcodes::LD); // 64位
};
// 检查两个内存访问是否访问相同的内存位置
auto areMemoryAccessesEqual =
[&areRegsEqual](MachineInstr *store_instr, MemOperand *store_mem,
MachineInstr *load_instr, MemOperand *load_mem) -> bool {
// 基址寄存器必须相同
if (!areRegsEqual(store_mem->getBase(), load_mem->getBase())) {
return false;
}
// 偏移量必须相同
if (store_mem->getOffset()->getValue() !=
load_mem->getOffset()->getValue()) {
return false;
}
// 检查访问大小是否兼容
auto store_op = store_instr->getOpcode();
auto load_op = load_instr->getOpcode();
// 获取访问大小(字节数)
auto getAccessSize = [](RVOpcodes opcode) -> int {
switch (opcode) {
case RVOpcodes::LB:
case RVOpcodes::LBU:
case RVOpcodes::SB:
return 1; // 8位
case RVOpcodes::LH:
case RVOpcodes::LHU:
case RVOpcodes::SH:
return 2; // 16位
case RVOpcodes::LW:
case RVOpcodes::SW:
return 4; // 32位
case RVOpcodes::LD:
case RVOpcodes::SD:
return 8; // 64位
default:
return -1; // 未知
}
};
int store_size = getAccessSize(store_op);
int load_size = getAccessSize(load_op);
// 只有访问大小完全匹配时才能进行优化
// 这避免了部分重叠访问的复杂情况
return store_size > 0 && store_size == load_size;
};
// 简单的内存别名分析:检查两个内存访问之间是否可能有冲突的内存操作
auto isMemoryAccessSafe =
[&](const std::vector<std::unique_ptr<MachineInstr>> &instrs,
size_t store_idx, size_t load_idx, MemOperand *mem) -> bool {
// 检查存储和加载之间是否有可能影响内存的指令
for (size_t j = store_idx + 1; j < load_idx; ++j) {
auto *between_instr = instrs[j].get();
auto between_op = between_instr->getOpcode();
// 检查是否有其他内存写入操作
switch (between_op) {
case RVOpcodes::SW:
case RVOpcodes::SH:
case RVOpcodes::SB:
case RVOpcodes::SD: {
// 如果有其他存储操作,需要检查是否可能访问相同的内存
if (between_instr->getOperands().size() >= 2 &&
between_instr->getOperands()[1]->getKind() ==
MachineOperand::KIND_MEM) {
auto *other_mem =
static_cast<MemOperand *>(between_instr->getOperands()[1].get());
// 保守的别名分析:如果使用不同的基址寄存器,假设可能别名
if (!areRegsEqual(mem->getBase(), other_mem->getBase())) {
return false; // 可能的别名,不安全
}
// 如果基址相同但偏移量不同,检查是否重叠
int64_t offset1 = mem->getOffset()->getValue();
int64_t offset2 = other_mem->getOffset()->getValue();
// 获取访问大小来检查重叠
auto getAccessSize = [](RVOpcodes opcode) -> int {
switch (opcode) {
case RVOpcodes::SB:
return 1;
case RVOpcodes::SH:
return 2;
case RVOpcodes::SW:
return 4;
case RVOpcodes::SD:
return 8;
default:
return 4; // 默认假设4字节
}
};
int size1 = getAccessSize(RVOpcodes::SW); // 从原存储指令推断
int size2 = getAccessSize(between_op);
// 检查内存区域是否重叠
bool overlaps =
!(offset1 + size1 <= offset2 || offset2 + size2 <= offset1);
if (overlaps) {
return false; // 内存重叠,不安全
}
}
break;
}
// 函数调用可能有副作用
case RVOpcodes::JAL:
case RVOpcodes::JALR:
return false; // 函数调用可能修改内存,不安全
// 原子操作或其他可能修改内存的指令
// 根据具体的RISC-V扩展添加更多指令
default:
// 对于未知指令,采用保守策略
// 可以根据具体需求调整
break;
}
}
return true; // 没有发现潜在的内存冲突
};
// isPowerOfTwo: 检查数值是否为2的幂次并返回其指数。
auto isPowerOfTwo = [](int64_t n) -> int {
if (n <= 0 || (n & (n - 1)) != 0)
return -1;
int shift = 0;
while (n > 1) {
n >>= 1;
shift++;
}
return shift;
};
for (auto &mbb_uptr : mfunc->getBlocks()) {
auto &mbb = *mbb_uptr;
auto &instrs = mbb.getInstructions();
if (instrs.size() < 2)
continue; // 基本块至少需要两条指令进行窥孔
// 遍历指令序列进行窥孔优化
for (size_t i = 0; i + 1 < instrs.size();) {
auto *mi1 = instrs[i].get();
auto *mi2 = instrs[i + 1].get();
bool changed = false;
// 1. 消除冗余交换移动: mv a, b; mv b, a -> mv a, b
if (mi1->getOpcode() == RVOpcodes::MV &&
mi2->getOpcode() == RVOpcodes::MV) {
if (mi1->getOperands().size() == 2 && mi2->getOperands().size() == 2) {
if (mi1->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[1]->getKind() == MachineOperand::KIND_REG &&
mi2->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi2->getOperands()[1]->getKind() == MachineOperand::KIND_REG) {
auto *dst1 = static_cast<RegOperand *>(mi1->getOperands()[0].get());
auto *src1 = static_cast<RegOperand *>(mi1->getOperands()[1].get());
auto *dst2 = static_cast<RegOperand *>(mi2->getOperands()[0].get());
auto *src2 = static_cast<RegOperand *>(mi2->getOperands()[1].get());
if (areRegsEqual(dst1, src2) && areRegsEqual(src1, dst2)) {
instrs.erase(instrs.begin() + i + 1); // 移除第二条指令
changed = true;
}
}
}
}
// 2. 冗余加载消除: sw t0, offset(base); lw t1, offset(base) -> 替换或消除
// lw 添加ld sd支持
else if (isStoreLoadPattern(mi1, mi2)) {
if (mi1->getOperands().size() == 2 && mi2->getOperands().size() == 2) {
if (mi1->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[1]->getKind() == MachineOperand::KIND_MEM &&
mi2->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi2->getOperands()[1]->getKind() == MachineOperand::KIND_MEM) {
auto *store_val =
static_cast<RegOperand *>(mi1->getOperands()[0].get());
auto *store_mem =
static_cast<MemOperand *>(mi1->getOperands()[1].get());
auto *load_val =
static_cast<RegOperand *>(mi2->getOperands()[0].get());
auto *load_mem =
static_cast<MemOperand *>(mi2->getOperands()[1].get());
// 检查内存访问是否匹配(基址、偏移量和访问大小)
if (areMemoryAccessesEqual(mi1, store_mem, mi2, load_mem)) {
// 进行简单的内存别名分析
if (isMemoryAccessSafe(instrs, i, i + 1, store_mem)) {
if (areRegsEqual(store_val, load_val)) {
// sw r1, mem; lw r1, mem -> 消除冗余的lw
instrs.erase(instrs.begin() + i + 1);
changed = true;
} else {
// sw r1, mem; lw r2, mem -> 替换lw为mv r2, r1
auto newInstr = std::make_unique<MachineInstr>(RVOpcodes::MV);
newInstr->addOperand(std::make_unique<RegOperand>(*load_val));
newInstr->addOperand(
std::make_unique<RegOperand>(*store_val));
instrs[i + 1] = std::move(newInstr);
changed = true;
}
}
}
}
}
}
// 3. 强度削减: mul y, x, 2^n -> slli y, x, n
else if (mi1->getOpcode() == RVOpcodes::MUL &&
mi1->getOperands().size() == 3) {
auto *dst_op = mi1->getOperands()[0].get();
auto *src1_op = mi1->getOperands()[1].get();
auto *src2_op = mi1->getOperands()[2].get();
if (dst_op->getKind() == MachineOperand::KIND_REG) {
auto *dst_reg = static_cast<RegOperand *>(dst_op);
RegOperand *src_reg = nullptr;
int shift = -1;
if (src1_op->getKind() == MachineOperand::KIND_REG &&
src2_op->getKind() == MachineOperand::KIND_IMM) {
shift =
isPowerOfTwo(static_cast<ImmOperand *>(src2_op)->getValue());
if (shift >= 0)
src_reg = static_cast<RegOperand *>(src1_op);
} else if (src1_op->getKind() == MachineOperand::KIND_IMM &&
src2_op->getKind() == MachineOperand::KIND_REG) {
shift =
isPowerOfTwo(static_cast<ImmOperand *>(src1_op)->getValue());
if (shift >= 0)
src_reg = static_cast<RegOperand *>(src2_op);
}
if (src_reg && shift >= 0 &&
shift <= 31) { // RISC-V 移位量限制 (0-31)
auto newInstr = std::make_unique<MachineInstr>(RVOpcodes::SLLI);
newInstr->addOperand(std::make_unique<RegOperand>(*dst_reg));
newInstr->addOperand(std::make_unique<RegOperand>(*src_reg));
newInstr->addOperand(std::make_unique<ImmOperand>(shift));
instrs[i] = std::move(newInstr);
changed = true;
}
}
}
// 4. 地址计算优化: addi dst, base, imm1; lw/sw val, imm2(dst) -> lw/sw
// val, (imm1+imm2)(base)
else if (mi1->getOpcode() == RVOpcodes::ADDI &&
mi1->getOperands().size() == 3) {
auto opcode2 = mi2->getOpcode();
if (opcode2 == RVOpcodes::LW || opcode2 == RVOpcodes::SW) {
if (mi2->getOperands().size() == 2 &&
mi2->getOperands()[1]->getKind() == MachineOperand::KIND_MEM &&
mi1->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[1]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[2]->getKind() == MachineOperand::KIND_IMM) {
auto *addi_dst =
static_cast<RegOperand *>(mi1->getOperands()[0].get());
auto *addi_base =
static_cast<RegOperand *>(mi1->getOperands()[1].get());
auto *addi_imm =
static_cast<ImmOperand *>(mi1->getOperands()[2].get());
auto *mem_op =
static_cast<MemOperand *>(mi2->getOperands()[1].get());
auto *mem_base = mem_op->getBase();
auto *mem_imm = mem_op->getOffset();
// 检查 ADDI 的目标寄存器是否是内存操作的基址
if (areRegsEqual(addi_dst, mem_base)) {
// 改进的使用检查:考虑寄存器可能在后续被重新定义的情况
bool canOptimize = true;
// 检查从 i+2 开始的指令
for (size_t j = i + 2; j < instrs.size(); ++j) {
auto *later_instr = instrs[j].get();
// 如果寄存器被重新定义,那么它后面的使用就不相关了
if (isRegRedefinedAt(later_instr, addi_dst, areRegsEqual)) {
break; // 寄存器被重新定义,可以安全优化
}
// 如果寄存器被使用,则不能优化
if (isRegUsedLater(instrs, addi_dst, j)) {
canOptimize = false;
break;
}
}
if (canOptimize) {
int64_t new_offset = addi_imm->getValue() + mem_imm->getValue();
// 检查新偏移量是否符合 RISC-V 12位有符号立即数范围
if (new_offset >= -2048 && new_offset <= 2047) {
auto new_mem_op = std::make_unique<MemOperand>(
std::make_unique<RegOperand>(*addi_base),
std::make_unique<ImmOperand>(new_offset));
mi2->getOperands()[1] = std::move(new_mem_op);
instrs.erase(instrs.begin() + i);
changed = true;
}
}
}
}
}
}
// 5. 冗余移动指令消除: mv x, y; op z, x, ... -> op z, y, ... (如果 x
// 之后不再使用)
else if (mi1->getOpcode() == RVOpcodes::MV &&
mi1->getOperands().size() == 2) {
if (mi1->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[1]->getKind() == MachineOperand::KIND_REG) {
auto *mv_dst = static_cast<RegOperand *>(mi1->getOperands()[0].get());
auto *mv_src = static_cast<RegOperand *>(mi1->getOperands()[1].get());
// 检查第二条指令是否使用了 mv 的目标寄存器
std::vector<size_t> use_positions;
for (size_t k = 1; k < mi2->getOperands().size(); ++k) {
if (mi2->getOperands()[k]->getKind() == MachineOperand::KIND_REG) {
auto *use_reg =
static_cast<RegOperand *>(mi2->getOperands()[k].get());
if (areRegsEqual(mv_dst, use_reg)) {
use_positions.push_back(k);
}
}
// 也检查内存操作数中的基址寄存器
else if (mi2->getOperands()[k]->getKind() ==
MachineOperand::KIND_MEM) {
auto *mem =
static_cast<MemOperand *>(mi2->getOperands()[k].get());
if (areRegsEqual(mv_dst, mem->getBase())) {
// 对于内存操作数我们需要创建新的MemOperand
auto new_mem = std::make_unique<MemOperand>(
std::make_unique<RegOperand>(*mv_src),
std::make_unique<ImmOperand>(mem->getOffset()->getValue()));
mi2->getOperands()[k] = std::move(new_mem);
use_positions.push_back(k); // 标记已处理
}
}
}
if (!use_positions.empty()) {
// 改进的后续使用检查
bool canOptimize = true;
for (size_t j = i + 2; j < instrs.size(); ++j) {
auto *later_instr = instrs[j].get();
// 如果寄存器被重新定义,后续使用就不相关了
if (isRegRedefinedAt(later_instr, mv_dst, areRegsEqual)) {
break;
}
// 检查是否还有其他使用
if (isRegUsedLater(instrs, mv_dst, j)) {
canOptimize = false;
break;
}
}
if (canOptimize) {
// 替换所有寄存器使用(内存操作数已在上面处理)
for (size_t pos : use_positions) {
if (mi2->getOperands()[pos]->getKind() ==
MachineOperand::KIND_REG) {
mi2->getOperands()[pos] =
std::make_unique<RegOperand>(*mv_src);
}
}
instrs.erase(instrs.begin() + i);
changed = true;
}
}
}
}
// 6. 连续加法指令合并: addi t1, t0, imm1; addi t2, t1, imm2 -> addi t2,
// t0, (imm1+imm2)
else if (mi1->getOpcode() == RVOpcodes::ADDI &&
mi2->getOpcode() == RVOpcodes::ADDI) {
if (mi1->getOperands().size() == 3 && mi2->getOperands().size() == 3) {
if (mi1->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[1]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[2]->getKind() == MachineOperand::KIND_IMM &&
mi2->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi2->getOperands()[1]->getKind() == MachineOperand::KIND_REG &&
mi2->getOperands()[2]->getKind() == MachineOperand::KIND_IMM) {
auto *addi1_dst =
static_cast<RegOperand *>(mi1->getOperands()[0].get());
auto *addi1_src =
static_cast<RegOperand *>(mi1->getOperands()[1].get());
auto *addi1_imm =
static_cast<ImmOperand *>(mi1->getOperands()[2].get());
auto *addi2_dst =
static_cast<RegOperand *>(mi2->getOperands()[0].get());
auto *addi2_src =
static_cast<RegOperand *>(mi2->getOperands()[1].get());
auto *addi2_imm =
static_cast<ImmOperand *>(mi2->getOperands()[2].get());
// 检查第一个ADDI的目标是否是第二个ADDI的源
if (areRegsEqual(addi1_dst, addi2_src)) {
// 改进的中间寄存器使用检查
bool canOptimize = true;
for (size_t j = i + 2; j < instrs.size(); ++j) {
auto *later_instr = instrs[j].get();
// 如果中间寄存器被重新定义,后续使用不相关
if (isRegRedefinedAt(later_instr, addi1_dst, areRegsEqual)) {
break;
}
// 检查是否有其他使用
if (isRegUsedLater(instrs, addi1_dst, j)) {
canOptimize = false;
break;
}
}
if (canOptimize) {
int64_t new_imm = addi1_imm->getValue() + addi2_imm->getValue();
// 检查新立即数范围
if (new_imm >= -2048 && new_imm <= 2047) {
auto newInstr =
std::make_unique<MachineInstr>(RVOpcodes::ADDI);
newInstr->addOperand(
std::make_unique<RegOperand>(*addi2_dst));
newInstr->addOperand(
std::make_unique<RegOperand>(*addi1_src));
newInstr->addOperand(std::make_unique<ImmOperand>(new_imm));
instrs[i + 1] = std::move(newInstr);
instrs.erase(instrs.begin() + i);
changed = true;
}
}
}
}
}
}
// 7. ADD with zero optimization: add r1, r2, zero -> mv r1, r2
else if (mi1->getOpcode() == RVOpcodes::ADD &&
mi1->getOperands().size() == 3) {
if (mi1->getOperands()[0]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[1]->getKind() == MachineOperand::KIND_REG &&
mi1->getOperands()[2]->getKind() == MachineOperand::KIND_REG) {
auto *add_dst =
static_cast<RegOperand *>(mi1->getOperands()[0].get());
auto *add_src1 =
static_cast<RegOperand *>(mi1->getOperands()[1].get());
auto *add_src2 =
static_cast<RegOperand *>(mi1->getOperands()[2].get());
// 检查第二个源操作数是否为ZERO寄存器
if (!add_src2->isVirtual() &&
add_src2->getPReg() == PhysicalReg::ZERO) {
// 创建新的 MV 指令
auto newInstr = std::make_unique<MachineInstr>(RVOpcodes::MV);
newInstr->addOperand(std::make_unique<RegOperand>(*add_dst));
newInstr->addOperand(std::make_unique<RegOperand>(*add_src1));
instrs[i] = std::move(newInstr);
changed = true;
}
}
}
// 根据是否发生变化调整遍历索引
if (!changed) {
++i; // 没有优化,继续检查下一对指令
} else {
// 发生变化,适当回退以捕获新的优化机会。
// 这是一种安全的回退策略,可以触发连锁优化,且不会导致无限循环。
if (i > 0) {
--i;
}
}
}
}
}
} // namespace sysy

View File

@ -0,0 +1,416 @@
#include "PostRA_Scheduler.h"
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#define MAX_SCHEDULING_BLOCK_SIZE 10000 // 限制调度块大小,避免过大导致性能问题
namespace sysy {
char PostRA_Scheduler::ID = 0;
// 检查指令是否是加载指令 (LW, LD)
bool isLoadInstr(MachineInstr *instr) {
RVOpcodes opcode = instr->getOpcode();
return opcode == RVOpcodes::LW || opcode == RVOpcodes::LD ||
opcode == RVOpcodes::LH || opcode == RVOpcodes::LB ||
opcode == RVOpcodes::LHU || opcode == RVOpcodes::LBU ||
opcode == RVOpcodes::LWU;
}
// 检查指令是否是存储指令 (SW, SD)
bool isStoreInstr(MachineInstr *instr) {
RVOpcodes opcode = instr->getOpcode();
return opcode == RVOpcodes::SW || opcode == RVOpcodes::SD ||
opcode == RVOpcodes::SH || opcode == RVOpcodes::SB;
}
// 检查指令是否为控制流指令
bool isControlFlowInstr(MachineInstr *instr) {
RVOpcodes opcode = instr->getOpcode();
return opcode == RVOpcodes::RET || opcode == RVOpcodes::J ||
opcode == RVOpcodes::BEQ || opcode == RVOpcodes::BNE ||
opcode == RVOpcodes::BLT || opcode == RVOpcodes::BGE ||
opcode == RVOpcodes::BLTU || opcode == RVOpcodes::BGEU ||
opcode == RVOpcodes::CALL;
}
// 预计算指令信息的缓存
static std::unordered_map<MachineInstr *, InstrRegInfo> instr_info_cache;
// 获取指令定义的寄存器 - 优化版本
std::unordered_set<PhysicalReg> getDefinedRegisters(MachineInstr *instr) {
std::unordered_set<PhysicalReg> defined_regs;
RVOpcodes opcode = instr->getOpcode();
// 特殊处理CALL指令
if (opcode == RVOpcodes::CALL) {
// CALL指令可能定义返回值寄存器
if (!instr->getOperands().empty() &&
instr->getOperands().front()->getKind() == MachineOperand::KIND_REG) {
auto reg_op =
static_cast<RegOperand *>(instr->getOperands().front().get());
if (!reg_op->isVirtual()) {
defined_regs.insert(reg_op->getPReg());
}
}
return defined_regs;
}
// 存储指令不定义寄存器
if (isStoreInstr(instr)) {
return defined_regs;
}
// 分支指令不定义寄存器
if (opcode == RVOpcodes::BEQ || opcode == RVOpcodes::BNE ||
opcode == RVOpcodes::BLT || opcode == RVOpcodes::BGE ||
opcode == RVOpcodes::BLTU || opcode == RVOpcodes::BGEU ||
opcode == RVOpcodes::J || opcode == RVOpcodes::RET) {
return defined_regs;
}
// 对于其他指令,第一个寄存器操作数通常是定义的
if (!instr->getOperands().empty() &&
instr->getOperands().front()->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand *>(instr->getOperands().front().get());
if (!reg_op->isVirtual()) {
defined_regs.insert(reg_op->getPReg());
}
}
return defined_regs;
}
// 获取指令使用的寄存器 - 优化版本
std::unordered_set<PhysicalReg> getUsedRegisters(MachineInstr *instr) {
std::unordered_set<PhysicalReg> used_regs;
RVOpcodes opcode = instr->getOpcode();
// 特殊处理CALL指令
if (opcode == RVOpcodes::CALL) {
bool first_reg_skipped = false;
for (const auto &op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) {
if (!first_reg_skipped) {
first_reg_skipped = true;
continue; // 跳过返回值寄存器
}
auto reg_op = static_cast<RegOperand *>(op.get());
if (!reg_op->isVirtual()) {
used_regs.insert(reg_op->getPReg());
}
}
}
return used_regs;
}
// 对于存储指令,所有寄存器操作数都是使用的
if (isStoreInstr(instr)) {
for (const auto &op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand *>(op.get());
if (!reg_op->isVirtual()) {
used_regs.insert(reg_op->getPReg());
}
} else if (op->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand *>(op.get());
if (!mem_op->getBase()->isVirtual()) {
used_regs.insert(mem_op->getBase()->getPReg());
}
}
}
return used_regs;
}
// 对于分支指令,所有寄存器操作数都是使用的
if (opcode == RVOpcodes::BEQ || opcode == RVOpcodes::BNE ||
opcode == RVOpcodes::BLT || opcode == RVOpcodes::BGE ||
opcode == RVOpcodes::BLTU || opcode == RVOpcodes::BGEU) {
for (const auto &op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand *>(op.get());
if (!reg_op->isVirtual()) {
used_regs.insert(reg_op->getPReg());
}
}
}
return used_regs;
}
// 对于其他指令,除了第一个寄存器操作数(通常是定义),其余都是使用的
bool first_reg = true;
for (const auto &op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) {
if (first_reg) {
first_reg = false;
continue; // 跳过第一个寄存器(定义)
}
auto reg_op = static_cast<RegOperand *>(op.get());
if (!reg_op->isVirtual()) {
used_regs.insert(reg_op->getPReg());
}
} else if (op->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand *>(op.get());
if (!mem_op->getBase()->isVirtual()) {
used_regs.insert(mem_op->getBase()->getPReg());
}
}
}
return used_regs;
}
// 获取内存访问的基址和偏移
MemoryAccess getMemoryAccess(MachineInstr *instr) {
if (!isLoadInstr(instr) && !isStoreInstr(instr)) {
return MemoryAccess();
}
// 查找内存操作数
for (const auto &op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand *>(op.get());
if (!mem_op->getBase()->isVirtual()) {
return MemoryAccess(mem_op->getBase()->getPReg(),
mem_op->getOffset()->getValue());
}
}
}
return MemoryAccess();
}
// 预计算指令信息
InstrRegInfo &getInstrInfo(MachineInstr *instr) {
auto it = instr_info_cache.find(instr);
if (it != instr_info_cache.end()) {
return it->second;
}
InstrRegInfo &info = instr_info_cache[instr];
info.defined_regs = getDefinedRegisters(instr);
info.used_regs = getUsedRegisters(instr);
info.is_load = isLoadInstr(instr);
info.is_store = isStoreInstr(instr);
info.is_control_flow = isControlFlowInstr(instr);
info.mem_access = getMemoryAccess(instr);
return info;
}
// 检查内存依赖 - 优化版本
bool hasMemoryDependency(const InstrRegInfo &info1, const InstrRegInfo &info2) {
// 如果都不是内存指令,没有内存依赖
if (!info1.is_load && !info1.is_store && !info2.is_load && !info2.is_store) {
return false;
}
const MemoryAccess &mem1 = info1.mem_access;
const MemoryAccess &mem2 = info2.mem_access;
if (!mem1.valid || !mem2.valid) {
// 如果无法确定内存访问模式,保守地认为存在依赖
return true;
}
// 如果访问相同的内存位置
if (mem1.base_reg == mem2.base_reg && mem1.offset == mem2.offset) {
// Store->Load: RAW依赖
// Load->Store: WAR依赖
// Store->Store: WAW依赖
return info1.is_store || info2.is_store;
}
// 不同内存位置通常没有依赖,但为了安全起见,
// 如果涉及store指令我们需要更保守
if (info1.is_store && info2.is_load) {
// 保守处理不同store和load之间可能有别名
return false; // 这里可以根据需要调整策略
}
return false;
}
// 检查两个指令之间是否存在依赖关系 - 优化版本
bool hasDependency(MachineInstr *instr1, MachineInstr *instr2) {
const InstrRegInfo &info1 = getInstrInfo(instr1);
const InstrRegInfo &info2 = getInstrInfo(instr2);
// 检查RAW依赖instr1定义的寄存器是否被instr2使用
for (const auto &reg : info1.defined_regs) {
if (info2.used_regs.find(reg) != info2.used_regs.end()) {
return true; // RAW依赖 - instr2读取instr1写入的值
}
}
// 检查WAR依赖instr1使用的寄存器是否被instr2定义
for (const auto &reg : info1.used_regs) {
if (info2.defined_regs.find(reg) != info2.defined_regs.end()) {
return true; // WAR依赖 - instr2覆盖instr1需要的值
}
}
// 检查WAW依赖两个指令定义相同寄存器
for (const auto &reg : info1.defined_regs) {
if (info2.defined_regs.find(reg) != info2.defined_regs.end()) {
return true; // WAW依赖 - 两条指令写入同一寄存器
}
}
// 检查内存依赖
if (hasMemoryDependency(info1, info2)) {
return true;
}
return false;
}
// 检查是否可以安全地将instr1和instr2交换位置 - 优化版本
bool canSwapInstructions(MachineInstr *instr1, MachineInstr *instr2) {
const InstrRegInfo &info1 = getInstrInfo(instr1);
const InstrRegInfo &info2 = getInstrInfo(instr2);
// 不能移动控制流指令
if (info1.is_control_flow || info2.is_control_flow) {
return false;
}
// 检查双向依赖关系
return !hasDependency(instr1, instr2) && !hasDependency(instr2, instr1);
}
// 新增:验证调度结果的正确性 - 优化版本
void validateSchedule(const std::vector<MachineInstr *> &instr_list) {
for (int i = 0; i < (int)instr_list.size(); i++) {
for (int j = i + 1; j < (int)instr_list.size(); j++) {
MachineInstr *earlier = instr_list[i];
MachineInstr *later = instr_list[j];
const InstrRegInfo &info_earlier = getInstrInfo(earlier);
const InstrRegInfo &info_later = getInstrInfo(later);
// 检查是否存在被违反的依赖关系
// 检查RAW依赖
for (const auto &reg : info_earlier.defined_regs) {
if (info_later.used_regs.find(reg) != info_later.used_regs.end()) {
// 这是正常的依赖关系earlier应该在later之前
continue;
}
}
// 检查内存依赖
if (hasMemoryDependency(info_earlier, info_later)) {
const MemoryAccess &mem1 = info_earlier.mem_access;
const MemoryAccess &mem2 = info_later.mem_access;
if (mem1.valid && mem2.valid && mem1.base_reg == mem2.base_reg &&
mem1.offset == mem2.offset) {
if (info_earlier.is_store && info_later.is_load) {
// Store->Load依赖顺序正确
continue;
}
}
}
}
}
}
// 在基本块内对指令进行调度优化 - 优化版本
void scheduleBlock(MachineBasicBlock *mbb) {
auto &instructions = mbb->getInstructions();
if (instructions.size() <= 1)
return;
if (instructions.size() > MAX_SCHEDULING_BLOCK_SIZE) {
return; // 跳过超大块,防止卡住
}
// 清理缓存,避免无效指针
instr_info_cache.clear();
std::vector<MachineInstr *> instr_list;
instr_list.reserve(instructions.size()); // 预分配容量
for (auto &instr : instructions) {
instr_list.push_back(instr.get());
}
// 预计算所有指令的信息
for (auto *instr : instr_list) {
getInstrInfo(instr);
}
// 使用更严格的调度策略,避免破坏依赖关系
bool changed = true;
int max_iterations = 10; // 限制迭代次数避免死循环
int iteration = 0;
while (changed && iteration < max_iterations) {
changed = false;
iteration++;
for (int i = 0; i < (int)instr_list.size() - 1; i++) {
MachineInstr *instr1 = instr_list[i];
MachineInstr *instr2 = instr_list[i + 1];
const InstrRegInfo &info1 = getInstrInfo(instr1);
const InstrRegInfo &info2 = getInstrInfo(instr2);
// 只进行非常保守的优化
bool should_swap = false;
// 策略1: 将load指令提前减少load-use延迟
if (info2.is_load && !info1.is_load && !info1.is_store) {
should_swap = canSwapInstructions(instr1, instr2);
}
// 策略2: 将非关键store指令延后为其他指令让路
else if (info1.is_store && !info2.is_load && !info2.is_store) {
should_swap = canSwapInstructions(instr1, instr2);
}
if (should_swap) {
std::swap(instr_list[i], instr_list[i + 1]);
changed = true;
// 调试输出
// std::cout << "Swapped instructions at positions " << i << " and " <<
// (i+1) << std::endl;
}
}
}
// 验证调度结果的正确性
validateSchedule(instr_list);
// 将调度后的指令顺序写回
std::unordered_map<MachineInstr *, std::unique_ptr<MachineInstr>> instr_map;
instr_map.reserve(instructions.size()); // 预分配容量
for (auto &instr : instructions) {
instr_map[instr.get()] = std::move(instr);
}
instructions.clear();
instructions.reserve(instr_list.size()); // 预分配容量
for (auto instr : instr_list) {
instructions.push_back(std::move(instr_map[instr]));
}
}
bool PostRA_Scheduler::runOnFunction(Function *F, AnalysisManager &AM) {
// 这个函数在IR级别运行但我们需要在机器指令级别运行
// 所以我们返回false表示没有对IR进行修改
return false;
}
void PostRA_Scheduler::runOnMachineFunction(MachineFunction *mfunc) {
// std::cout << "Running Post-RA Local Scheduler... " << std::endl;
// 遍历每个机器基本块
for (auto &mbb : mfunc->getBlocks()) {
scheduleBlock(mbb.get());
}
// 清理全局缓存
instr_info_cache.clear();
}
} // namespace sysy

View File

@ -0,0 +1,466 @@
#include "PreRA_Scheduler.h"
#include "RISCv64LLIR.h"
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#define MAX_SCHEDULING_BLOCK_SIZE 1000 // 严格限制调度块大小
namespace sysy {
char PreRA_Scheduler::ID = 0;
// 检查指令是否是加载指令 (LW, LD)
static bool isLoadInstr(MachineInstr *instr) {
RVOpcodes opcode = instr->getOpcode();
return opcode == RVOpcodes::LW || opcode == RVOpcodes::LD ||
opcode == RVOpcodes::LH || opcode == RVOpcodes::LB ||
opcode == RVOpcodes::LHU || opcode == RVOpcodes::LBU ||
opcode == RVOpcodes::LWU;
}
// 检查指令是否是存储指令 (SW, SD)
static bool isStoreInstr(MachineInstr *instr) {
RVOpcodes opcode = instr->getOpcode();
return opcode == RVOpcodes::SW || opcode == RVOpcodes::SD ||
opcode == RVOpcodes::SH || opcode == RVOpcodes::SB;
}
// 检查指令是否为分支指令
static bool isBranchInstr(MachineInstr *instr) {
RVOpcodes opcode = instr->getOpcode();
return opcode == RVOpcodes::BEQ || opcode == RVOpcodes::BNE ||
opcode == RVOpcodes::BLT || opcode == RVOpcodes::BGE ||
opcode == RVOpcodes::BLTU || opcode == RVOpcodes::BGEU;
}
// 检查指令是否为跳转指令
static bool isJumpInstr(MachineInstr *instr) {
RVOpcodes opcode = instr->getOpcode();
return opcode == RVOpcodes::J;
}
// 检查指令是否为返回指令
static bool isReturnInstr(MachineInstr *instr) {
return instr->getOpcode() == RVOpcodes::RET;
}
// 检查指令是否为调用指令
static bool isCallInstr(MachineInstr *instr) {
return instr->getOpcode() == RVOpcodes::CALL;
}
// 检查指令是否为块终结指令(必须保持在块尾)
static bool isTerminatorInstr(MachineInstr *instr) {
return isBranchInstr(instr) || isJumpInstr(instr) || isReturnInstr(instr);
}
// 检查指令是否有副作用(需要谨慎处理)
static bool hasSideEffect(MachineInstr *instr) {
return isStoreInstr(instr) || isCallInstr(instr) || isTerminatorInstr(instr);
}
// 检查指令是否涉及内存操作
static bool hasMemoryAccess(MachineInstr *instr) {
return isLoadInstr(instr) || isStoreInstr(instr);
}
// 获取内存访问位置信息
struct MemoryLocation {
unsigned base_reg;
int64_t offset;
bool is_valid;
MemoryLocation() : base_reg(0), offset(0), is_valid(false) {}
MemoryLocation(unsigned base, int64_t off)
: base_reg(base), offset(off), is_valid(true) {}
bool operator==(const MemoryLocation &other) const {
return is_valid && other.is_valid && base_reg == other.base_reg &&
offset == other.offset;
}
};
// 缓存指令分析信息
struct InstrInfo {
std::unordered_set<unsigned> defined_regs;
std::unordered_set<unsigned> used_regs;
MemoryLocation mem_location;
bool is_load;
bool is_store;
bool is_terminator;
bool is_call;
bool has_side_effect;
bool has_memory_access;
InstrInfo() : is_load(false), is_store(false), is_terminator(false),
is_call(false), has_side_effect(false), has_memory_access(false) {}
};
// 指令信息缓存
static std::unordered_map<MachineInstr*, InstrInfo> instr_info_cache;
// 获取指令定义的虚拟寄存器 - 优化版本
static std::unordered_set<unsigned> getDefinedVirtualRegisters(MachineInstr *instr) {
std::unordered_set<unsigned> defined_regs;
RVOpcodes opcode = instr->getOpcode();
// CALL指令可能定义返回值寄存器
if (opcode == RVOpcodes::CALL) {
if (!instr->getOperands().empty() &&
instr->getOperands().front()->getKind() == MachineOperand::KIND_REG) {
auto reg_op =
static_cast<RegOperand *>(instr->getOperands().front().get());
if (reg_op->isVirtual()) {
defined_regs.insert(reg_op->getVRegNum());
}
}
return defined_regs;
}
// 存储指令和终结指令不定义寄存器
if (isStoreInstr(instr) || isTerminatorInstr(instr)) {
return defined_regs;
}
// 其他指令的第一个操作数通常是目标寄存器
if (!instr->getOperands().empty() &&
instr->getOperands().front()->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand *>(instr->getOperands().front().get());
if (reg_op->isVirtual()) {
defined_regs.insert(reg_op->getVRegNum());
}
}
return defined_regs;
}
// 获取指令使用的虚拟寄存器 - 优化版本
static std::unordered_set<unsigned> getUsedVirtualRegisters(MachineInstr *instr) {
std::unordered_set<unsigned> used_regs;
RVOpcodes opcode = instr->getOpcode();
// CALL指令跳过第一个操作数返回值其余为参数
if (opcode == RVOpcodes::CALL) {
bool first_reg_skipped = false;
for (const auto &op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) {
if (!first_reg_skipped) {
first_reg_skipped = true;
continue;
}
auto reg_op = static_cast<RegOperand *>(op.get());
if (reg_op->isVirtual()) {
used_regs.insert(reg_op->getVRegNum());
}
}
}
return used_regs;
}
// 存储指令和终结指令:所有操作数都是使用的
if (isStoreInstr(instr) || isTerminatorInstr(instr)) {
for (const auto &op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand *>(op.get());
if (reg_op->isVirtual()) {
used_regs.insert(reg_op->getVRegNum());
}
} else if (op->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand *>(op.get());
if (mem_op->getBase()->isVirtual()) {
used_regs.insert(mem_op->getBase()->getVRegNum());
}
}
}
return used_regs;
}
// 其他指令:跳过第一个操作数(目标寄存器),其余为源操作数
bool first_reg = true;
for (const auto &op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) {
if (first_reg) {
first_reg = false;
continue;
}
auto reg_op = static_cast<RegOperand *>(op.get());
if (reg_op->isVirtual()) {
used_regs.insert(reg_op->getVRegNum());
}
} else if (op->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand *>(op.get());
if (mem_op->getBase()->isVirtual()) {
used_regs.insert(mem_op->getBase()->getVRegNum());
}
}
}
return used_regs;
}
// 获取内存访问位置
static MemoryLocation getMemoryLocation(MachineInstr *instr) {
if (!isLoadInstr(instr) && !isStoreInstr(instr)) {
return MemoryLocation();
}
for (const auto &op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand *>(op.get());
if (mem_op->getBase()->isVirtual()) {
return MemoryLocation(mem_op->getBase()->getVRegNum(),
mem_op->getOffset()->getValue());
}
}
}
return MemoryLocation();
}
// 预计算并缓存指令信息
static const InstrInfo& getInstrInfo(MachineInstr *instr) {
auto it = instr_info_cache.find(instr);
if (it != instr_info_cache.end()) {
return it->second;
}
InstrInfo& info = instr_info_cache[instr];
info.defined_regs = getDefinedVirtualRegisters(instr);
info.used_regs = getUsedVirtualRegisters(instr);
info.mem_location = getMemoryLocation(instr);
info.is_load = isLoadInstr(instr);
info.is_store = isStoreInstr(instr);
info.is_terminator = isTerminatorInstr(instr);
info.is_call = isCallInstr(instr);
info.has_side_effect = hasSideEffect(instr);
info.has_memory_access = hasMemoryAccess(instr);
return info;
}
// 检查两个内存位置是否可能别名
static bool mayAlias(const MemoryLocation &loc1, const MemoryLocation &loc2) {
if (!loc1.is_valid || !loc2.is_valid) {
return true; // 保守处理:未知位置可能别名
}
// 不同基址寄存器,保守假设可能别名
if (loc1.base_reg != loc2.base_reg) {
return true;
}
// 相同基址寄存器,检查偏移
return loc1.offset == loc2.offset;
}
// 检查两个指令之间是否存在数据依赖 - 优化版本
static bool hasDataDependency(MachineInstr *first, MachineInstr *second) {
const InstrInfo& info_first = getInstrInfo(first);
const InstrInfo& info_second = getInstrInfo(second);
// RAW依赖: second读取first写入的寄存器
for (const auto &reg : info_first.defined_regs) {
if (info_second.used_regs.find(reg) != info_second.used_regs.end()) {
return true;
}
}
// WAR依赖: second写入first读取的寄存器
for (const auto &reg : info_first.used_regs) {
if (info_second.defined_regs.find(reg) != info_second.defined_regs.end()) {
return true;
}
}
// WAW依赖: 两个指令写入同一寄存器
for (const auto &reg : info_first.defined_regs) {
if (info_second.defined_regs.find(reg) != info_second.defined_regs.end()) {
return true;
}
}
return false;
}
// 检查两个指令之间是否存在内存依赖 - 优化版本
static bool hasMemoryDependency(MachineInstr *first, MachineInstr *second) {
const InstrInfo& info_first = getInstrInfo(first);
const InstrInfo& info_second = getInstrInfo(second);
if (!info_first.has_memory_access || !info_second.has_memory_access) {
return false;
}
// 如果至少有一个是存储指令,需要检查别名
if (info_first.is_store || info_second.is_store) {
return mayAlias(info_first.mem_location, info_second.mem_location);
}
return false; // 两个加载指令之间没有依赖
}
// 检查两个指令之间是否存在控制依赖 - 优化版本
static bool hasControlDependency(MachineInstr *first, MachineInstr *second) {
const InstrInfo& info_first = getInstrInfo(first);
const InstrInfo& info_second = getInstrInfo(second);
// 终结指令与任何其他指令都有控制依赖
if (info_first.is_terminator) {
return true; // first是终结指令second不能移动到first之前
}
if (info_second.is_terminator) {
return false; // second是终结指令可以保持在后面
}
// CALL指令具有控制副作用但可以参与有限的调度
if (info_first.is_call || info_second.is_call) {
// CALL指令之间保持顺序
if (info_first.is_call && info_second.is_call) {
return true;
}
// 其他情况允许调度(通过数据依赖控制)
}
return false;
}
// 综合检查两个指令是否可以交换 - 优化版本
static bool canSwapInstructions(MachineInstr *first, MachineInstr *second) {
// 检查所有类型的依赖
if (hasDataDependency(first, second) || hasDataDependency(second, first)) {
return false;
}
if (hasMemoryDependency(first, second)) {
return false;
}
if (hasControlDependency(first, second) ||
hasControlDependency(second, first)) {
return false;
}
return true;
}
// 找到基本块中的调度边界 - 优化版本
static std::vector<size_t>
findSchedulingBoundaries(const std::vector<MachineInstr *> &instrs) {
std::vector<size_t> boundaries;
boundaries.reserve(instrs.size() / 10); // 预估边界数量
boundaries.push_back(0); // 起始边界
for (size_t i = 0; i < instrs.size(); i++) {
const InstrInfo& info = getInstrInfo(instrs[i]);
// 终结指令前后都是边界
if (info.is_terminator) {
if (i > 0)
boundaries.push_back(i);
if (i + 1 < instrs.size())
boundaries.push_back(i + 1);
}
// 跳转目标标签也可能是边界(这里简化处理)
}
boundaries.push_back(instrs.size()); // 结束边界
// 去重并排序
std::sort(boundaries.begin(), boundaries.end());
boundaries.erase(std::unique(boundaries.begin(), boundaries.end()),
boundaries.end());
return boundaries;
}
// 在单个调度区域内进行指令调度 - 优化版本
static void scheduleRegion(std::vector<MachineInstr *> &instrs, size_t start,
size_t end) {
if (end - start <= 1) {
return; // 区域太小,无需调度
}
// 保守的调度策略:
// 1. 只对小规模区域进行调度
// 2. 优先将加载指令向前调度,以隐藏内存延迟
// 3. 确保不破坏数据依赖和内存依赖
// 简单的调度算法:只尝试将加载指令尽可能前移
for (size_t i = start + 1; i < end; i++) {
const InstrInfo& info = getInstrInfo(instrs[i]);
if (info.is_load) {
// 尝试将加载指令向前移动
for (size_t j = i; j > start; j--) {
// 检查是否可以与前一条指令交换
if (canSwapInstructions(instrs[j - 1], instrs[j])) {
std::swap(instrs[j - 1], instrs[j]);
} else {
// 一旦遇到依赖关系就停止移动
break;
}
}
}
}
}
static void scheduleBlock(MachineBasicBlock *mbb) {
auto &instructions = mbb->getInstructions();
if (instructions.size() <= 1 ||
instructions.size() > MAX_SCHEDULING_BLOCK_SIZE) {
return;
}
// 清理缓存,避免无效指针
instr_info_cache.clear();
// 构建指令列表
std::vector<MachineInstr *> instr_list;
instr_list.reserve(instructions.size()); // 预分配容量
for (auto &instr : instructions) {
instr_list.push_back(instr.get());
}
// 预计算所有指令信息
for (auto* instr : instr_list) {
getInstrInfo(instr);
}
// 找到调度边界
std::vector<size_t> boundaries = findSchedulingBoundaries(instr_list);
// 在每个调度区域内进行局部调度
for (size_t i = 0; i < boundaries.size() - 1; i++) {
size_t region_start = boundaries[i];
size_t region_end = boundaries[i + 1];
scheduleRegion(instr_list, region_start, region_end);
}
// 重建指令序列
std::unordered_map<MachineInstr *, std::unique_ptr<MachineInstr>> instr_map;
instr_map.reserve(instructions.size()); // 预分配容量
for (auto &instr : instructions) {
instr_map[instr.get()] = std::move(instr);
}
instructions.clear();
instructions.reserve(instr_list.size()); // 预分配容量
for (auto *instr : instr_list) {
instructions.push_back(std::move(instr_map[instr]));
}
}
bool PreRA_Scheduler::runOnFunction(Function *F, AnalysisManager &AM) {
return false;
}
void PreRA_Scheduler::runOnMachineFunction(MachineFunction *mfunc) {
for (auto &mbb : mfunc->getBlocks()) {
scheduleBlock(mbb.get());
}
// 清理全局缓存
instr_info_cache.clear();
}
} // namespace sysy

View File

@ -1,15 +1,22 @@
#include "RISCv64AsmPrinter.h"
#include "RISCv64ISel.h"
#include <stdexcept>
#include <sstream>
#include <iostream>
namespace sysy {
// 检查是否为内存加载/存储指令,以处理特殊的打印格式
bool isMemoryOp(RVOpcodes opcode) {
switch (opcode) {
// --- 整数加载/存储 (原有逻辑) ---
case RVOpcodes::LB: case RVOpcodes::LH: case RVOpcodes::LW: case RVOpcodes::LD:
case RVOpcodes::LBU: case RVOpcodes::LHU: case RVOpcodes::LWU:
case RVOpcodes::SB: case RVOpcodes::SH: case RVOpcodes::SW: case RVOpcodes::SD:
case RVOpcodes::FLW:
case RVOpcodes::FSW:
// 如果未来支持双精度也在这里添加FLD/FSD
// case RVOpcodes::FLD:
// case RVOpcodes::FSD:
return true;
default:
return false;
@ -22,41 +29,12 @@ void RISCv64AsmPrinter::run(std::ostream& os, bool debug) {
OS = &os;
*OS << ".globl " << MFunc->getName() << "\n";
*OS << MFunc->getName() << ":\n";
printPrologue();
for (auto& mbb : MFunc->getBlocks()) {
printBasicBlock(mbb.get(), debug);
}
}
// 在 RISCv64AsmPrinter.cpp 文件中
void RISCv64AsmPrinter::printPrologue() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
// 序言需要为保存ra和s0预留16字节
int total_stack_size = frame_info.locals_size + frame_info.spill_size + 16;
int aligned_stack_size = (total_stack_size + 15) & ~15;
frame_info.total_size = aligned_stack_size;
if (aligned_stack_size > 0) {
*OS << " addi sp, sp, -" << aligned_stack_size << "\n";
*OS << " sd ra, " << (aligned_stack_size - 8) << "(sp)\n";
*OS << " sd s0, " << (aligned_stack_size - 16) << "(sp)\n";
*OS << " addi s0, sp, " << aligned_stack_size << "\n";
}
}
void RISCv64AsmPrinter::printEpilogue() {
int aligned_stack_size = MFunc->getFrameInfo().total_size;
if (aligned_stack_size > 0) {
*OS << " ld ra, " << (aligned_stack_size - 8) << "(sp)\n";
*OS << " ld s0, " << (aligned_stack_size - 16) << "(sp)\n";
*OS << " addi sp, sp, " << aligned_stack_size << "\n";
}
}
void RISCv64AsmPrinter::printBasicBlock(MachineBasicBlock* mbb, bool debug) {
if (!mbb->getName().empty()) {
*OS << mbb->getName() << ":\n";
@ -68,9 +46,6 @@ void RISCv64AsmPrinter::printBasicBlock(MachineBasicBlock* mbb, bool debug) {
void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
auto opcode = instr->getOpcode();
if (opcode == RVOpcodes::RET) {
printEpilogue();
}
if (opcode == RVOpcodes::LABEL) {
// 标签直接打印,不加缩进
@ -86,7 +61,7 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
case RVOpcodes::ADD: *OS << "add "; break; case RVOpcodes::ADDI: *OS << "addi "; break;
case RVOpcodes::ADDW: *OS << "addw "; break; case RVOpcodes::ADDIW: *OS << "addiw "; break;
case RVOpcodes::SUB: *OS << "sub "; break; case RVOpcodes::SUBW: *OS << "subw "; break;
case RVOpcodes::MUL: *OS << "mul "; break; case RVOpcodes::MULW: *OS << "mulw "; break;
case RVOpcodes::MUL: *OS << "mul "; break; case RVOpcodes::MULW: *OS << "mulw "; break; case RVOpcodes::MULH: *OS << "mulh "; break;
case RVOpcodes::DIV: *OS << "div "; break; case RVOpcodes::DIVW: *OS << "divw "; break;
case RVOpcodes::REM: *OS << "rem "; break; case RVOpcodes::REMW: *OS << "remw "; break;
case RVOpcodes::XOR: *OS << "xor "; break; case RVOpcodes::XORI: *OS << "xori "; break;
@ -105,7 +80,9 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
case RVOpcodes::LHU: *OS << "lhu "; break; case RVOpcodes::LBU: *OS << "lbu "; break;
case RVOpcodes::SW: *OS << "sw "; break; case RVOpcodes::SH: *OS << "sh "; break;
case RVOpcodes::SB: *OS << "sb "; break; case RVOpcodes::LD: *OS << "ld "; break;
case RVOpcodes::SD: *OS << "sd "; break;
case RVOpcodes::SD: *OS << "sd "; break; case RVOpcodes::FLW: *OS << "flw "; break;
case RVOpcodes::FSW: *OS << "fsw "; break; case RVOpcodes::FLD: *OS << "fld "; break;
case RVOpcodes::FSD: *OS << "fsd "; break;
case RVOpcodes::J: *OS << "j "; break; case RVOpcodes::JAL: *OS << "jal "; break;
case RVOpcodes::JALR: *OS << "jalr "; break; case RVOpcodes::RET: *OS << "ret"; break;
case RVOpcodes::BEQ: *OS << "beq "; break; case RVOpcodes::BNE: *OS << "bne "; break;
@ -114,8 +91,32 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
case RVOpcodes::LI: *OS << "li "; break; case RVOpcodes::LA: *OS << "la "; break;
case RVOpcodes::MV: *OS << "mv "; break; case RVOpcodes::NEG: *OS << "neg "; break;
case RVOpcodes::NEGW: *OS << "negw "; break; case RVOpcodes::SEQZ: *OS << "seqz "; break;
case RVOpcodes::SNEZ: *OS << "snez "; break;
case RVOpcodes::CALL: *OS << "call "; break;
case RVOpcodes::SNEZ: *OS << "snez "; break;
case RVOpcodes::FADD_S: *OS << "fadd.s "; break;
case RVOpcodes::FSUB_S: *OS << "fsub.s "; break;
case RVOpcodes::FMUL_S: *OS << "fmul.s "; break;
case RVOpcodes::FDIV_S: *OS << "fdiv.s "; break;
case RVOpcodes::FNEG_S: *OS << "fneg.s "; break;
case RVOpcodes::FEQ_S: *OS << "feq.s "; break;
case RVOpcodes::FLT_S: *OS << "flt.s "; break;
case RVOpcodes::FLE_S: *OS << "fle.s "; break;
case RVOpcodes::FCVT_S_W: *OS << "fcvt.s.w "; break;
case RVOpcodes::FCVT_W_S: *OS << "fcvt.w.s "; break;
case RVOpcodes::FMV_S: *OS << "fmv.s "; break;
case RVOpcodes::FMV_W_X: *OS << "fmv.w.x "; break;
case RVOpcodes::FMV_X_W: *OS << "fmv.x.w "; break;
case RVOpcodes::CALL: { // 为CALL指令添加特殊处理逻辑
*OS << "call ";
// 遍历所有操作数,只寻找并打印函数名标签
for (const auto& op : instr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_LABEL) {
printOperand(op.get());
break; // 找到标签后即可退出
}
}
*OS << "\n";
return; // 处理完毕,直接返回,不再执行后续的通用操作数打印
}
case RVOpcodes::LABEL:
break;
case RVOpcodes::FRAME_LOAD_W:
@ -138,6 +139,15 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
// It should have been eliminated by RegAlloc
if (!debug) throw std::runtime_error("FRAME pseudo-instruction not eliminated before AsmPrinter");
*OS << "frame_addr "; break;
case RVOpcodes::FRAME_LOAD_F:
if (!debug) throw std::runtime_error("FRAME_LOAD_F not eliminated before AsmPrinter");
*OS << "frame_load_f "; break;
case RVOpcodes::FRAME_STORE_F:
if (!debug) throw std::runtime_error("FRAME_STORE_F not eliminated before AsmPrinter");
*OS << "frame_store_f "; break;
case RVOpcodes::PSEUDO_KEEPALIVE:
if (!debug) throw std::runtime_error("PSEUDO_KEEPALIVE not eliminated before AsmPrinter");
*OS << "keepalive "; break;
default:
throw std::runtime_error("Unknown opcode in AsmPrinter");
}
@ -227,4 +237,30 @@ std::string RISCv64AsmPrinter::regToString(PhysicalReg reg) {
}
}
std::string RISCv64AsmPrinter::formatInstr(const MachineInstr* instr) {
if (!instr) return "(null instr)";
// 使用 stringstream 作为临时的输出目标
std::stringstream ss;
// 关键: 临时将类成员 'OS' 指向我们的 stringstream
std::ostream* old_os = this->OS;
this->OS = &ss;
// 修正: 调用正确的内部打印函数 printMachineInstr
printInstruction(const_cast<MachineInstr*>(instr), false);
// 恢复旧的 ostream 指针
this->OS = old_os;
// 获取stringstream的内容并做一些清理
std::string result = ss.str();
size_t endpos = result.find_last_not_of(" \t\n\r");
if (std::string::npos != endpos) {
result = result.substr(0, endpos + 1);
}
return result;
}
} // namespace sysy

View File

@ -0,0 +1,282 @@
#include "RISCv64Backend.h"
#include "RISCv64ISel.h"
#include "RISCv64RegAlloc.h"
#include "RISCv64AsmPrinter.h"
#include "RISCv64Passes.h"
#include <sstream>
namespace sysy {
// 顶层入口
std::string RISCv64CodeGen::code_gen() {
return module_gen();
}
unsigned RISCv64CodeGen::getTypeSizeInBytes(Type* type) {
if (!type) {
assert(false && "Cannot get size of a null type.");
return 0;
}
switch (type->getKind()) {
// 对于SysY语言基本类型int和float都占用4字节
case Type::kInt:
case Type::kFloat:
return 4;
// 指针类型在RISC-V 64位架构下占用8字节
// 虽然SysY没有'int*'语法但数组变量在IR层面本身就是指针类型
case Type::kPointer:
return 8;
// 数组类型的总大小 = 元素数量 * 单个元素的大小
case Type::kArray: {
auto arrayType = type->as<ArrayType>();
// 递归调用以计算元素大小
return arrayType->getNumElements() * getTypeSizeInBytes(arrayType->getElementType());
}
// 其他类型如Void, Label等不占用栈空间或者不应该出现在这里
default:
// 如果遇到未处理的类型,触发断言,方便调试
// assert(false && "Unsupported type for size calculation.");
return 0; // 对于像Label或Void这样的类型返回0是合理的
}
}
void printInitializer(std::stringstream& ss, const ValueCounter& init_values) {
for (size_t i = 0; i < init_values.getValues().size(); ++i) {
auto val = init_values.getValues()[i];
auto count = init_values.getNumbers()[i];
if (auto constant = dynamic_cast<ConstantValue*>(val)) {
for (unsigned j = 0; j < count; ++j) {
if (constant->isInt()) {
ss << " .word " << constant->getInt() << "\n";
} else {
float f = constant->getFloat();
uint32_t float_bits = *(uint32_t*)&f;
ss << " .word " << float_bits << "\n";
}
}
}
}
}
std::string RISCv64CodeGen::module_gen() {
std::stringstream ss;
// --- 步骤1将全局变量(GlobalValue)分为.data和.bss两组 ---
std::vector<GlobalValue*> data_globals;
std::vector<GlobalValue*> bss_globals;
for (const auto& global_ptr : module->getGlobals()) {
GlobalValue* global = global_ptr.get();
// 使用更健壮的逻辑来判断是否为大型零初始化数组
bool is_all_zeros = true;
const auto& init_values = global->getInitValues();
// 检查初始化值是否全部为0
if (init_values.getValues().empty()) {
// 如果 ValueCounter 为空GlobalValue 的构造函数会确保它是零初始化的
is_all_zeros = true;
} else {
for (auto val : init_values.getValues()) {
if (auto const_val = dynamic_cast<ConstantValue*>(val)) {
if (!const_val->isZero()) {
is_all_zeros = false;
break;
}
} else {
// 如果初始值包含非常量(例如,另一个全局变量的地址),则不认为是纯零初始化
is_all_zeros = false;
break;
}
}
}
// 使用 getTypeSizeInBytes 检查总大小是否超过阈值 (16个整数 = 64字节)
Type* allocated_type = global->getType()->as<PointerType>()->getBaseType();
unsigned total_size = getTypeSizeInBytes(allocated_type);
bool is_large_zero_array = is_all_zeros && (total_size > 64);
if (is_large_zero_array) {
bss_globals.push_back(global);
} else {
data_globals.push_back(global);
}
}
// --- 步骤2生成 .bss 段的代码 ---
if (!bss_globals.empty()) {
ss << ".bss\n";
for (GlobalValue* global : bss_globals) {
Type* allocated_type = global->getType()->as<PointerType>()->getBaseType();
unsigned total_size = getTypeSizeInBytes(allocated_type);
ss << " .align 3\n";
ss << ".globl " << global->getName() << "\n";
ss << ".type " << global->getName() << ", @object\n";
ss << ".size " << global->getName() << ", " << total_size << "\n";
ss << global->getName() << ":\n";
ss << " .space " << total_size << "\n";
}
}
// --- 步骤3生成 .data 段的代码 ---
if (!data_globals.empty() || !module->getConsts().empty()) {
ss << ".data\n";
// a. 处理普通的全局变量 (GlobalValue)
for (GlobalValue* global : data_globals) {
Type* allocated_type = global->getType()->as<PointerType>()->getBaseType();
unsigned total_size = getTypeSizeInBytes(allocated_type);
ss << " .align 3\n";
ss << ".globl " << global->getName() << "\n";
ss << ".type " << global->getName() << ", @object\n";
ss << ".size " << global->getName() << ", " << total_size << "\n";
ss << global->getName() << ":\n";
bool is_all_zeros = true;
const auto& init_values = global->getInitValues();
if (init_values.getValues().empty()) {
is_all_zeros = true;
} else {
for (auto val : init_values.getValues()) {
if (auto const_val = dynamic_cast<ConstantValue*>(val)) {
if (!const_val->isZero()) {
is_all_zeros = false;
break;
}
} else {
is_all_zeros = false;
break;
}
}
}
if (is_all_zeros) {
ss << " .zero " << total_size << "\n";
} else {
// 对于有非零初始值的变量,保持原有的打印逻辑。
printInitializer(ss, global->getInitValues());
}
}
// b. 处理全局常量 (ConstantVariable)
for (const auto& const_ptr : module->getConsts()) {
ConstantVariable* cnst = const_ptr.get();
Type* allocated_type = cnst->getType()->as<PointerType>()->getBaseType();
unsigned total_size = getTypeSizeInBytes(allocated_type);
ss << " .align 3\n";
ss << ".globl " << cnst->getName() << "\n";
ss << ".type " << cnst->getName() << ", @object\n";
ss << ".size " << cnst->getName() << ", " << total_size << "\n";
ss << cnst->getName() << ":\n";
printInitializer(ss, cnst->getInitValues());
}
}
// --- 步骤4处理函数 (.text段) 的逻辑 ---
if (!module->getFunctions().empty()) {
ss << ".text\n";
for (const auto& func_pair : module->getFunctions()) {
if (func_pair.second.get() && !func_pair.second->getBasicBlocks().empty()) {
ss << function_gen(func_pair.second.get());
if (DEBUG) std::cerr << "Function: " << func_pair.first << " generated.\n";
}
}
}
return ss.str();
}
std::string RISCv64CodeGen::function_gen(Function* func) {
// === 完整的后端处理流水线 ===
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
DEBUG = 0;
DEEPDEBUG = 0;
RISCv64ISel isel;
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
// 第一次调试打印输出
std::stringstream ss_after_isel;
RISCv64AsmPrinter printer_isel(mfunc.get());
printer_isel.run(ss_after_isel, true);
if (DEBUG) {
std::cout << ss_after_isel.str();
}
if (DEBUG) {
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
<< ss_after_isel.str();
}
// 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
// 这个Pass必须在寄存器分配之前运行
EliminateFrameIndicesPass efi_pass;
efi_pass.runOnMachineFunction(mfunc.get());
if (DEBUG) {
std::cerr << "====== stack info after eliminate frame indices ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
std::stringstream ss_after_eli;
printer_isel.run(ss_after_eli, true);
std::cerr << "====== LLIR after eliminate frame indices ======\n"
<< ss_after_eli.str();
}
// 阶段 2: 除法强度削弱优化 (Division Strength Reduction)
DivStrengthReduction div_strength_reduction;
div_strength_reduction.runOnMachineFunction(mfunc.get());
// 阶段 2.1: 指令调度 (Instruction Scheduling)
PreRA_Scheduler scheduler;
scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3: 物理寄存器分配 (Register Allocation)
RISCv64RegAlloc reg_alloc(mfunc.get());
reg_alloc.run();
if (DEBUG) {
std::cerr << "====== stack info after reg alloc ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
}
// 阶段 3.1: 处理被调用者保存寄存器
CalleeSavedHandler callee_handler;
callee_handler.runOnMachineFunction(mfunc.get());
if (DEBUG) {
std::cerr << "====== stack info after callee handler ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
}
// 阶段 4: 窥孔优化 (Peephole Optimization)
PeepholeOptimizer peephole;
peephole.runOnMachineFunction(mfunc.get());
// 阶段 5: 局部指令调度 (Local Scheduling)
PostRA_Scheduler local_scheduler;
local_scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3.2: 插入序言和尾声
PrologueEpilogueInsertionPass pei_pass;
pei_pass.runOnMachineFunction(mfunc.get());
// 阶段 3.3: 大立即数合法化
LegalizeImmediatesPass legalizer;
legalizer.runOnMachineFunction(mfunc.get());
// 阶段 6: 代码发射 (Code Emission)
std::stringstream ss;
RISCv64AsmPrinter printer(mfunc.get());
printer.run(ss);
return ss.str();
}
} // namespace sysy

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,122 @@
#include "RISCv64LLIR.h"
#include <vector>
#include <iostream> // 用于 std::ostream 和 std::cerr
#include <string> // 用于 std::string
namespace sysy {
// 辅助函数:将 PhysicalReg 枚举转换为可读的字符串
std::string regToString(PhysicalReg reg) {
switch (reg) {
case PhysicalReg::ZERO: return "x0"; case PhysicalReg::RA: return "ra";
case PhysicalReg::SP: return "sp"; case PhysicalReg::GP: return "gp";
case PhysicalReg::TP: return "tp"; case PhysicalReg::T0: return "t0";
case PhysicalReg::T1: return "t1"; case PhysicalReg::T2: return "t2";
case PhysicalReg::S0: return "s0"; case PhysicalReg::S1: return "s1";
case PhysicalReg::A0: return "a0"; case PhysicalReg::A1: return "a1";
case PhysicalReg::A2: return "a2"; case PhysicalReg::A3: return "a3";
case PhysicalReg::A4: return "a4"; case PhysicalReg::A5: return "a5";
case PhysicalReg::A6: return "a6"; case PhysicalReg::A7: return "a7";
case PhysicalReg::S2: return "s2"; case PhysicalReg::S3: return "s3";
case PhysicalReg::S4: return "s4"; case PhysicalReg::S5: return "s5";
case PhysicalReg::S6: return "s6"; case PhysicalReg::S7: return "s7";
case PhysicalReg::S8: return "s8"; case PhysicalReg::S9: return "s9";
case PhysicalReg::S10: return "s10"; case PhysicalReg::S11: return "s11";
case PhysicalReg::T3: return "t3"; case PhysicalReg::T4: return "t4";
case PhysicalReg::T5: return "t5"; case PhysicalReg::T6: return "t6";
case PhysicalReg::F0: return "f0"; case PhysicalReg::F1: return "f1";
case PhysicalReg::F2: return "f2"; case PhysicalReg::F3: return "f3";
case PhysicalReg::F4: return "f4"; case PhysicalReg::F5: return "f5";
case PhysicalReg::F6: return "f6"; case PhysicalReg::F7: return "f7";
case PhysicalReg::F8: return "f8"; case PhysicalReg::F9: return "f9";
case PhysicalReg::F10: return "f10"; case PhysicalReg::F11: return "f11";
case PhysicalReg::F12: return "f12"; case PhysicalReg::F13: return "f13";
case PhysicalReg::F14: return "f14"; case PhysicalReg::F15: return "f15";
case PhysicalReg::F16: return "f16"; case PhysicalReg::F17: return "f17";
case PhysicalReg::F18: return "f18"; case PhysicalReg::F19: return "f19";
case PhysicalReg::F20: return "f20"; case PhysicalReg::F21: return "f21";
case PhysicalReg::F22: return "f22"; case PhysicalReg::F23: return "f23";
case PhysicalReg::F24: return "f24"; case PhysicalReg::F25: return "f25";
case PhysicalReg::F26: return "f26"; case PhysicalReg::F27: return "f27";
case PhysicalReg::F28: return "f28"; case PhysicalReg::F29: return "f29";
case PhysicalReg::F30: return "f30"; case PhysicalReg::F31: return "f31";
default: return "UNKNOWN_REG";
}
}
// 打印栈帧信息的完整实现
void MachineFunction::dumpStackFrameInfo(std::ostream& os) const {
const StackFrameInfo& info = frame_info;
os << "--- Stack Frame Info for function '" << getName() << "' ---\n";
// 打印尺寸信息
os << " Sizes:\n";
os << " Total Size: " << info.total_size << " bytes\n";
os << " Locals Size: " << info.locals_size << " bytes\n";
os << " Spill Size: " << info.spill_size << " bytes\n";
os << " Callee-Saved Size: " << info.callee_saved_size << " bytes\n";
os << "\n";
// 打印 Alloca 变量的偏移量
os << " Alloca Offsets (vreg -> offset from FP):\n";
if (info.alloca_offsets.empty()) {
os << " (None)\n";
} else {
for (const auto& pair : info.alloca_offsets) {
os << " %vreg" << pair.first << " -> " << pair.second << "\n";
}
}
os << "\n";
// 打印溢出变量的偏移量
os << " Spill Offsets (vreg -> offset from FP):\n";
if (info.spill_offsets.empty()) {
os << " (None)\n";
} else {
for (const auto& pair : info.spill_offsets) {
os << " %vreg" << pair.first << " -> " << pair.second << "\n";
}
}
os << "\n";
// 打印使用的被调用者保存寄存器
os << " Used Callee-Saved Registers:\n";
if (info.used_callee_saved_regs.empty()) {
os << " (None)\n";
} else {
os << " { ";
for (const auto& reg : info.used_callee_saved_regs) {
os << regToString(reg) << " ";
}
os << "}\n";
}
os << "\n";
// 打印需要保存/恢复的被调用者保存寄存器 (有序)
os << " Callee-Saved Registers to Store/Restore:\n";
if (info.callee_saved_regs_to_store.empty()) {
os << " (None)\n";
} else {
os << " [ ";
for (const auto& reg : info.callee_saved_regs_to_store) {
os << regToString(reg) << " ";
}
os << "]\n";
}
os << "\n";
// 打印最终的寄存器分配结果
os << " Final Register Allocation Map (vreg -> preg):\n";
if (info.vreg_to_preg_map.empty()) {
os << " (None)\n";
} else {
for (const auto& pair : info.vreg_to_preg_map) {
os << " %vreg" << pair.first << " -> " << regToString(pair.second) << "\n";
}
}
os << "---------------------------------------------------\n";
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
# src/frontend/CMakeLists.txt
add_library(frontend_lib STATIC
SysYBaseVisitor.cpp
SysY.g4
SysYLexer.cpp
SysYParser.cpp
SysYVisitor.cpp
)
# 包含前端模块所需的头文件路径
target_include_directories(frontend_lib PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../include/frontend # 前端头文件
${ANTLR_RUNTIME}/runtime/src # ANTLR 运行时头文件
)
# 链接 ANTLR 运行时库
target_link_libraries(frontend_lib PRIVATE antlr4_shared)

View File

@ -1,59 +0,0 @@
#pragma once
#include "IR.h" // 假设IR.h包含了Module, Function, BasicBlock, Instruction, Value, IRBuilder, Type等定义
#include "IRBuilder.h" // 需要IRBuilder来创建新指令
#include "SysYIRPrinter.h" // 新增: 用于调试输出
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <list> // 用于迭代和修改指令列表
#include <algorithm> // for std::reverse (if needed, although not used in final version)
#include <iostream> // MODIFICATION: 用于警告输出
namespace sysy {
/**
* @brief AddressCalculationExpansion Pass
*
* 这是一个IR优化Pass用于将LoadInst和StoreInst中包含的多维数组索引
* 显式地转换为IR中的BinaryInst乘法和加法序列并生成带有线性偏移量的
* LoadInst/StoreInst。
*
* 目的确保在寄存器分配之前所有中间地址计算的结果都有明确的IR指令和对应的虚拟寄存器
* 从而避免在后端DAG构建时临时创建值而导致寄存器分配缺失的问题。
*
* SysY语言特性
* - 无指针类型所有数组访问的基地址是alloca或global的AllocaType/ArrayType
* - 数据类型只有int和float且都占用4字节。
* - LoadInst和StoreInst直接接受多个索引作为额外操作数。
*/
class AddressCalculationExpansion {
private:
Module* pModule;
IRBuilder* pBuilder; // 用于在IR中插入新指令
// 数组元素的固定大小根据SysY特性int和float都是4字节
static const int ELEMENT_SIZE = 4;
// 辅助函数:根据数组的维度信息和当前索引的维度,计算该索引的步长(字节数)
// dims: 包含所有维度大小的vector例如 {2, 3, 4}
// currentDimIndex: 当前正在处理的索引在 dims 中的位置 (0, 1, 2...)
int calculateStride(const std::vector<int>& dims, size_t currentDimIndex) {
int stride = ELEMENT_SIZE; // 最内层元素大小 (4字节)
// 乘以当前维度之后的所有维度的大小
for (size_t i = currentDimIndex + 1; i < dims.size(); ++i) {
stride *= dims[i];
}
return stride;
}
public:
AddressCalculationExpansion(Module* module, IRBuilder* builder)
: pModule(module), pBuilder(builder) {}
// 运行此Pass
bool run();
};
} // namespace sysy

View File

@ -1,52 +0,0 @@
#pragma once
#include "Pass.h" // 包含 Pass 框架
#include "IR.h" // 包含 IR 定义
#include <map>
#include <set>
#include <vector>
#include <algorithm>
namespace sysy {
// 支配树分析结果类 (保持不变)
class DominatorTree : public AnalysisResultBase {
public:
DominatorTree(Function* F);
const std::set<BasicBlock*>* getDominators(BasicBlock* BB) const;
BasicBlock* getImmediateDominator(BasicBlock* BB) const;
const std::set<BasicBlock*>* getDominanceFrontier(BasicBlock* BB) const;
const std::map<BasicBlock*, std::set<BasicBlock*>>& getDominatorsMap() const { return Dominators; }
const std::map<BasicBlock*, BasicBlock*>& getIDomsMap() const { return IDoms; }
const std::map<BasicBlock*, std::set<BasicBlock*>>& getDominanceFrontiersMap() const { return DominanceFrontiers; }
void computeDominators(Function* F);
void computeIDoms(Function* F);
void computeDominanceFrontiers(Function* F);
private:
Function* AssociatedFunction;
std::map<BasicBlock*, std::set<BasicBlock*>> Dominators;
std::map<BasicBlock*, BasicBlock*> IDoms;
std::map<BasicBlock*, std::set<BasicBlock*>> DominanceFrontiers;
};
// 支配树分析遍
class DominatorTreeAnalysisPass : public AnalysisPass {
public:
// 唯一的 Pass ID
static void *ID;
DominatorTreeAnalysisPass() : AnalysisPass("DominatorTreeAnalysis", Pass::Granularity::Function) {}
// 实现 getPassID
void* getPassID() const override { return &ID; }
bool runOnFunction(Function* F, AnalysisManager &AM) override;
std::unique_ptr<AnalysisResultBase> getResult() override;
private:
std::unique_ptr<DominatorTree> CurrentDominatorTree;
};
} // namespace sysy

View File

@ -1,75 +0,0 @@
#ifndef RISCV64_PASSES_H
#define RISCV64_PASSES_H
#include "RISCv64LLIR.h"
namespace sysy {
/**
* @class BackendPass
* @brief 所有优化Pass的抽象基类 (可选,但推荐)
* * 定义一个通用的接口,所有优化都应该实现它。
*/
class BackendPass {
public:
virtual ~BackendPass() = default;
virtual void runOnMachineFunction(MachineFunction* mfunc) = 0;
};
// --- 寄存器分配前优化 ---
/**
* @class PreRA_Scheduler
* @brief 寄存器分配前的指令调度器
* * 在虚拟寄存器上进行操作,此时调度自由度最大,
* 主要目标是隐藏指令延迟,提高流水线效率。
*/
class PreRA_Scheduler : public BackendPass {
public:
void runOnMachineFunction(MachineFunction* mfunc) override;
};
/**
* @class CalleeSavedHandler
* @brief 处理被调用者保存寄存器(Callee-Saved Registers)的Pass。
* * 这个Pass在寄存器分配之后运行。它的主要职责是
* 1. 扫描整个函数,找出所有被使用的 `s` 系列寄存器。
* 2. 在函数序言中插入 `sd` 指令来保存这些寄存器。
* 3. 在函数结尾ret指令前插入 `ld` 指令来恢复这些寄存器。
* 4. 正确计算因保存这些寄存器而需要的额外栈空间并更新StackFrameInfo。
*/
class CalleeSavedHandler : public BackendPass {
public:
void runOnMachineFunction(MachineFunction* mfunc) override;
};
// --- 寄存器分配后优化 ---
/**
* @class PeepholeOptimizer
* @brief 窥孔优化器
* * 在已分配物理寄存器的指令流上,通过一个小的滑动窗口来查找
* 并替换掉一些冗余或低效的指令模式。
*/
class PeepholeOptimizer : public BackendPass {
public:
void runOnMachineFunction(MachineFunction* mfunc) override;
};
/**
* @class PostRA_Scheduler
* @brief 寄存器分配后的局部指令调度器
* * 主要目标是优化寄存器分配器插入的spill/fill代码(lw/sw)
* 尝试将加载指令提前,以隐藏其访存延迟。
*/
class PostRA_Scheduler : public BackendPass {
public:
void runOnMachineFunction(MachineFunction* mfunc) override;
};
} // namespace sysy
#endif // RISCV64_PASSES_H

View File

@ -1,69 +0,0 @@
#ifndef RISCV64_REGALLOC_H
#define RISCV64_REGALLOC_H
#include "RISCv64LLIR.h"
#include "RISCv64ISel.h" // 包含 RISCv64ISel.h 以访问 ISel 和 Value 类型
namespace sysy {
class RISCv64RegAlloc {
public:
RISCv64RegAlloc(MachineFunction* mfunc);
// 模块主入口
void run();
private:
using LiveSet = std::set<unsigned>; // 活跃虚拟寄存器集合
using InterferenceGraph = std::map<unsigned, std::set<unsigned>>;
// 栈帧管理
void eliminateFrameIndices();
// 活跃性分析
void analyzeLiveness();
// 构建干扰图
void buildInterferenceGraph();
// 图着色分配寄存器
void colorGraph();
// 重写函数替换vreg并插入溢出代码
void rewriteFunction();
// 辅助函数获取指令的Use/Def集合
void getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet& def);
// 辅助函数,处理调用约定
void handleCallingConvention();
MachineFunction* MFunc;
// 活跃性分析结果
std::map<const MachineInstr*, LiveSet> live_in_map;
std::map<const MachineInstr*, LiveSet> live_out_map;
// 干扰图
InterferenceGraph interference_graph;
// 图着色结果
std::map<unsigned, PhysicalReg> color_map; // vreg -> preg
std::set<unsigned> spilled_vregs; // 被溢出的vreg集合
// 可用的物理寄存器池
std::vector<PhysicalReg> allocable_int_regs;
// 存储vreg到IR Value*的反向映射
// 这个map将在run()函数开始时被填充并在rewriteFunction()中使用。
std::map<unsigned, Value*> vreg_to_value_map;
std::map<PhysicalReg, unsigned> preg_to_vreg_id_map; // 物理寄存器到特殊vreg ID的映射
// 用于计算类型大小的辅助函数
unsigned getTypeSizeInBytes(Type* type);
};
} // namespace sysy
#endif // RISCV64_REGALLOC_H

View File

@ -1,196 +0,0 @@
#pragma once
#include "IR.h"
namespace sysy {
// 稀疏条件常量传播类
// Sparse Conditional Constant Propagation
/*
伪代码
function SCCP_Optimization(Module):
for each Function in Module:
changed = true
while changed:
changed = false
// 阶段1: 常量传播与折叠
changed |= PropagateConstants(Function)
// 阶段2: 控制流简化
changed |= SimplifyControlFlow(Function)
end while
end for
function PropagateConstants(Function):
// 初始化
executableBlocks = {entryBlock}
valueState = map<Value, State> // 值->状态映射
instWorkList = Queue()
edgeWorkList = Queue()
// 初始化工作列表
for each inst in entryBlock:
instWorkList.push(inst)
// 迭代处理
while !instWorkList.empty() || !edgeWorkList.empty():
// 处理指令工作列表
while !instWorkList.empty():
inst = instWorkList.pop()
// 如果指令是可执行基本块中的
if executableBlocks.contains(inst.parent):
ProcessInstruction(inst)
// 处理边工作列表
while !edgeWorkList.empty():
edge = edgeWorkList.pop()
ProcessEdge(edge)
// 应用常量替换
for each inst in Function:
if valueState[inst] == CONSTANT:
ReplaceWithConstant(inst, valueState[inst].constant)
changed = true
return changed
function ProcessInstruction(Instruction inst):
switch inst.type:
//二元操作
case BINARY_OP:
lhs = GetValueState(inst.operands[0])
rhs = GetValueState(inst.operands[1])
if lhs == CONSTANT && rhs == CONSTANT:
newState = ComputeConstant(inst.op, lhs.value, rhs.value)
UpdateState(inst, newState)
else if lhs == BOTTOM || rhs == BOTTOM:
UpdateState(inst, BOTTOM)
//phi
case PHI:
mergedState =
for each incoming in inst.incomings:
// 检查每个输入的状态
if executableBlocks.contains(incoming.block):
incomingState = GetValueState(incoming.value)
mergedState = Meet(mergedState, incomingState)
UpdateState(inst, mergedState)
// 条件分支
case COND_BRANCH:
cond = GetValueState(inst.condition)
if cond == CONSTANT:
// 判断条件分支
if cond.value == true:
AddEdgeToWorkList(inst.parent, inst.trueTarget)
else:
AddEdgeToWorkList(inst.parent, inst.falseTarget)
else if cond == BOTTOM:
AddEdgeToWorkList(inst.parent, inst.trueTarget)
AddEdgeToWorkList(inst.parent, inst.falseTarget)
case UNCOND_BRANCH:
AddEdgeToWorkList(inst.parent, inst.target)
// 其他指令处理...
function ProcessEdge(Edge edge):
fromBB, toBB = edge
if !executableBlocks.contains(toBB):
executableBlocks.add(toBB)
for each inst in toBB:
if inst is PHI:
instWorkList.push(inst)
else:
instWorkList.push(inst) // 非PHI指令
// 更新PHI节点的输入
for each phi in toBB.phis:
instWorkList.push(phi)
function SimplifyControlFlow(Function):
changed = false
// 标记可达基本块
ReachableBBs = FindReachableBlocks(Function.entry)
// 删除不可达块
for each bb in Function.blocks:
if !ReachableBBs.contains(bb):
RemoveDeadBlock(bb)
changed = true
// 简化条件分支
for each bb in Function.blocks:
terminator = bb.terminator
if terminator is COND_BRANCH:
cond = GetValueState(terminator.condition)
if cond == CONSTANT:
SimplifyBranch(terminator, cond.value)
changed = true
return changed
function RemoveDeadBlock(BasicBlock bb):
// 1. 更新前驱块的分支指令
for each pred in bb.predecessors:
UpdateTerminator(pred, bb)
// 2. 更新后继块的PHI节点
for each succ in bb.successors:
RemovePhiIncoming(succ, bb)
// 3. 删除块内所有指令
for each inst in bb.instructions:
inst.remove()
// 4. 从函数中移除基本块
Function.removeBlock(bb)
function Meet(State a, State b):
if a == : return b
if b == : return a
if a == ⊥ || b == ⊥: return ⊥
if a.value == b.value: return a
return ⊥
function UpdateState(Value v, State newState):
oldState = valueState.get(v, )
if newState != oldState:
valueState[v] = newState
for each user in v.users:
if user is Instruction:
instWorkList.push(user)
*/
enum class LatticeValue {
Top, // (Unknown)
Constant, // c (Constant)
Bottom // ⊥ (Undefined / Varying)
};
// LatticeValue: 用于表示值的状态Top表示未知Constant表示常量Bottom表示未定义或变化的值。
// 这里的LatticeValue用于跟踪每个SSA值变量、指令结果的状态
// 以便在SCCP过程中进行常量传播和控制流简化。
//TODO: 下列数据结构考虑集成到类中,避免重命名问题
static std::set<Instruction *> Worklist;
static std::unordered_set<BasicBlock*> Executable_Blocks;
static std::queue<std::pair<BasicBlock *, BasicBlock *> > Executable_Edges;
static std::map<Value*, LatticeValue> valueState;
class SCCP {
private:
Module *pModule;
public:
SCCP(Module *pMoudle) : pModule(pMoudle) {}
void run();
bool PropagateConstants(Function *function);
bool SimplifyControlFlow(Function *function);
void ProcessInstruction(Instruction *inst);
void ProcessEdge(const std::pair<BasicBlock *, BasicBlock *> &edge);
void RemoveDeadBlock(BasicBlock *bb);
void UpdateState(Value *v, LatticeValue newState);
LatticeValue Meet(LatticeValue a, LatticeValue b);
LatticeValue GetValueState(Value *v);
};
} // namespace sysy

View File

@ -1,465 +0,0 @@
#pragma once
#include "IR.h"
namespace sysy {
// 前向声明
class Loop;
// 基本块分析信息类
class BlockAnalysisInfo {
public:
using block_list = std::vector<BasicBlock*>;
using block_set = std::unordered_set<BasicBlock*>;
protected:
// 支配树相关
int domdepth = 0; ///< 支配节点所在深度
BasicBlock* idom = nullptr; ///< 直接支配结点
block_list sdoms; ///< 支配树后继
block_set dominants; ///< 必经结点集合
block_set dominant_frontiers; ///< 支配边界
// 后续添加循环分析相关
// Loop* loopbelong = nullptr; ///< 所属循环
// int loopdepth = 0; ///< 循环深度
public:
// getterface
const int getDomDepth() const { return domdepth; }
const BasicBlock* getIdom() const { return idom; }
const block_list& getSdoms() const { return sdoms; }
const block_set& getDominants() const { return dominants; }
const block_set& getDomFrontiers() const { return dominant_frontiers; }
// 支配树操作
void setDomDepth(int depth) { domdepth = depth; }
void setIdom(BasicBlock* block) { idom = block; }
void addSdoms(BasicBlock* block) { sdoms.push_back(block); }
void clearSdoms() { sdoms.clear(); }
void removeSdoms(BasicBlock* block) {
sdoms.erase(std::remove(sdoms.begin(), sdoms.end(), block), sdoms.end());
}
void addDominants(BasicBlock* block) { dominants.emplace(block); }
void addDominants(const block_set& blocks) { dominants.insert(blocks.begin(), blocks.end()); }
void setDominants(BasicBlock* block) {
dominants.clear();
addDominants(block);
}
void setDominants(const block_set& doms) {
dominants = doms;
}
void setDomFrontiers(const block_set& df) {
dominant_frontiers = df;
}
// TODO循环分析操作方法
// 清空所有分析信息
void clear() {
domdepth = -1;
idom = nullptr;
sdoms.clear();
dominants.clear();
dominant_frontiers.clear();
// loopbelong = nullptr;
// loopdepth = 0;
}
};
// 函数分析信息类
class FunctionAnalysisInfo {
public:
// 函数属性
enum FunctionAttribute : uint64_t {
PlaceHolder = 0x0UL,
Pure = 0x1UL << 0,
SelfRecursive = 0x1UL << 1,
SideEffect = 0x1UL << 2,
NoPureCauseMemRead = 0x1UL << 3
};
// 数据结构
using Loop_list = std::list<std::unique_ptr<Loop>>;
using block_loop_map = std::unordered_map<BasicBlock*, Loop*>;
using value_block_map = std::unordered_map<Value*, BasicBlock*>;
using value_block_count_map = std::unordered_map<Value*, std::unordered_map<BasicBlock*, int>>;
// 分析数据
FunctionAttribute attribute = PlaceHolder; ///< 函数属性
std::set<Function*> callees; ///< 函数调用集合
Loop_list loops; ///< 所有循环
Loop_list topLoops; ///< 顶层循环
// block_loop_map basicblock2Loop; ///< 基本块到循环映射
std::list<std::unique_ptr<AllocaInst>> indirectAllocas; ///< 间接分配内存
// 值定义/使用信息
value_block_map value2AllocBlocks; ///< 值分配位置映射
value_block_count_map value2DefBlocks; ///< 值定义位置映射
value_block_count_map value2UseBlocks; ///< 值使用位置映射
// 函数属性操作
FunctionAttribute getAttribute() const { return attribute; }
void setAttribute(FunctionAttribute attr) { attribute = static_cast<FunctionAttribute>(attribute | attr); }
void clearAttribute() { attribute = PlaceHolder; }
// 调用关系操作
void addCallee(Function* callee) { callees.insert(callee); }
void removeCallee(Function* callee) { callees.erase(callee); }
void clearCallees() { callees.clear(); }
// 值-块映射操作
BasicBlock* getAllocBlockByValue(Value* value) {
auto it = value2AllocBlocks.find(value);
return it != value2AllocBlocks.end() ? it->second : nullptr;
}
std::unordered_set<BasicBlock *> getDefBlocksByValue(Value *value) {
std::unordered_set<BasicBlock *> blocks;
if (value2DefBlocks.count(value) > 0) {
for (const auto &pair : value2DefBlocks[value]) {
blocks.insert(pair.first);
}
}
return blocks;
}
std::unordered_set<BasicBlock *> getUseBlocksByValue(Value *value) {
std::unordered_set<BasicBlock *> blocks;
if (value2UseBlocks.count(value) > 0) {
for (const auto &pair : value2UseBlocks[value]) {
blocks.insert(pair.first);
}
}
return blocks;
}
// 值定义/使用操作
void addValue2AllocBlocks(Value* value, BasicBlock* block) { value2AllocBlocks[value] = block; }
void addValue2DefBlocks(Value* value, BasicBlock* block) { ++value2DefBlocks[value][block]; }
void addValue2UseBlocks(Value* value, BasicBlock* block) { ++value2UseBlocks[value][block]; }
// 获取值定义/使用信息
std::unordered_map<Value *, BasicBlock *>& getValue2AllocBlocks() {
return value2AllocBlocks;
}
std::unordered_map<Value *, std::unordered_map<BasicBlock *, int>>& getValue2DefBlocks() {
return value2DefBlocks;
}
std::unordered_map<Value *, std::unordered_map<BasicBlock *, int>>& getValue2UseBlocks() {
return value2UseBlocks;
}
std::unordered_set<Value *> getValuesOfDefBlock() {
std::unordered_set<Value *> values;
for (const auto &pair : value2DefBlocks) {
values.insert(pair.first);
}
return values;
}
// 删除信息操作
void removeValue2AllocBlock(Value *value) { value2AllocBlocks.erase(value); }
bool removeValue2DefBlock(Value *value, BasicBlock *block) {
bool changed = false;
if (--value2DefBlocks[value][block] == 0) {
value2DefBlocks[value].erase(block);
if (value2DefBlocks[value].empty()) {
value2DefBlocks.erase(value);
changed = true;
}
}
return changed;
}
bool removeValue2UseBlock(Value *value, BasicBlock *block) {
bool changed = false;
if (--value2UseBlocks[value][block] == 0) {
value2UseBlocks[value].erase(block);
if (value2UseBlocks[value].empty()) {
value2UseBlocks.erase(value);
changed = true;
}
}
return changed;
}
// 间接分配操作
void addIndirectAlloca(AllocaInst* alloca) { indirectAllocas.emplace_back(alloca); }
std::list<std::unique_ptr<AllocaInst>>& getIndirectAllocas() { return indirectAllocas; }
// TODO循环分析操作
// 清空所有分析信息
void clear() {
attribute = PlaceHolder;
callees.clear();
loops.clear();
topLoops.clear();
// basicblock2Loop.clear();
indirectAllocas.clear();
value2AllocBlocks.clear();
value2DefBlocks.clear();
value2UseBlocks.clear();
}
};
// 循环类 - 未实现优化
class Loop {
public:
using block_list = std::vector<BasicBlock *>;
using block_set = std::unordered_set<BasicBlock *>;
using Loop_list = std::vector<Loop *>;
protected:
Function *parent; // 所属函数
block_list blocksInLoop; // 循环内的基本块
BasicBlock *preheaderBlock = nullptr; // 前驱块
BasicBlock *headerBlock = nullptr; // 循环头
block_list latchBlock; // 回边块
block_set exitingBlocks; // 退出块
block_set exitBlocks; // 退出目标块
Loop *parentloop = nullptr; // 父循环
Loop_list subLoops; // 子循环
size_t loopID; // 循环ID
unsigned loopDepth; // 循环深度
Instruction *indCondVar = nullptr; // 循环条件变量
Instruction::Kind IcmpKind; // 比较类型
Value *indEnd = nullptr; // 循环结束值
AllocaInst *IndPhi = nullptr; // 循环变量
ConstantValue *indBegin = nullptr; // 循环起始值
ConstantValue *indStep = nullptr; // 循环步长
std::set<GlobalValue *> GlobalValuechange; // 循环内改变的全局变量
int StepType = 0; // 循环步长类型
bool parallelable = false; // 是否可并行
public:
explicit Loop(BasicBlock *header, const std::string &name = "")
: headerBlock(header) {
blocksInLoop.push_back(header);
}
void setloopID() {
static unsigned loopCount = 0;
loopCount = loopCount + 1;
loopID = loopCount;
}
ConstantValue* getindBegin() { return indBegin; }
ConstantValue* getindStep() { return indStep; }
void setindBegin(ConstantValue *indBegin2set) { indBegin = indBegin2set; }
void setindStep(ConstantValue *indStep2set) { indStep = indStep2set; }
void setStepType(int StepType2Set) { StepType = StepType2Set; }
int getStepType() { return StepType; }
size_t getLoopID() { return loopID; }
BasicBlock* getHeader() const { return headerBlock; }
BasicBlock* getPreheaderBlock() const { return preheaderBlock; }
block_list& getLatchBlocks() { return latchBlock; }
block_set& getExitingBlocks() { return exitingBlocks; }
block_set& getExitBlocks() { return exitBlocks; }
Loop* getParentLoop() const { return parentloop; }
void setParentLoop(Loop *parent) { parentloop = parent; }
void addBasicBlock(BasicBlock *bb) { blocksInLoop.push_back(bb); }
void addSubLoop(Loop *loop) { subLoops.push_back(loop); }
void setLoopDepth(unsigned depth) { loopDepth = depth; }
block_list& getBasicBlocks() { return blocksInLoop; }
Loop_list& getSubLoops() { return subLoops; }
unsigned getLoopDepth() const { return loopDepth; }
bool isLoopContainsBasicBlock(BasicBlock *bb) const {
return std::find(blocksInLoop.begin(), blocksInLoop.end(), bb) != blocksInLoop.end();
}
void addExitingBlock(BasicBlock *bb) { exitingBlocks.insert(bb); }
void addExitBlock(BasicBlock *bb) { exitBlocks.insert(bb); }
void addLatchBlock(BasicBlock *bb) { latchBlock.push_back(bb); }
void setPreheaderBlock(BasicBlock *bb) { preheaderBlock = bb; }
void setIndexCondInstr(Instruction *instr) { indCondVar = instr; }
void setIcmpKind(Instruction::Kind kind) { IcmpKind = kind; }
Instruction::Kind getIcmpKind() const { return IcmpKind; }
bool isSimpleLoopInvariant(Value *value) ;
void setIndEnd(Value *value) { indEnd = value; }
void setIndPhi(AllocaInst *phi) { IndPhi = phi; }
Value* getIndEnd() const { return indEnd; }
AllocaInst* getIndPhi() const { return IndPhi; }
Instruction* getIndCondVar() const { return indCondVar; }
void addGlobalValuechange(GlobalValue *globalvaluechange2add) {
GlobalValuechange.insert(globalvaluechange2add);
}
std::set<GlobalValue *>& getGlobalValuechange() {
return GlobalValuechange;
}
void setParallelable(bool flag) { parallelable = flag; }
bool isParallelable() const { return parallelable; }
};
// 控制流分析类
class ControlFlowAnalysis {
private:
Module *pModule; ///< 模块
std::unordered_map<BasicBlock*, BlockAnalysisInfo*> blockAnalysisInfo; // 基本块分析信息表
std::unordered_map<Function*, FunctionAnalysisInfo*> functionAnalysisInfo; // 函数分析信息
public:
explicit ControlFlowAnalysis(Module *pMoudle) : pModule(pMoudle) {}
// 获取基本块分析信息
BlockAnalysisInfo* getBlockAnalysisInfo(BasicBlock *block) {
auto it = blockAnalysisInfo.find(block);
if (it != blockAnalysisInfo.end()) {
return it->second;
}
return nullptr; // 如果未找到返回nullptr
}
FunctionAnalysisInfo* getFunctionAnalysisInfo(Function *func) {
auto it = functionAnalysisInfo.find(func);
if (it != functionAnalysisInfo.end()) {
return it->second;
}
return nullptr; // 如果未找到返回nullptr
}
void init(); // 初始化分析器
void computeDomNode(); // 计算必经结点
void computeDomTree(); // 构造支配树
// std::unordered_set<BasicBlock *> computeDomFrontier(BasicBlock *block) ; // 计算单个块的支配边界(弃用)
void computeDomFrontierAllBlk(); // 计算所有块的支配边界
void runControlFlowAnalysis(); // 运行控制流分析(主要是支配树和支配边界)
void clear(){
for (auto &pair : blockAnalysisInfo) {
delete pair.second; // 清理基本块分析信息
}
blockAnalysisInfo.clear();
for (auto &pair : functionAnalysisInfo) {
delete pair.second; // 清理函数分析信息
}
functionAnalysisInfo.clear();
} // 清空分析结果
~ControlFlowAnalysis() {
clear(); // 析构时清理所有分析信息
}
private:
void intersectOP4Dom(std::unordered_set<BasicBlock *> &dom, const std::unordered_set<BasicBlock *> &other); // 交集运算,
BasicBlock* findCommonDominator(BasicBlock *a, BasicBlock *b); // 查找两个基本块的共同支配结点
};
// 数据流分析类
// 该类为抽象类,具体的数据流分析器需要继承此类
// 因为每个数据流分析器的分析动作都不一样所以需要继承并实现analyze方法
class DataFlowAnalysis {
public:
virtual ~DataFlowAnalysis() = default;
public:
virtual void init(Module *pModule) {} ///< 分析器初始化
virtual auto analyze(Module *pModule, BasicBlock *block) -> bool { return true; } ///< 分析动作若完成则返回true;
virtual void clear() {} ///< 清空
};
// 数据流分析工具类
// 该类用于管理多个数据流分析器,提供统一的前向与后向分析接口
class DataFlowAnalysisUtils {
private:
std::vector<DataFlowAnalysis *> forwardAnalysisList; ///< 前向分析器列表
std::vector<DataFlowAnalysis *> backwardAnalysisList; ///< 后向分析器列表
public:
DataFlowAnalysisUtils() = default;
~DataFlowAnalysisUtils() {
clear(); // 析构时清理所有分析器
}
// 统一添加接口
void addAnalyzers(
std::vector<DataFlowAnalysis *> forwardList,
std::vector<DataFlowAnalysis *> backwardList = {})
{
forwardAnalysisList.insert(
forwardAnalysisList.end(),
forwardList.begin(),
forwardList.end());
backwardAnalysisList.insert(
backwardAnalysisList.end(),
backwardList.begin(),
backwardList.end());
}
// 单独添加接口
void addForwardAnalyzer(DataFlowAnalysis *analyzer) {
forwardAnalysisList.push_back(analyzer);
}
void addBackwardAnalyzer(DataFlowAnalysis *analyzer) {
backwardAnalysisList.push_back(analyzer);
}
// 设置分析器列表
void setAnalyzers(
std::vector<DataFlowAnalysis *> forwardList,
std::vector<DataFlowAnalysis *> backwardList)
{
forwardAnalysisList = std::move(forwardList);
backwardAnalysisList = std::move(backwardList);
}
// 清空列表
void clear() {
forwardAnalysisList.clear();
backwardAnalysisList.clear();
}
// 访问器
const auto& getForwardAnalyzers() const { return forwardAnalysisList; }
const auto& getBackwardAnalyzers() const { return backwardAnalysisList; }
public:
void forwardAnalyze(Module *pModule); ///< 执行前向分析
void backwardAnalyze(Module *pModule); ///< 执行后向分析
};
// 活跃变量分析类
// 提供def - use分析
// 未兼容数组变量但是考虑了维度的use信息
class ActiveVarAnalysis : public DataFlowAnalysis {
private:
std::map<BasicBlock *, std::vector<std::set<User *>>> activeTable; ///< 活跃信息表,存储每个基本块内的的活跃变量信息
public:
ActiveVarAnalysis() = default;
~ActiveVarAnalysis() override = default;
public:
static std::set<User*> getUsedSet(Instruction *inst);
static User* getDefine(Instruction *inst);
public:
void init(Module *pModule) override;
bool analyze(Module *pModule, BasicBlock *block) override;
// 外部活跃信息表访问器
const std::map<BasicBlock *, std::vector<std::set<User *>>> &getActiveTable() const;
void clear() override {
activeTable.clear(); // 清空活跃信息表
}
};
// 分析管理器 后续实现
// class AnalysisManager {
// };
} // namespace sysy

View File

@ -1,33 +0,0 @@
#pragma once
#include "IR.h"
namespace sysy {
// 优化工具类,包含一些通用的优化方法
// 这些方法可以在不同的优化 pass 中复用
// 例如删除use关系,判断是否是全局变量等
class SysYIROptUtils{
public:
// 仅仅删除use关系
static void usedelete(Instruction *instr) {
for (auto &use : instr->getOperands()) {
Value* val = use->getValue();
val->removeUse(use);
}
}
// 判断是否是全局变量
static bool isGlobal(Value *val) {
auto gval = dynamic_cast<GlobalValue *>(val);
return gval != nullptr;
}
// 判断是否是数组
static bool isArr(Value *val) {
auto aval = dynamic_cast<AllocaInst *>(val);
return aval != nullptr && aval->getNumDims() != 0;
}
};
}// namespace sysy

View File

@ -1,58 +0,0 @@
// PassManager.h
#pragma once
#include <vector>
#include <memory>
#include <typeindex> // For std::type_index
#include <unordered_map>
#include "SysYIRPass.h"
#include "IR.h" // 假设你的IR.h定义了Module, Function等
namespace sysy {
class PassManager {
public:
PassManager() = default;
// 添加一个FunctionPass
void addPass(std::unique_ptr<FunctionPass> pass) {
functionPasses.push_back(std::move(pass));
}
// 添加一个ModulePass
void addPass(std::unique_ptr<ModulePass> pass) {
modulePasses.push_back(std::move(pass));
}
// 添加一个AnalysisPass
template<typename T, typename... Args>
T* addAnalysisPass(Args&&... args) {
static_assert(std::is_base_of<AnalysisPass, T>::value, "T must derive from AnalysisPass");
auto analysis = std::make_unique<T>(std::forward<Args>(args)...);
T* rawPtr = analysis.get();
analysisPasses[std::type_index(typeid(T))] = std::move(analysis);
return rawPtr;
}
// 获取分析结果用于其他Pass访问
template<typename T>
T* getAnalysis() {
static_assert(std::is_base_of<AnalysisPass, T>::value, "T must derive from AnalysisPass");
auto it = analysisPasses.find(std::type_index(typeid(T)));
if (it != analysisPasses.end()) {
return static_cast<T*>(it->second.get());
}
return nullptr; // 或者抛出异常
}
// 运行所有注册的遍
void run(Module& M);
private:
std::vector<std::unique_ptr<FunctionPass>> functionPasses;
std::vector<std::unique_ptr<ModulePass>> modulePasses;
std::unordered_map<std::type_index, std::unique_ptr<AnalysisPass>> analysisPasses;
// 未来可以添加AnalysisPass的缓存机制
};
} // namespace sysy

View File

@ -0,0 +1,33 @@
#ifndef CALLEE_SAVED_HANDLER_H
#define CALLEE_SAVED_HANDLER_H
#include "RISCv64LLIR.h"
#include "Pass.h"
namespace sysy {
/**
* @class CalleeSavedHandler
* @brief 处理被调用者保存寄存器(Callee-Saved Registers)的Pass。
* * 这个Pass在寄存器分配之后运行。它的主要职责是
* 1. 扫描整个函数,找出所有被使用的 `s` 系列寄存器。
* 2. 在函数序言中插入 `sd` 指令来保存这些寄存器。
* 3. 在函数结尾ret指令前插入 `ld` 指令来恢复这些寄存器。
* 4. 正确计算因保存这些寄存器而需要的额外栈空间并更新StackFrameInfo。
*/
class CalleeSavedHandler : public Pass {
public:
static char ID;
CalleeSavedHandler() : Pass("callee-saved-handler", Granularity::Function, PassKind::Optimization) {}
void *getPassID() const override { return &ID; }
bool runOnFunction(Function *F, AnalysisManager& AM) override;
void runOnMachineFunction(MachineFunction* mfunc);
};
} // namespace sysy
#endif // CALLEE_SAVED_HANDLER_H

View File

@ -0,0 +1,20 @@
#ifndef ELIMINATE_FRAME_INDICES_H
#define ELIMINATE_FRAME_INDICES_H
#include "RISCv64LLIR.h"
namespace sysy {
class EliminateFrameIndicesPass {
public:
// Pass 的主入口函数
void runOnMachineFunction(MachineFunction* mfunc);
private:
// 帮助计算类型大小的辅助函数从原RegAlloc中移出
unsigned getTypeSizeInBytes(Type* type);
};
} // namespace sysy
#endif // ELIMINATE_FRAME_INDICES_H

View File

@ -0,0 +1,36 @@
#ifndef SYSY_LEGALIZE_IMMEDIATES_H
#define SYSY_LEGALIZE_IMMEDIATES_H
#include "RISCv64LLIR.h"
#include "Pass.h"
namespace sysy {
// MachineFunction 的前向声明在这里是可选的,因为 RISCv64LLIR.h 已经定义了它
// class MachineFunction;
/**
* @class LegalizeImmediatesPass
* @brief 一个用于“合法化”机器指令的Pass。
*
* 这个Pass的主要职责是遍历所有机器指令查找那些包含了超出
* 目标架构RISC-V编码范围的大立即数immediate的指令
* 并将它们展开成一个等价的、只包含合法立即数的指令序列。
*
* 它在指令选择之后、寄存器分配之前运行,确保进入后续阶段的
* 所有指令都符合硬件约束。
*/
class LegalizeImmediatesPass : public Pass {
public:
static char ID;
LegalizeImmediatesPass() : Pass("legalize-immediates", Granularity::Function, PassKind::Optimization) {}
void *getPassID() const override { return &ID; }
void runOnMachineFunction(MachineFunction* mfunc);
};
} // namespace sysy
#endif // SYSY_LEGALIZE_IMMEDIATES_H

View File

@ -0,0 +1,35 @@
#ifndef SYSY_PROLOGUE_EPILOGUE_INSERTION_H
#define SYSY_PROLOGUE_EPILOGUE_INSERTION_H
#include "RISCv64LLIR.h"
#include "Pass.h"
namespace sysy {
class MachineFunction;
/**
* @class PrologueEpilogueInsertionPass
* @brief 在函数中插入序言和尾声的机器指令。
*
* 这个Pass在所有栈帧大小计算完毕后包括局部变量、溢出槽、被调用者保存寄存器
* 在寄存器分配之后运行。它的职责是:
* 1. 根据 StackFrameInfo 中的最终栈大小,生成用于分配和释放栈帧的指令 (addi sp, sp, +/-size)。
* 2. 生成用于保存和恢复返回地址(ra)和旧帧指针(s0)的指令。
* 3. 将这些指令作为 MachineInstr 对象插入到 MachineFunction 的入口块和所有返回块中。
* 4. 这个Pass可能会生成带有大立即数的指令需要后续的 LegalizeImmediatesPass 来处理。
*/
class PrologueEpilogueInsertionPass : public Pass {
public:
static char ID;
PrologueEpilogueInsertionPass() : Pass("prologue-epilogue-insertion", Granularity::Function, PassKind::Optimization) {}
void *getPassID() const override { return &ID; }
void runOnMachineFunction(MachineFunction* mfunc);
};
} // namespace sysy
#endif // SYSY_PROLOGUE_EPILOGUE_INSERTION_H

View File

@ -0,0 +1,30 @@
#ifndef RISCV64_DIV_STRENGTH_REDUCTION_H
#define RISCV64_DIV_STRENGTH_REDUCTION_H
#include "RISCv64LLIR.h"
#include "Pass.h"
namespace sysy {
/**
* @class DivStrengthReduction
* @brief 除法强度削弱优化器
* * 将除法运算转换为乘法运算使用magic number算法
* 适用于除数为常数的情况,可以显著提高性能
*/
class DivStrengthReduction : public Pass {
public:
static char ID;
DivStrengthReduction() : Pass("div-strength-reduction", Granularity::Function, PassKind::Optimization) {}
void *getPassID() const override { return &ID; }
bool runOnFunction(Function *F, AnalysisManager& AM) override;
void runOnMachineFunction(MachineFunction* mfunc);
};
} // namespace sysy
#endif // RISCV64_DIV_STRENGTH_REDUCTION_H

View File

@ -0,0 +1,30 @@
#ifndef RISCV64_PEEPHOLE_H
#define RISCV64_PEEPHOLE_H
#include "RISCv64LLIR.h"
#include "Pass.h"
namespace sysy {
/**
* @class PeepholeOptimizer
* @brief 窥孔优化器
* * 在已分配物理寄存器的指令流上,通过一个小的滑动窗口来查找
* 并替换掉一些冗余或低效的指令模式。
*/
class PeepholeOptimizer : public Pass {
public:
static char ID;
PeepholeOptimizer() : Pass("peephole-optimizer", Granularity::Function, PassKind::Optimization) {}
void *getPassID() const override { return &ID; }
bool runOnFunction(Function *F, AnalysisManager& AM) override;
void runOnMachineFunction(MachineFunction* mfunc);
};
} // namespace sysy
#endif // RISCV64_PEEPHOLE_H

View File

@ -0,0 +1,50 @@
#ifndef POST_RA_SCHEDULER_H
#define POST_RA_SCHEDULER_H
#include "RISCv64LLIR.h"
#include "Pass.h"
namespace sysy {
/**
* @class PostRA_Scheduler
* @brief 寄存器分配后的局部指令调度器
* * 主要目标是优化寄存器分配器插入的spill/fill代码(lw/sw)
* 尝试将加载指令提前,以隐藏其访存延迟。
*/
struct MemoryAccess {
PhysicalReg base_reg;
int64_t offset;
bool valid;
MemoryAccess() : valid(false) {}
MemoryAccess(PhysicalReg base, int64_t off) : base_reg(base), offset(off), valid(true) {}
};
struct InstrRegInfo {
std::unordered_set<PhysicalReg> defined_regs;
std::unordered_set<PhysicalReg> used_regs;
bool is_load;
bool is_store;
bool is_control_flow;
MemoryAccess mem_access;
InstrRegInfo() : is_load(false), is_store(false), is_control_flow(false) {}
};
class PostRA_Scheduler : public Pass {
public:
static char ID;
PostRA_Scheduler() : Pass("post-ra-scheduler", Granularity::Function, PassKind::Optimization) {}
void *getPassID() const override { return &ID; }
bool runOnFunction(Function *F, AnalysisManager& AM) override;
void runOnMachineFunction(MachineFunction* mfunc);
};
} // namespace sysy
#endif // POST_RA_SCHEDULER_H

View File

@ -0,0 +1,30 @@
#ifndef PRE_RA_SCHEDULER_H
#define PRE_RA_SCHEDULER_H
#include "RISCv64LLIR.h"
#include "Pass.h"
namespace sysy {
/**
* @class PreRA_Scheduler
* @brief 寄存器分配前的指令调度器
* * 在虚拟寄存器上进行操作,此时调度自由度最大,
* 主要目标是隐藏指令延迟,提高流水线效率。
*/
class PreRA_Scheduler : public Pass {
public:
static char ID;
PreRA_Scheduler() : Pass("pre-ra-scheduler", Granularity::Function, PassKind::Optimization) {}
void *getPassID() const override { return &ID; }
bool runOnFunction(Function *F, AnalysisManager& AM) override;
void runOnMachineFunction(MachineFunction* mfunc);
};
} // namespace sysy
#endif // PRE_RA_SCHEDULER_H

View File

@ -12,22 +12,25 @@ namespace sysy {
class RISCv64AsmPrinter {
public:
RISCv64AsmPrinter(MachineFunction* mfunc);
// 主入口
void run(std::ostream& os, bool debug = false);
void printInstruction(MachineInstr* instr, bool debug = false);
// 辅助函数
void setStream(std::ostream& os) { OS = &os; }
// 辅助函数
std::string regToString(PhysicalReg reg);
std::string formatInstr(const MachineInstr *instr);
private:
// 打印各个部分
void printPrologue();
void printEpilogue();
void printBasicBlock(MachineBasicBlock* mbb, bool debug = false);
void printInstruction(MachineInstr* instr, bool debug = false);
// 辅助函数
std::string regToString(PhysicalReg reg);
void printOperand(MachineOperand* op);
MachineFunction* MFunc;
std::ostream* OS;
std::ostream* OS = nullptr;
};
} // namespace sysy

View File

@ -22,6 +22,9 @@ private:
// 函数级代码生成 (实现新的流水线)
std::string function_gen(Function* func);
// 私有辅助函数,用于根据类型计算其占用的字节数。
unsigned getTypeSizeInBytes(Type* type);
Module* module;
};

View File

@ -3,6 +3,12 @@
#include "RISCv64LLIR.h"
// Forward declarations
namespace sysy {
class GlobalValue;
class Value;
}
extern int DEBUG;
extern int DEEPDEBUG;
@ -17,8 +23,12 @@ public:
// 公开接口以便后续模块如RegAlloc可以查询或创建vreg
unsigned getVReg(Value* val);
unsigned getNewVReg() { return vreg_counter++; }
unsigned getNewVReg(Type* type);
unsigned getVRegCounter() const;
// 获取 vreg_map 的公共接口
const std::map<Value*, unsigned>& getVRegMap() const { return vreg_map; }
const std::map<unsigned, Value*>& getVRegValueMap() const { return vreg_to_value_map; }
const std::map<unsigned, Type*>& getVRegTypeMap() const { return vreg_type_map; }
private:
// DAG节点定义作为ISel的内部实现细节
@ -38,6 +48,7 @@ private:
// 用于计算类型大小的辅助函数
unsigned getTypeSizeInBytes(Type* type);
// 打印DAG图以供调试
void print_dag(const std::vector<std::unique_ptr<DAGNode>>& dag, const std::string& bb_name);
// 状态
@ -47,6 +58,8 @@ private:
// 映射关系
std::map<Value*, unsigned> vreg_map;
std::map<unsigned, Value*> vreg_to_value_map;
std::map<unsigned, Type*> vreg_type_map;
std::map<const BasicBlock*, MachineBasicBlock*> bb_map;
unsigned vreg_counter;

View File

@ -3,6 +3,7 @@
#include "IR.h" // 确保包含了您自己的IR头文件
#include <string>
#include <iostream>
#include <vector>
#include <memory>
#include <cstdint>
@ -32,21 +33,20 @@ enum class PhysicalReg {
A0, A1, A2, A3, A4, A5, A6, A7,
// --- 浮点寄存器 ---
// (保持您原有的 F0-F31 命名)
F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11,
F12, F13, F14, F15, F16, F17, F18, F19, F20, F21,
F22, F23, F24, F25, F26, F27, F28, F29, F30, F31,
// 用于内部表示物理寄存器在干扰图中的节点ID一个简单的特殊ID确保不与vreg_counter冲突
// 假设 vreg_counter 不会达到这么大的值
PHYS_REG_START_ID = 10000,
PHYS_REG_END_ID = PHYS_REG_START_ID + 32, // 预留足够的空间
PHYS_REG_START_ID = 1000000,
PHYS_REG_END_ID = PHYS_REG_START_ID + 320, // 预留足够的空间
};
// RISC-V 指令操作码枚举
enum class RVOpcodes {
// 算术指令
ADD, ADDI, ADDW, ADDIW, SUB, SUBW, MUL, MULW, DIV, DIVW, REM, REMW,
ADD, ADDI, ADDW, ADDIW, SUB, SUBW, MUL, MULW, MULH, DIV, DIVW, REM, REMW,
// 逻辑指令
XOR, XORI, OR, ORI, AND, ANDI,
// 移位指令
@ -64,16 +64,98 @@ enum class RVOpcodes {
CALL,
// 特殊标记,非指令
LABEL,
// 新增伪指令,用于解耦栈帧处理
// 浮点指令 (RISC-V 'F' 扩展)
// 浮点加载与存储
FLW, // flw rd, offset(rs1)
FSW, // fsw rs2, offset(rs1)
FLD, // fld rd, offset(rs1)
FSD, // fsd rs2, offset(rs1)
// 浮点算术运算 (单精度)
FADD_S, // fadd.s rd, rs1, rs2
FSUB_S, // fsub.s rd, rs1, rs2
FMUL_S, // fmul.s rd, rs1, rs2
FDIV_S, // fdiv.s rd, rs1, rs2
// 浮点比较 (单精度)
FEQ_S, // feq.s rd, rs1, rs2 (结果写入整数寄存器rd)
FLT_S, // flt.s rd, rs1, rs2 (less than)
FLE_S, // fle.s rd, rs1, rs2 (less than or equal)
// 浮点转换
FCVT_S_W, // fcvt.s.w rd, rs1 (有符号整数 -> 单精度浮点)
FCVT_W_S, // fcvt.w.s rd, rs1 (单精度浮点 -> 有符号整数)
// 浮点传送/移动
FMV_S, // fmv.s rd, rs1 (浮点寄存器之间)
FMV_W_X, // fmv.w.x rd, rs1 (整数寄存器位模式 -> 浮点寄存器)
FMV_X_W, // fmv.x.w rd, rs1 (浮点寄存器位模式 -> 整数寄存器)
FNEG_S, // fneg.s rd, rs (浮点取负)
// 伪指令
FRAME_LOAD_W, // 从栈帧加载 32位 Word (对应 lw)
FRAME_LOAD_D, // 从栈帧加载 64位 Doubleword (对应 ld)
FRAME_STORE_W, // 保存 32位 Word 到栈帧 (对应 sw)
FRAME_STORE_D, // 保存 64位 Doubleword 到栈帧 (对应 sd)
FRAME_LOAD_F, // 从栈帧加载单精度浮点数
FRAME_STORE_F, // 将单精度浮点数存入栈帧
FRAME_ADDR, // 获取栈帧变量的地址
PSEUDO_KEEPALIVE, // 保持寄存器活跃,防止优化器删除
};
// 定义一个全局辅助函数或常量,提供调用者保存寄存器列表
const std::vector<PhysicalReg>& getCallerSavedIntRegs();
inline bool isGPR(PhysicalReg reg) {
return reg >= PhysicalReg::ZERO && reg <= PhysicalReg::T6;
}
// 判断一个物理寄存器是否是浮点寄存器 (FPR)
inline bool isFPR(PhysicalReg reg) {
return reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31;
}
// 获取所有调用者保存的整数寄存器 (t0-t6, a0-a7)
inline const std::vector<PhysicalReg>& getCallerSavedIntRegs() {
static const std::vector<PhysicalReg> regs = {
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3,
PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6,
PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3,
PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7
};
return regs;
}
// 获取所有被调用者保存的整数寄存器 (s0-s11)
inline const std::vector<PhysicalReg>& getCalleeSavedIntRegs() {
static const std::vector<PhysicalReg> regs = {
PhysicalReg::S0, PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3,
PhysicalReg::S4, PhysicalReg::S5, PhysicalReg::S6, PhysicalReg::S7,
PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11
};
return regs;
}
// 获取所有调用者保存的浮点寄存器 (ft0-ft11, fa0-fa7)
inline const std::vector<PhysicalReg>& getCallerSavedFpRegs() {
static const std::vector<PhysicalReg> regs = {
PhysicalReg::F0, PhysicalReg::F1, PhysicalReg::F2, PhysicalReg::F3,
PhysicalReg::F4, PhysicalReg::F5, PhysicalReg::F6, PhysicalReg::F7,
PhysicalReg::F8, PhysicalReg::F9, PhysicalReg::F10, PhysicalReg::F11, // ft0-ft11 和 fa0-fa7 在标准ABI中重叠
PhysicalReg::F12, PhysicalReg::F13, PhysicalReg::F14, PhysicalReg::F15,
PhysicalReg::F16, PhysicalReg::F17
};
return regs;
}
// 获取所有被调用者保存的浮点寄存器 (fs0-fs11)
inline const std::vector<PhysicalReg>& getCalleeSavedFpRegs() {
static const std::vector<PhysicalReg> regs = {
PhysicalReg::F18, PhysicalReg::F19, PhysicalReg::F20, PhysicalReg::F21,
PhysicalReg::F22, PhysicalReg::F23, PhysicalReg::F24, PhysicalReg::F25,
PhysicalReg::F26, PhysicalReg::F27, PhysicalReg::F28, PhysicalReg::F29,
PhysicalReg::F30, PhysicalReg::F31
};
return regs;
}
class MachineOperand;
class RegOperand;
@ -114,6 +196,11 @@ public:
preg = new_preg;
is_virtual = false;
}
void setVRegNum(unsigned new_vreg_num) {
vreg_num = new_vreg_num;
is_virtual = true; // 确保设置vreg时操作数状态正确
}
private:
unsigned vreg_num = 0;
PhysicalReg preg = PhysicalReg::ZERO;
@ -193,11 +280,15 @@ private:
// 栈帧信息
struct StackFrameInfo {
int locals_size = 0; // 仅为AllocaInst分配的大小
int locals_end_offset = 0; // 记录局部变量分配结束后的偏移量(相对于s0为负)
int spill_size = 0; // 仅为溢出分配的大小
int total_size = 0; // 总大小
int callee_saved_size = 0; // 保存寄存器的大小
std::map<unsigned, int> alloca_offsets; // <AllocaInst的vreg, 栈偏移>
std::map<unsigned, int> spill_offsets; // <溢出vreg, 栈偏移>
std::set<PhysicalReg> used_callee_saved_regs; // 使用的保存寄存器
std::map<unsigned, PhysicalReg> vreg_to_preg_map; // RegAlloc最终的分配结果
std::vector<PhysicalReg> callee_saved_regs_to_store; // 已排序的、需要存取的被调用者保存寄存器
};
// 机器函数
@ -211,7 +302,7 @@ public:
StackFrameInfo& getFrameInfo() { return frame_info; }
const std::vector<std::unique_ptr<MachineBasicBlock>>& getBlocks() const { return blocks; }
std::vector<std::unique_ptr<MachineBasicBlock>>& getBlocks() { return blocks; }
void dumpStackFrameInfo(std::ostream& os = std::cerr) const;
void addBlock(std::unique_ptr<MachineBasicBlock> block) {
blocks.push_back(std::move(block));
}
@ -223,15 +314,6 @@ private:
StackFrameInfo frame_info;
};
inline const std::vector<PhysicalReg>& getCallerSavedIntRegs() {
static const std::vector<PhysicalReg> regs = {
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3,
PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6,
PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3,
PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7
};
return regs;
}
} // namespace sysy
#endif // RISCV64_LLIR_H

View File

@ -0,0 +1,20 @@
#ifndef RISCV64_PASSES_H
#define RISCV64_PASSES_H
#include "RISCv64LLIR.h"
#include "Peephole.h"
#include "PreRA_Scheduler.h"
#include "PostRA_Scheduler.h"
#include "CalleeSavedHandler.h"
#include "LegalizeImmediates.h"
#include "PrologueEpilogueInsertion.h"
#include "EliminateFrameIndices.h"
#include "Pass.h"
#include "DivStrengthReduction.h"
namespace sysy {
} // namespace sysy
#endif // RISCV64_PASSES_H

View File

@ -0,0 +1,122 @@
#ifndef RISCV64_REGALLOC_H
#define RISCV64_REGALLOC_H
#include "RISCv64LLIR.h"
#include "RISCv64ISel.h" // 包含 RISCv64ISel.h 以访问 ISel 和 Value 类型
#include <set>
#include <vector>
#include <map>
#include <stack>
extern int DEBUG;
extern int DEEPDEBUG;
extern int DEBUGLENGTH; // 用于限制调试输出的长度
extern int DEEPERDEBUG; // 用于更深层次的调试输出
namespace sysy {
class RISCv64RegAlloc {
public:
RISCv64RegAlloc(MachineFunction* mfunc);
// 模块主入口
void run();
private:
// 类型定义与Python版本对应
using VRegSet = std::set<unsigned>;
using InterferenceGraph = std::map<unsigned, VRegSet>;
using VRegStack = std::vector<unsigned>; // 使用vector模拟栈方便遍历
using MoveList = std::map<unsigned, std::set<const MachineInstr*>>;
using AliasMap = std::map<unsigned, unsigned>;
using ColorMap = std::map<unsigned, PhysicalReg>;
using VRegMoveSet = std::set<const MachineInstr*>;
// --- 核心算法流程 ---
void initialize();
void build();
void makeWorklist();
void simplify();
void coalesce();
void freeze();
void selectSpill();
void assignColors();
void rewriteProgram();
bool doAllocation();
void applyColoring();
void dumpState(const std::string &stage);
void precolorByCallingConvention();
// --- 辅助函数 ---
void getInstrUseDef(const MachineInstr* instr, VRegSet& use, VRegSet& def);
void getInstrUseDef_Liveness(const MachineInstr *instr, VRegSet &use, VRegSet &def);
void addEdge(unsigned u, unsigned v);
VRegSet adjacent(unsigned n);
VRegMoveSet nodeMoves(unsigned n);
bool moveRelated(unsigned n);
void decrementDegree(unsigned m);
void enableMoves(const VRegSet& nodes);
unsigned getAlias(unsigned n);
void addWorklist(unsigned u);
bool briggsHeuristic(unsigned u, unsigned v);
bool georgeHeuristic(unsigned u, unsigned v);
void combine(unsigned u, unsigned v);
void freezeMoves(unsigned u);
void collectUsedCalleeSavedRegs();
bool isFPVReg(unsigned vreg) const;
std::string regToString(PhysicalReg reg);
std::string regIdToString(unsigned id);
// --- 活跃性分析 ---
void analyzeLiveness();
MachineFunction* MFunc;
RISCv64ISel* ISel;
// --- 算法数据结构 ---
// 寄存器池
std::vector<PhysicalReg> allocable_int_regs;
std::vector<PhysicalReg> allocable_fp_regs;
int K_int; // 整数寄存器数量
int K_fp; // 浮点寄存器数量
// 节点集合
VRegSet precolored; // 预着色的节点 (物理寄存器)
VRegSet initial; // 初始的、所有待处理的虚拟寄存器节点
VRegSet simplifyWorklist;
VRegSet freezeWorklist;
VRegSet spillWorklist;
VRegSet spilledNodes;
VRegSet coalescedNodes;
VRegSet coloredNodes;
VRegStack selectStack;
// Move指令相关
std::set<const MachineInstr*> coalescedMoves;
std::set<const MachineInstr*> constrainedMoves;
std::set<const MachineInstr*> frozenMoves;
std::set<const MachineInstr*> worklistMoves;
std::set<const MachineInstr*> activeMoves;
// 数据结构
InterferenceGraph adjSet;
std::map<unsigned, VRegSet> adjList; // 邻接表
std::map<unsigned, int> degree;
MoveList moveList;
AliasMap alias;
ColorMap color_map;
// 活跃性分析结果
std::map<const MachineInstr*, VRegSet> live_in_map;
std::map<const MachineInstr*, VRegSet> live_out_map;
// VReg -> Value* 和 VReg -> Type* 的映射
const std::map<unsigned, Value*>& vreg_to_value_map;
const std::map<unsigned, Type*>& vreg_type_map;
};
} // namespace sysy
#endif // RISCV64_REGALLOC_H

View File

@ -20,6 +20,10 @@
#include <algorithm>
namespace sysy {
// Global cleanup function to release all statically allocated IR objects
void cleanupIRPools();
/**
* \defgroup type Types
* @brief Sysy的类型系统
@ -83,6 +87,7 @@ class Type {
auto as() const -> std::enable_if_t<std::is_base_of_v<Type, T>, T *> {
return dynamic_cast<T *>(const_cast<Type *>(this));
}
virtual void print(std::ostream& os) const;
};
class PointerType : public Type {
@ -94,6 +99,9 @@ class PointerType : public Type {
public:
static PointerType* get(Type *baseType); ///< 获取指向baseType的Pointer类型
// Cleanup method to release all cached pointer types (call at program exit)
static void cleanup();
public:
Type* getBaseType() const { return baseType; } ///< 获取指向的类型
@ -111,6 +119,9 @@ class FunctionType : public Type {
public:
/// 获取返回值类型为returnType 形参类型列表为paramTypes的Function类型
static FunctionType* get(Type *returnType, const std::vector<Type *> &paramTypes = {});
// Cleanup method to release all cached function types (call at program exit)
static void cleanup();
public:
Type* getReturnType() const { return returnType; } ///< 获取返回值类信息
@ -123,6 +134,9 @@ class ArrayType : public Type {
// elements数组的元素类型 (例如int[3] 的 elementType 是 int)
// numElements该维度的大小 (例如int[3] 的 numElements 是 3)
static ArrayType *get(Type *elementType, unsigned numElements);
// Cleanup method to release all cached array types (call at program exit)
static void cleanup();
Type *getElementType() const { return elementType; }
unsigned getNumElements() const { return numElements; }
@ -202,9 +216,11 @@ class Use {
public:
unsigned getIndex() const { return index; } ///< 返回value在User操作数中的位置
void setIndex(int newIndex) { index = newIndex; } ///< 设置value在User操作数中的位置
User* getUser() const { return user; } ///< 返回使用者
Value* getValue() const { return value; } ///< 返回被使用的值
void setValue(Value *newValue) { value = newValue; } ///< 将被使用的值设置为newValue
void print(std::ostream& os) const;
};
//! The base class of all value types
@ -229,7 +245,15 @@ class Value {
std::list<std::shared_ptr<Use>>& getUses() { return uses; } ///< 获取使用关系列表
void addUse(const std::shared_ptr<Use> &use) { uses.push_back(use); } ///< 添加使用关系
void replaceAllUsesWith(Value *value); ///< 将原来使用该value的使用者全变为使用给定参数value并修改相应use关系
void removeUse(const std::shared_ptr<Use> &use) { uses.remove(use); } ///< 删除使用关系use
void removeUse(const std::shared_ptr<Use> &use) {
assert(use != nullptr && "Use cannot be null");
assert(use->getValue() == this && "Use being removed does NOT point to this Value!");
auto it = std::find(uses.begin(), uses.end(), use);
assert(it != uses.end() && "Use not found in Value's uses");
uses.remove(use);
} ///< 删除使用关系use
void removeAllUses();
virtual void print(std::ostream& os) const = 0; ///< 输出值信息到输出流
};
/**
@ -356,15 +380,31 @@ public:
// Static factory method to get a canonical ConstantValue from the pool
static ConstantValue* get(Type* type, ConstantValVariant val);
// Cleanup method to release all cached constants (call at program exit)
static void cleanup();
// Helper methods to access constant values with appropriate casting
int getInt() const {
assert(getType()->isInt() && "Calling getInt() on non-integer type");
return std::get<int>(getVal());
auto val = getVal();
if (std::holds_alternative<int>(val)) {
return std::get<int>(val);
} else if (std::holds_alternative<float>(val)) {
return static_cast<int>(std::get<float>(val));
}
// Handle other possible types if needed
return 0; // Default fallback
}
float getFloat() const {
assert(getType()->isFloat() && "Calling getFloat() on non-float type");
return std::get<float>(getVal());
auto val = getVal();
if (std::holds_alternative<float>(val)) {
return std::get<float>(val);
} else if (std::holds_alternative<int>(val)) {
return static_cast<float>(std::get<int>(val));
}
// Handle other possible types if needed
return 0.0f; // Default fallback
}
template<typename T>
@ -381,6 +421,7 @@ public:
virtual bool isZero() const = 0;
virtual bool isOne() const = 0;
void print(std::ostream& os) const = 0;
};
class ConstantInteger : public ConstantValue {
@ -407,6 +448,7 @@ public:
bool isZero() const override { return constVal == 0; }
bool isOne() const override { return constVal == 1; }
void print(std::ostream& os) const;
};
class ConstantFloating : public ConstantValue {
@ -433,6 +475,7 @@ public:
bool isZero() const override { return constFVal == 0.0f; }
bool isOne() const override { return constFVal == 1.0f; }
void print(std::ostream& os) const;
};
class UndefinedValue : public ConstantValue {
@ -447,6 +490,9 @@ protected:
public:
static UndefinedValue* get(Type* type);
// Cleanup method to release all cached undefined values (call at program exit)
static void cleanup();
size_t hash() const override {
return std::hash<Type*>{}(getType());
@ -464,6 +510,7 @@ public:
bool isZero() const override { return false; }
bool isOne() const override { return false; }
void print(std::ostream& os) const;
};
// --- End of refactored ConstantValue and related classes ---
@ -501,12 +548,15 @@ public:
explicit BasicBlock(Function *parent, const std::string &name = "")
: Value(Type::getLabelType(), name), parent(parent) {}
~BasicBlock() override {
for (auto pre : predecessors) {
pre->removeSuccessor(this);
}
for (auto suc : successors) {
suc->removePredecessor(this);
}
// for (auto pre : predecessors) {
// pre->removeSuccessor(this);
// }
// for (auto suc : successors) {
// suc->removePredecessor(this);
// }
// 这些关系应该在 BasicBlock 被从 Function 中移除时,
// 由负责 CFG 优化的 Pass (例如 SCCP 的 RemoveDeadBlock) 显式地清理。
// 析构函数只负责清理 BasicBlock 自身拥有的资源(例如,指令列表)。
}
public:
@ -525,6 +575,10 @@ public:
iterator begin() { return instructions.begin(); }
iterator end() { return instructions.end(); }
iterator terminator() { return std::prev(end()); }
iterator findInstIterator(Instruction *inst) {
return std::find_if(instructions.begin(), instructions.end(),
[inst](const std::unique_ptr<Instruction> &i) { return i.get() == inst; });
} ///< 查找指定指令的迭代器
bool hasSuccessor(BasicBlock *block) const {
return std::find(successors.begin(), successors.end(), block) != successors.end();
} ///< 判断是否有后继块
@ -556,7 +610,9 @@ public:
if (iter != predecessors.end()) {
predecessors.erase(iter);
} else {
assert(false);
// 如果没有找到前驱块,可能是因为它已经被移除或不存在
// 这可能是一个错误情况或者是因为在CFG优化过程中已经处理
// assert(false && "Predecessor block not found in BasicBlock");
}
}
void removeSuccessor(BasicBlock *block) {
@ -564,7 +620,9 @@ public:
if (iter != successors.end()) {
successors.erase(iter);
} else {
assert(false);
// 如果没有找到后继块,可能是因为它已经被移除或不存在
// 这可能是一个错误情况或者是因为在CFG优化过程中已经处理
// assert(false && "Successor block not found in BasicBlock");
}
}
void replacePredecessor(BasicBlock *oldBlock, BasicBlock *newBlock) {
@ -582,7 +640,7 @@ public:
prev->addSuccessor(next);
next->addPredecessor(prev);
}
void removeInst(iterator pos) { instructions.erase(pos); }
iterator removeInst(iterator pos) { return instructions.erase(pos); }
void removeInst(Instruction *inst) {
auto pos = std::find_if(instructions.begin(), instructions.end(),
[inst](const std::unique_ptr<Instruction> &i) { return i.get() == inst; });
@ -593,6 +651,11 @@ public:
}
} ///< 移除指定位置的指令
iterator moveInst(iterator sourcePos, iterator targetPos, BasicBlock *block);
/// 清理基本块中的所有使用关系
void cleanup();
void print(std::ostream& os) const;
};
//! User is the abstract base type of `Value` types which use other `Value` as
@ -618,11 +681,7 @@ class User : public Value {
operands.emplace_back(std::make_shared<Use>(operands.size(), this, value));
value->addUse(operands.back());
} ///< 增加操作数
void removeOperand(unsigned index) {
auto value = getOperand(index);
value->removeUse(operands[index]);
operands.erase(operands.begin() + index);
} ///< 移除操作数
void removeOperand(unsigned index);
template <typename ContainerT>
void addOperands(const ContainerT &newoperands) {
for (auto value : newoperands) {
@ -631,6 +690,9 @@ class User : public Value {
} ///< 增加多个操作数
void replaceOperand(unsigned index, Value *value); ///< 替换操作数
void setOperand(unsigned index, Value *value); ///< 设置操作数
/// 清理用户的所有操作数使用关系
void cleanup();
};
/*!
@ -678,19 +740,19 @@ class Instruction : public User {
kCondBr = 0x1UL << 30,
kBr = 0x1UL << 31,
kReturn = 0x1UL << 32,
kUnreachable = 0x1UL << 33,
// mem op
kAlloca = 0x1UL << 33,
kLoad = 0x1UL << 34,
kStore = 0x1UL << 35,
kGetElementPtr = 0x1UL << 36,
kMemset = 0x1UL << 37,
// kGetSubArray = 0x1UL << 38,
// Constant Kind removed as Constants are now Values, not Instructions.
// kConstant = 0x1UL << 37, // Conflicts with kMemset if kept as is
kAlloca = 0x1UL << 34,
kLoad = 0x1UL << 35,
kStore = 0x1UL << 36,
kGetElementPtr = 0x1UL << 37,
kMemset = 0x1UL << 38,
// phi
kPhi = 0x1UL << 39,
kBitItoF = 0x1UL << 40,
kBitFtoI = 0x1UL << 41,
kSRA = 0x1UL << 42,
kMulh = 0x1UL << 43
};
protected:
@ -708,57 +770,57 @@ public:
std::string getKindString() const{
switch (kind) {
case kInvalid:
return "Invalid";
return "invalid";
case kAdd:
return "Add";
return "add";
case kSub:
return "Sub";
return "sub";
case kMul:
return "Mul";
return "mul";
case kDiv:
return "Div";
return "sdiv";
case kRem:
return "Rem";
return "srem";
case kICmpEQ:
return "ICmpEQ";
return "icmp eq";
case kICmpNE:
return "ICmpNE";
return "icmp ne";
case kICmpLT:
return "ICmpLT";
return "icmp slt";
case kICmpGT:
return "ICmpGT";
return "icmp sgt";
case kICmpLE:
return "ICmpLE";
return "icmp sle";
case kICmpGE:
return "ICmpGE";
return "icmp sge";
case kFAdd:
return "FAdd";
return "fadd";
case kFSub:
return "FSub";
return "fsub";
case kFMul:
return "FMul";
return "fmul";
case kFDiv:
return "FDiv";
return "fdiv";
case kFCmpEQ:
return "FCmpEQ";
return "fcmp oeq";
case kFCmpNE:
return "FCmpNE";
return "fcmp one";
case kFCmpLT:
return "FCmpLT";
return "fcmp olt";
case kFCmpGT:
return "FCmpGT";
return "fcmp ogt";
case kFCmpLE:
return "FCmpLE";
return "fcmp ole";
case kFCmpGE:
return "FCmpGE";
return "fcmp oge";
case kAnd:
return "And";
return "and";
case kOr:
return "Or";
return "or";
case kNeg:
return "Neg";
return "neg";
case kNot:
return "Not";
return "not";
case kFNeg:
return "FNeg";
case kFNot:
@ -766,27 +828,35 @@ public:
case kFtoI:
return "FtoI";
case kItoF:
return "IToF";
return "iToF";
case kCall:
return "Call";
return "call";
case kCondBr:
return "CondBr";
return "condBr";
case kBr:
return "Br";
return "br";
case kReturn:
return "Return";
return "return";
case kUnreachable:
return "unreachable";
case kAlloca:
return "Alloca";
return "alloca";
case kLoad:
return "Load";
return "load";
case kStore:
return "Store";
return "store";
case kGetElementPtr:
return "GetElementPtr";
return "getElementPtr";
case kMemset:
return "Memset";
return "memset";
case kPhi:
return "Phi";
return "phi";
case kBitItoF:
return "BitItoF";
case kBitFtoI:
return "BitFtoI";
case kSRA:
return "ashr";
default:
return "Unknown";
}
@ -798,11 +868,15 @@ public:
bool isBinary() const {
static constexpr uint64_t BinaryOpMask =
(kAdd | kSub | kMul | kDiv | kRem | kAnd | kOr) |
(kICmpEQ | kICmpNE | kICmpLT | kICmpGT | kICmpLE | kICmpGE) |
(kAdd | kSub | kMul | kDiv | kRem | kAnd | kOr | kSRA | kMulh) |
(kICmpEQ | kICmpNE | kICmpLT | kICmpGT | kICmpLE | kICmpGE);
return kind & BinaryOpMask;
}
bool isFPBinary() const {
static constexpr uint64_t FPBinaryOpMask =
(kFAdd | kFSub | kFMul | kFDiv) |
(kFCmpEQ | kFCmpNE | kFCmpLT | kFCmpGT | kFCmpLE | kFCmpGE);
return kind & BinaryOpMask;
return kind & FPBinaryOpMask;
}
bool isUnary() const {
static constexpr uint64_t UnaryOpMask =
@ -815,7 +889,7 @@ public:
return kind & MemoryOpMask;
}
bool isTerminator() const {
static constexpr uint64_t TerminatorOpMask = kCondBr | kBr | kReturn;
static constexpr uint64_t TerminatorOpMask = kCondBr | kBr | kReturn | kUnreachable;
return kind & TerminatorOpMask;
}
bool isCmp() const {
@ -835,6 +909,7 @@ public:
}
bool isUnconditional() const { return kind == kBr; }
bool isConditional() const { return kind == kCondBr; }
bool isCondBr() const { return kind == kCondBr; }
bool isPhi() const { return kind == kPhi; }
bool isAlloca() const { return kind == kAlloca; }
bool isLoad() const { return kind == kLoad; }
@ -843,10 +918,15 @@ public:
bool isMemset() const { return kind == kMemset; }
bool isCall() const { return kind == kCall; }
bool isReturn() const { return kind == kReturn; }
bool isUnreachable() const { return kind == kUnreachable; }
bool isDefine() const {
static constexpr uint64_t DefineOpMask = kAlloca | kStore | kPhi;
return (kind & DefineOpMask) != 0U;
}
virtual ~Instruction() = default;
virtual void print(std::ostream& os) const = 0;
}; // class Instruction
class Function;
@ -868,38 +948,56 @@ class PhiInst : public Instruction {
const std::string &name = "")
: Instruction(Kind::kPhi, type, parent, name), vsize(rhs.size()) {
assert(rhs.size() == Blocks.size() && "PhiInst: rhs and Blocks must have the same size");
for(size_t i = 0; i < rhs.size(); ++i) {
for(size_t i = 0; i < vsize; ++i) {
addOperand(rhs[i]);
addOperand(Blocks[i]);
blk2val[Blocks[i]] = rhs[i];
}
}
public:
Value* getValue(unsigned k) const {return getOperand(2 * k);} ///< 获取位置为k的值
BasicBlock* getBlock(unsigned k) const {return dynamic_cast<BasicBlock*>(getOperand(2 * k + 1));}
auto& getincomings() const {return blk2val;} ///< 获取所有的基本块和对应的值
Value* getvalfromBlk(BasicBlock* blk);
BasicBlock* getBlkfromVal(Value* val);
unsigned getNumIncomingValues() const { return vsize; } ///< 获取传入值的数量
Value *getIncomingValue(unsigned Idx) const { return getOperand(Idx * 2); } ///< 获取指定位置的传入值
BasicBlock *getIncomingBlock(unsigned Idx) const {return dynamic_cast<BasicBlock *>(getOperand(Idx * 2 + 1)); } ///< 获取指定位置的传入基本块
Value* getValfromBlk(BasicBlock* block);
BasicBlock* getBlkfromVal(Value* value);
void addIncoming(Value *value, BasicBlock *block) {
assert(value && block && "PhiInst: value and block must not be null");
assert(value && block && "PhiInst: value and block cannot be null");
addOperand(value);
addOperand(block);
blk2val[block] = value;
vsize++;
} ///< 添加传入值和对应的基本块
void delValue(Value* val);
void delBlk(BasicBlock* blk);
void replaceBlk(BasicBlock* newBlk, unsigned k);
void replaceold2new(BasicBlock* oldBlk, BasicBlock* newBlk);
void refreshB2VMap();
void removeIncoming(unsigned Idx) {
assert(Idx < vsize && "PhiInst: Index out of bounds");
auto blk = getIncomingBlock(Idx);
removeOperand(Idx * 2 + 1); // Remove block
removeOperand(Idx * 2); // Remove value
blk2val.erase(blk);
vsize--;
} ///< 移除指定位置的传入值和对应的基本块
// 移除指定的传入值或基本块
void removeIncomingValue(Value *value);
void removeIncomingBlock(BasicBlock *block);
// 设置指定位置的传入值或基本块
void setIncomingValue(unsigned Idx, Value *value);
void setIncomingBlock(unsigned Idx, BasicBlock *block);
// 替换指定位置的传入值或基本块(原理是删除再添加)保留旧块或者旧值
void replaceIncomingValue(Value *oldValue, Value *newValue);
void replaceIncomingBlock(BasicBlock *oldBlock, BasicBlock *newBlock);
// 替换指定位置的传入值或基本块(原理是删除再添加)
void replaceIncomingValue(Value *oldValue, Value *newValue, BasicBlock *newBlock);
void replaceIncomingBlock(BasicBlock *oldBlock, BasicBlock *newBlock, Value *newValue);
void refreshMap() {
blk2val.clear();
for (unsigned i = 0; i < vsize; ++i) {
blk2val[getIncomingBlock(i)] = getIncomingValue(i);
}
} ///< 刷新块到值的映射关系
auto getValues() { return make_range(std::next(operand_begin()), operand_end()); }
void print(std::ostream& os) const override;
};
@ -908,16 +1006,14 @@ class CallInst : public Instruction {
friend class IRBuilder;
protected:
CallInst(Function *callee, const std::vector<Value *> &args = {},
BasicBlock *parent = nullptr, const std::string &name = "");
CallInst(Function *callee, const std::vector<Value *> &args, BasicBlock *parent = nullptr, const std::string &name = "");
public:
Function* getCallee() const;
Function *getCallee() const;
auto getArguments() const {
return make_range(std::next(operand_begin()), operand_end());
}
void print(std::ostream& os) const override;
}; // class CallInst
//! Unary instruction, includes '!', '-' and type conversion.
@ -935,7 +1031,7 @@ protected:
public:
Value* getOperand() const { return User::getOperand(0); }
void print(std::ostream& os) const override;
}; // class UnaryInst
//! Binary instruction, e.g., arithmatic, relation, logic, etc.
@ -1014,6 +1110,7 @@ public:
// 后端处理数组访存操作时需要创建计算地址的指令,需要在外部构造 BinaryInst 对象
return new BinaryInst(kind, type, lhs, rhs, parent, name);
}
void print(std::ostream& os) const override;
}; // class BinaryInst
//! The return statement
@ -1034,6 +1131,7 @@ class ReturnInst : public Instruction {
Value* getReturnValue() const {
return hasReturnValue() ? getOperand(0) : nullptr;
}
void print(std::ostream& os) const override;
};
//! Unconditional branch
@ -1042,12 +1140,10 @@ class UncondBrInst : public Instruction {
friend class Function;
protected:
UncondBrInst(BasicBlock *block, std::vector<Value *> args,
UncondBrInst(BasicBlock *block,
BasicBlock *parent = nullptr)
: Instruction(kBr, Type::getVoidType(), parent, "") {
// assert(block->getNumArguments() == args.size());
addOperand(block);
addOperands(args);
}
public:
@ -1055,7 +1151,17 @@ public:
auto getArguments() const {
return make_range(std::next(operand_begin()), operand_end());
}
std::vector<BasicBlock *> getSuccessors() const {
std::vector<BasicBlock *> succs;
// 假设无条件分支的目标块是它的第一个操作数
if (getNumOperands() > 0) {
if (auto target_bb = dynamic_cast<BasicBlock *>(getOperand(0))) {
succs.push_back(target_bb);
}
}
return succs;
}
void print(std::ostream& os) const override;
}; // class UncondBrInst
//! Conditional branch
@ -1066,17 +1172,12 @@ class CondBrInst : public Instruction {
friend class Function;
protected:
CondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock,
const std::vector<Value *> &thenArgs,
const std::vector<Value *> &elseArgs, BasicBlock *parent = nullptr)
CondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock,
BasicBlock *parent = nullptr)
: Instruction(kCondBr, Type::getVoidType(), parent, "") {
// assert(thenBlock->getNumArguments() == thenArgs.size() and
// elseBlock->getNumArguments() == elseArgs.size());
addOperand(condition);
addOperand(thenBlock);
addOperand(elseBlock);
addOperands(thenArgs);
addOperands(elseArgs);
}
public:
Value* getCondition() const { return getOperand(0); }
@ -1086,37 +1187,47 @@ public:
BasicBlock* getElseBlock() const {
return dynamic_cast<BasicBlock *>(getOperand(2));
}
// auto getThenArguments() const {
// auto begin = std::next(operand_begin(), 3);
// // auto end = std::next(begin, getThenBlock()->getNumArguments());
// return make_range(begin, end);
// }
// auto getElseArguments() const {
// auto begin =
// std::next(operand_begin(), 3 + getThenBlock()->getNumArguments());
// auto end = operand_end();
// return make_range(begin, end);
// }
std::vector<BasicBlock *> getSuccessors() const {
std::vector<BasicBlock *> succs;
// 假设条件分支的真实块是第二个操作数,假块是第三个操作数
// 操作数通常是:[0] 条件值, [1] TrueTargetBlock, [2] FalseTargetBlock
if (getNumOperands() > 2) {
if (auto true_bb = getThenBlock()) {
succs.push_back(true_bb);
}
if (auto false_bb = getElseBlock()) {
succs.push_back(false_bb);
}
}
return succs;
}
void print(std::ostream& os) const override;
}; // class CondBrInst
class UnreachableInst : public Instruction {
public:
// 构造函数:设置指令类型为 kUnreachable
explicit UnreachableInst(const std::string& name, BasicBlock *parent = nullptr)
: Instruction(kUnreachable, Type::getVoidType(), parent, "") {}
void print(std::ostream& os) const { os << "unreachable"; }
};
//! Allocate memory for stack variables, used for non-global variable declartion
class AllocaInst : public Instruction {
friend class IRBuilder;
friend class Function;
protected:
AllocaInst(Type *type, const std::vector<Value *> &dims = {},
AllocaInst(Type *type,
BasicBlock *parent = nullptr, const std::string &name = "")
: Instruction(kAlloca, type, parent, name) {
addOperands(dims);
}
public:
int getNumDims() const { return getNumOperands(); }
auto getDims() const { return getOperands(); }
Value* getDim(int index) { return getOperand(index); }
//! 获取分配的类型
Type* getAllocatedType() const {
return getType()->as<PointerType>()->getBaseType();
} ///< 获取分配的类型
void print(std::ostream& os) const override;
}; // class AllocaInst
@ -1154,6 +1265,7 @@ public:
BasicBlock *parent = nullptr, const std::string &name = "") {
return new GetElementPtrInst(resultType, basePointer, indices, parent, name);
}
void print(std::ostream& os) const override;
};
//! Load a value from memory address specified by a pointer value
@ -1162,22 +1274,16 @@ class LoadInst : public Instruction {
friend class Function;
protected:
LoadInst(Value *pointer, const std::vector<Value *> &indices = {},
LoadInst(Value *pointer,
BasicBlock *parent = nullptr, const std::string &name = "")
: Instruction(kLoad, pointer->getType()->as<PointerType>()->getBaseType(),
parent, name) {
addOperand(pointer);
addOperands(indices);
}
public:
int getNumIndices() const { return getNumOperands() - 1; }
Value* getPointer() const { return getOperand(0); }
auto getIndices() const {
return make_range(std::next(operand_begin()), operand_end());
}
Value* getIndex(int index) const { return getOperand(index + 1); }
void print(std::ostream& os) const override;
}; // class LoadInst
//! Store a value to memory address specified by a pointer value
@ -1187,23 +1293,16 @@ class StoreInst : public Instruction {
protected:
StoreInst(Value *value, Value *pointer,
const std::vector<Value *> &indices = {},
BasicBlock *parent = nullptr, const std::string &name = "")
: Instruction(kStore, Type::getVoidType(), parent, name) {
addOperand(value);
addOperand(pointer);
addOperands(indices);
}
public:
int getNumIndices() const { return getNumOperands() - 2; }
Value* getValue() const { return getOperand(0); }
Value* getPointer() const { return getOperand(1); }
auto getIndices() const {
return make_range(std::next(operand_begin(), 2), operand_end());
}
Value* getIndex(int index) const { return getOperand(index + 2); }
void print(std::ostream& os) const override;
}; // class StoreInst
//! Memset instruction
@ -1233,7 +1332,7 @@ public:
Value* getBegin() const { return getOperand(1); }
Value* getSize() const { return getOperand(2); }
Value* getValue() const { return getOperand(3); }
void print(std::ostream& os) const override;
};
class GlobalValue;
@ -1251,6 +1350,11 @@ public:
public:
Function* getParent() const { return func; }
int getIndex() const { return index; }
/// 清理参数的使用关系
void cleanup();
void print(std::ostream& os) const;
};
@ -1328,10 +1432,15 @@ protected:
blocks.emplace_front(block);
return block;
}
/// 清理函数中的所有使用关系
void cleanup();
void print(std::ostream& os) const;
};
//! Global value declared at file scope
class GlobalValue : public User {
class GlobalValue : public Value {
friend class Module;
protected:
@ -1341,19 +1450,18 @@ protected:
protected:
GlobalValue(Module *parent, Type *type, const std::string &name,
const std::vector<Value *> &dims = {},
ValueCounter init = {})
: User(type, name), parent(parent) {
: Value(type, name), parent(parent) {
assert(type->isPointer());
addOperands(dims);
numDims = dims.size();
// 维度信息已经被记录到Type中dim只是为了方便初始化
numDims = 0;
if (init.size() == 0) {
unsigned num = 1;
for (unsigned i = 0; i < numDims; i++) {
// Assume dims elements are ConstantInteger and cast appropriately
auto dim_val = dynamic_cast<ConstantInteger*>(dims[i]);
assert(dim_val && "GlobalValue dims must be constant integers");
num *= dim_val->getInt();
auto arrayType = type->as<ArrayType>();
while (arrayType) {
numDims++;
num *= arrayType->getNumElements();
arrayType = arrayType->getElementType()->as<ArrayType>();
}
if (dynamic_cast<PointerType *>(type)->getBaseType() == Type::getFloatType()) {
init.push_back(ConstantFloating::get(0.0F), num); // Use new constant factory
@ -1365,28 +1473,40 @@ protected:
}
public:
unsigned getNumDims() const { return numDims; } ///< 获取维度数量
Value* getDim(unsigned index) const { return getOperand(index); } ///< 获取位置为index的维度
auto getDims() const { return getOperands(); } ///< 获取维度列表
unsigned getNumIndices() const {
return numDims;
} ///< 获取维度数量
unsigned getIndex(unsigned index) const {
assert(index < getNumIndices() && "Index out of bounds for GlobalValue!");
Type *GlobalValueType = getType()->as<PointerType>()->getBaseType();
for (unsigned i = 0; i < index; i++) {
GlobalValueType = GlobalValueType->as<ArrayType>()->getElementType();
}
return GlobalValueType->as<ArrayType>()->getNumElements();
} ///< 获取维度大小(从第0个开始)
Value* getByIndex(unsigned index) const {
return initValues.getValue(index);
} ///< 通过一维偏移量index获取初始值
Value* getByIndices(const std::vector<Value *> &indices) const {
Value* getByIndices(const std::vector<Value *> &indices) const {
int index = 0;
Type *GlobalValueType = getType()->as<PointerType>()->getBaseType();
for (size_t i = 0; i < indices.size(); i++) {
// Ensure dims[i] and indices[i] are ConstantInteger and retrieve their values correctly
auto dim_val = dynamic_cast<ConstantInteger*>(getDim(i));
// GlobalValueType->as<ArrayType>()->getNumElements();
auto dim_val = GlobalValueType->as<ArrayType>()->getNumElements();
auto idx_val = dynamic_cast<ConstantInteger*>(indices[i]);
assert(dim_val && idx_val && "Dims and indices must be constant integers");
index = dim_val->getInt() * index + idx_val->getInt();
index = dim_val * index + idx_val->getInt();
GlobalValueType = GlobalValueType->as<ArrayType>()->getElementType();
}
return getByIndex(index);
} ///< 通过多维索引indices获取初始值
const ValueCounter& getInitValues() const { return initValues; }
void print(std::ostream& os) const;
}; // class GlobalValue
class ConstantVariable : public User {
class ConstantVariable : public Value {
friend class Module;
protected:
@ -1395,34 +1515,53 @@ class ConstantVariable : public User {
ValueCounter initValues; ///< 值
protected:
ConstantVariable(Module *parent, Type *type, const std::string &name, const ValueCounter &init,
const std::vector<Value *> &dims = {})
: User(type, name), parent(parent) {
ConstantVariable(Module *parent, Type *type, const std::string &name, const ValueCounter &init)
: Value(type, name), parent(parent) {
assert(type->isPointer());
numDims = dims.size();
// numDims = dims.size();
numDims = 0;
if(type->as<PointerType>()->getBaseType()->isArray()) {
auto arrayType = type->as<ArrayType>();
while (arrayType) {
numDims++;
arrayType = arrayType->getElementType()->as<ArrayType>();
}
}
initValues = init;
addOperands(dims);
}
public:
unsigned getNumIndices() const {
return numDims;
} ///< 获取索引数量
unsigned getIndex(unsigned index) const {
assert(index < getNumIndices() && "Index out of bounds for ConstantVariable!");
Type *ConstantVariableType = getType()->as<PointerType>()->getBaseType();
for (unsigned i = 0; i < index; i++) {
ConstantVariableType = ConstantVariableType->as<ArrayType>()->getElementType();
}
return ConstantVariableType->as<ArrayType>()->getNumElements();
} ///< 获取索引个数(从第0个开始)
Value* getByIndex(unsigned index) const { return initValues.getValue(index); } ///< 通过一维位置index获取值
Value* getByIndices(const std::vector<Value *> &indices) const {
int index = 0;
// 计算偏移量
Type *ConstantVariableType = getType()->as<PointerType>()->getBaseType();
for (size_t i = 0; i < indices.size(); i++) {
// Ensure dims[i] and indices[i] are ConstantInteger and retrieve their values correctly
auto dim_val = dynamic_cast<ConstantInteger*>(getDim(i));
// ConstantVariableType->as<ArrayType>()->getNumElements();
auto dim_val = ConstantVariableType->as<ArrayType>()->getNumElements();
auto idx_val = dynamic_cast<ConstantInteger*>(indices[i]);
assert(dim_val && idx_val && "Dims and indices must be constant integers");
index = dim_val->getInt() * index + idx_val->getInt();
index = dim_val * index + idx_val->getInt();
ConstantVariableType = ConstantVariableType->as<ArrayType>()->getElementType();
}
return getByIndex(index);
} ///< 通过多维索引indices获取初始值
unsigned getNumDims() const { return numDims; } ///< 获取维度数量
Value* getDim(unsigned index) const { return getOperand(index); } ///< 获取位置为index的维度
auto getDims() const { return getOperands(); } ///< 获取维度列表
const ValueCounter& getInitValues() const { return initValues; } ///< 获取初始值
void print(std::ostream& os) const;
void print_init(std::ostream& os) const;
};
using SymbolTableNode = struct SymbolTableNode {
@ -1437,7 +1576,7 @@ class SymbolTable {
SymbolTableNode *curNode{}; ///< 当前所在的作用域(符号表节点)
std::map<std::string, unsigned> variableIndex; ///< 变量命名索引表
std::vector<std::unique_ptr<GlobalValue>> globals; ///< 全局变量列表
std::vector<std::unique_ptr<ConstantVariable>> consts; ///< 常量列表
std::vector<std::unique_ptr<ConstantVariable>> globalconsts; ///< 全局常量列表
std::vector<std::unique_ptr<SymbolTableNode>> nodeList; ///< 符号表节点列表
public:
@ -1445,13 +1584,18 @@ class SymbolTable {
Value* getVariable(const std::string &name) const; ///< 根据名字name以及当前作用域获取变量
Value* addVariable(const std::string &name, Value *variable); ///< 添加变量
void registerParameterName(const std::string &name); ///< 注册函数参数名字避免alloca重名
void addVariableDirectly(const std::string &name, Value *variable); ///< 直接添加变量到当前作用域,不重命名
std::vector<std::unique_ptr<GlobalValue>>& getGlobals(); ///< 获取全局变量列表
const std::vector<std::unique_ptr<ConstantVariable>>& getConsts() const; ///< 获取常量列表
const std::vector<std::unique_ptr<ConstantVariable>>& getConsts() const; ///< 获取全局常量列表
void enterNewScope(); ///< 进入新的作用域
void leaveScope(); ///< 离开作用域
bool isInGlobalScope() const; ///< 是否位于全局作用域
void enterGlobalScope(); ///< 进入全局作用域
bool isCurNodeNull() { return curNode == nullptr; }
/// 清理符号表中的所有内容
void cleanup();
};
//! IR unit for representing a SysY compile unit
@ -1480,13 +1624,12 @@ class Module {
return result.first->second.get();
} ///< 创建外部函数
///< 变量创建伴随着符号表的更新
GlobalValue* createGlobalValue(const std::string &name, Type *type, const std::vector<Value *> &dims = {},
const ValueCounter &init = {}) {
GlobalValue* createGlobalValue(const std::string &name, Type *type, const ValueCounter &init = {}) {
bool isFinished = variableTable.isCurNodeNull();
if (isFinished) {
variableTable.enterGlobalScope();
}
auto result = variableTable.addVariable(name, new GlobalValue(this, type, name, dims, init));
auto result = variableTable.addVariable(name, new GlobalValue(this, type, name, init));
if (isFinished) {
variableTable.leaveScope();
}
@ -1495,9 +1638,8 @@ class Module {
}
return dynamic_cast<GlobalValue *>(result);
} ///< 创建全局变量
ConstantVariable* createConstVar(const std::string &name, Type *type, const ValueCounter &init,
const std::vector<Value *> &dims = {}) {
auto result = variableTable.addVariable(name, new ConstantVariable(this, type, name, init, dims));
ConstantVariable* createConstVar(const std::string &name, Type *type, const ValueCounter &init) {
auto result = variableTable.addVariable(name, new ConstantVariable(this, type, name, init));
if (result == nullptr) {
return nullptr;
}
@ -1506,6 +1648,12 @@ class Module {
void addVariable(const std::string &name, AllocaInst *variable) {
variableTable.addVariable(name, variable);
} ///< 添加变量
void addVariableDirectly(const std::string &name, AllocaInst *variable) {
variableTable.addVariableDirectly(name, variable);
} ///< 直接添加变量到当前作用域,不重命名
void registerParameterName(const std::string &name) {
variableTable.registerParameterName(name);
} ///< 注册函数参数名字避免alloca重名
Value* getVariable(const std::string &name) {
return variableTable.getVariable(name);
} ///< 根据名字name和当前作用域获取变量
@ -1518,7 +1666,7 @@ class Module {
} ///< 获取函数
Function* getExternalFunction(const std::string &name) const {
auto result = externalFunctions.find(name);
if (result == functions.end()) {
if (result == externalFunctions.end()) {
return nullptr;
}
return result->second.get();
@ -1538,6 +1686,11 @@ class Module {
void leaveScope() { variableTable.leaveScope(); } ///< 离开作用域
bool isInGlobalArea() const { return variableTable.isInGlobalScope(); } ///< 是否位于全局作用域
/// 清理模块中的所有对象,包括函数、基本块、指令等
void cleanup();
void print(std::ostream& os) const;
};
/*!

View File

@ -126,7 +126,7 @@ class IRBuilder {
UnaryInst * createFNotInst(Value *operand, const std::string &name = "") {
return createUnaryInst(Instruction::kFNot, Type::getIntType(), operand, name);
} ///< 创建浮点取非指令
UnaryInst * createIToFInst(Value *operand, const std::string &name = "") {
UnaryInst * createItoFInst(Value *operand, const std::string &name = "") {
return createUnaryInst(Instruction::kItoF, Type::getFloatType(), operand, name);
} ///< 创建整型转浮点指令
UnaryInst * createBitItoFInst(Value *operand, const std::string &name = "") {
@ -217,6 +217,12 @@ class IRBuilder {
BinaryInst * createOrInst(Value *lhs, Value *rhs, const std::string &name = "") {
return createBinaryInst(Instruction::kOr, Type::getIntType(), lhs, rhs, name);
} ///< 创建按位或指令
BinaryInst * createSRAInst(Value *lhs, Value *rhs, const std::string &name = "") {
return createBinaryInst(Instruction::kSRA, Type::getIntType(), lhs, rhs, name);
} ///< 创建算术右移指令
BinaryInst * createMulhInst(Value *lhs, Value *rhs, const std::string &name = "") {
return createBinaryInst(Instruction::kMulh, Type::getIntType(), lhs, rhs, name);
} ///< 创建高位乘法指令
CallInst * createCallInst(Function *callee, const std::vector<Value *> &args, const std::string &name = "") {
std::string newName;
if (name.empty() && callee->getReturnType() != Type::getVoidType()) {
@ -239,31 +245,30 @@ class IRBuilder {
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建return指令
UncondBrInst * createUncondBrInst(BasicBlock *thenBlock, const std::vector<Value *> &args) {
auto inst = new UncondBrInst(thenBlock, args, block);
UncondBrInst * createUncondBrInst(BasicBlock *thenBlock) {
auto inst = new UncondBrInst(thenBlock, block);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建无条件指令
CondBrInst * createCondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock,
const std::vector<Value *> &thenArgs, const std::vector<Value *> &elseArgs) {
auto inst = new CondBrInst(condition, thenBlock, elseBlock, thenArgs, elseArgs, block);
CondBrInst * createCondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock) {
auto inst = new CondBrInst(condition, thenBlock, elseBlock, block);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建条件跳转指令
AllocaInst * createAllocaInst(Type *type, const std::vector<Value *> &dims = {}, const std::string &name = "") {
auto inst = new AllocaInst(type, dims, block, name);
UnreachableInst * createUnreachableInst(const std::string &name = "") {
auto inst = new UnreachableInst(name, block);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建不可达指令
AllocaInst * createAllocaInst(Type *type, const std::string &name = "") {
auto inst = new AllocaInst(type, block, name);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建分配指令
AllocaInst * createAllocaInstWithoutInsert(Type *type, const std::vector<Value *> &dims = {}, BasicBlock *parent = nullptr,
const std::string &name = "") {
auto inst = new AllocaInst(type, dims, parent, name);
assert(inst);
return inst;
} ///< 创建不插入指令列表的分配指令[仅用于phi指令]
LoadInst * createLoadInst(Value *pointer, const std::vector<Value *> &indices = {}, const std::string &name = "") {
std::string newName;
if (name.empty()) {
@ -275,7 +280,7 @@ class IRBuilder {
newName = name;
}
auto inst = new LoadInst(pointer, indices, block, newName);
auto inst = new LoadInst(pointer, block, newName);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
@ -286,37 +291,27 @@ class IRBuilder {
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建memset指令
StoreInst * createStoreInst(Value *value, Value *pointer, const std::vector<Value *> &indices = {},
const std::string &name = "") {
auto inst = new StoreInst(value, pointer, indices, block, name);
StoreInst * createStoreInst(Value *value, Value *pointer, const std::string &name = "") {
auto inst = new StoreInst(value, pointer, block, name);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建store指令
PhiInst * createPhiInst(Type *type, const std::vector<Value*> &vals = {}, const std::vector<BasicBlock*> &blks = {}, const std::string &name = "") {
auto inst = new PhiInst(type, vals, blks, block, name);
std::string newName;
if (name.empty()) {
std::stringstream ss;
ss << tmpIndex;
newName = ss.str();
tmpIndex++;
} else {
newName = name;
}
auto inst = new PhiInst(type, vals, blks, block, newName);
assert(inst);
block->getInstructions().emplace(block->begin(), inst);
return inst;
} ///< 创建Phi指令
// GetElementPtrInst* createGetElementPtrInst(Value *basePointer,
// const std::vector<Value *> &indices = {},
// const std::string &name = "") {
// std::string newName;
// if (name.empty()) {
// std::stringstream ss;
// ss << tmpIndex;
// newName = ss.str();
// tmpIndex++;
// } else {
// newName = name;
// }
// auto inst = new GetElementPtrInst(basePointer, indices, block, newName);
// assert(inst);
// block->getInstructions().emplace(position, inst);
// return inst;
// }
/**
* @brief LLVM GEP
*
@ -355,38 +350,31 @@ class IRBuilder {
Type *currentWalkType = pointerType->as<PointerType>()->getBaseType();
// 遍历所有索引来深入类型层次结构。
// `indices` 向量包含了所有 GEP 索引,包括由 `visitLValue` 等函数添加的初始 `0` 索引
// 重要:第一个索引总是用于"解引用"指针,后续索引才用于数组/结构体的索引
for (int i = 0; i < indices.size(); ++i) {
if (currentWalkType->isArray()) {
// 情况一:当前遍历类型是 `ArrayType`。
// 索引用于选择数组元素,`currentWalkType` 更新为数组的元素类型。
currentWalkType = currentWalkType->as<ArrayType>()->getElementType();
} else if (currentWalkType->isPointer()) {
// 情况二:当前遍历类型是 `PointerType`。
// 这意味着我们正在通过一个指针来访问其指向的内存。
// 索引用于选择该指针所指向的“数组”的元素。
// `currentWalkType` 更新为该指针所指向的基础类型。
// 例如:如果 `currentWalkType` 是 `i32*`,它将变为 `i32`。
// 如果 `currentWalkType` 是 `[10 x i32]*`,它将变为 `[10 x i32]`。
currentWalkType = currentWalkType->as<PointerType>()->getBaseType();
if (i == 0) {
// 第一个索引:总是用于"解引用"基指针不改变currentWalkType
// 例如:对于 `[4 x i32]* ptr, i32 0`第一个0只是说"访问ptr指向的对象"
// currentWalkType 保持为 `[4 x i32]`
continue;
} else {
// 情况三:当前遍历类型是标量类型 (例如 `i32`, `float` 等非聚合、非指针类型)。
//
// 如果 `currentWalkType` 是标量,并且当前索引 `i` **不是** `indices` 向量中的最后一个索引,
// 这意味着尝试对一个标量类型进行进一步的结构性索引,这是**无效的**。
// 例如:`int x; x[0];` 对应的 GEP 链中,`x` 的类型是 `i32`,再加 `[0]` 索引就是错误。
//
// 如果 `currentWalkType` 是标量,且这是**最后一个索引** (`i == indices.size() - 1`)
// 那么 GEP 是合法的,它只是计算一个偏移地址,最终的类型就是这个标量类型。
// 此时 `currentWalkType` 保持不变,循环结束。
if (i < indices.size() - 1) {
assert(false && "Invalid GEP indexing: attempting to index into a non-aggregate/non-pointer type with further indices.");
return nullptr; // 返回空指针表示类型推断失败
// 后续索引:用于实际的数组/结构体索引
if (currentWalkType->isArray()) {
// 数组索引:选择数组中的元素
currentWalkType = currentWalkType->as<ArrayType>()->getElementType();
} else if (currentWalkType->isPointer()) {
// 指针索引:解引用指针并继续
currentWalkType = currentWalkType->as<PointerType>()->getBaseType();
} else {
// 标量类型:不能进一步索引
if (i < indices.size() - 1) {
assert(false && "Invalid GEP indexing: attempting to index into a non-aggregate/non-pointer type with further indices.");
return nullptr;
}
}
// 如果是最后一个索引,且当前类型是标量,则类型保持不变,这是合法的。
// 循环会自然结束,返回正确的 `currentWalkType`。
}
}
// 所有索引处理完毕后,`currentWalkType` 就是 GEP 指令最终计算出的地址所指向的元素的类型。
return currentWalkType;
}

View File

@ -0,0 +1,107 @@
#pragma once
#include "Pass.h" // 包含 Pass 框架
#include "IR.h" // 包含 IR 定义
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
namespace sysy {
// 支配树分析结果类
class DominatorTree : public AnalysisResultBase {
public:
DominatorTree(Function* F);
// 获取指定基本块的所有支配者
const std::set<BasicBlock*>* getDominators(BasicBlock* BB) const;
// 获取指定基本块的即时支配者 (Immediate Dominator)
BasicBlock* getImmediateDominator(BasicBlock* BB) const;
// 获取指定基本块的支配边界 (Dominance Frontier)
const std::set<BasicBlock*>* getDominanceFrontier(BasicBlock* BB) const;
// 获取指定基本块在支配树中的子节点
const std::set<BasicBlock*>* getDominatorTreeChildren(BasicBlock* BB) const;
// 额外的 Getter获取所有支配者、即时支配者和支配边界的完整映射可选主要用于调试或特定场景
const std::map<BasicBlock*, std::set<BasicBlock*>>& getDominatorsMap() const { return Dominators; }
const std::map<BasicBlock*, BasicBlock*>& getIDomsMap() const { return IDoms; }
const std::map<BasicBlock*, std::set<BasicBlock*>>& getDominanceFrontiersMap() const { return DominanceFrontiers; }
// 计算所有基本块的支配者集合
void computeDominators(Function* F);
// 计算所有基本块的即时支配者(内部使用 Lengauer-Tarjan 算法)
void computeIDoms(Function* F);
// 计算所有基本块的支配边界
void computeDominanceFrontiers(Function* F);
// 计算支配树的结构(即每个节点的直接子节点)
void computeDominatorTreeChildren(Function* F);
private:
// 与该支配树关联的函数
Function* AssociatedFunction;
std::map<BasicBlock*, std::set<BasicBlock*>> Dominators; // 每个基本块的支配者集合
std::map<BasicBlock*, BasicBlock*> IDoms; // 每个基本块的即时支配者
std::map<BasicBlock*, std::set<BasicBlock*>> DominanceFrontiers; // 每个基本块的支配边界
std::map<BasicBlock*, std::set<BasicBlock*>> DominatorTreeChildren; // 支配树中每个基本块的子节点
// ==========================================================
// Lengauer-Tarjan 算法内部所需的数据结构和辅助函数
// 这些成员是私有的,以封装 LT 算法的复杂性并避免命名空间污染
// ==========================================================
// DFS 遍历相关:
std::map<BasicBlock*, int> dfnum_map; // 存储每个基本块的 DFS 编号
std::vector<BasicBlock*> vertex_vec; // 通过 DFS 编号反向查找对应的基本块指针
std::map<BasicBlock*, BasicBlock*> parent_map; // 存储 DFS 树中每个基本块的父节点
int df_counter; // DFS 计数器,也代表 DFS 遍历的总节点数 (N)
// 半支配者 (Semi-dominator) 相关:
std::map<BasicBlock*, BasicBlock*> sdom_map; // 存储每个基本块的半支配者
std::map<BasicBlock*, BasicBlock*> idom_map; // 存储每个基本块的即时支配者 (IDom)
std::map<BasicBlock*, std::vector<BasicBlock*>> bucket_map; // 桶结构,用于存储具有相同半支配者的节点,以延迟 IDom 计算
// 并查集 (Union-Find) 相关(用于 evalAndCompress 函数):
std::map<BasicBlock*, BasicBlock*> ancestor_map; // 并查集中的父节点(用于路径压缩)
std::map<BasicBlock*, BasicBlock*> label_map; // 并查集中,每个集合的代表节点(或其路径上 sdom 最小的节点)
// ==========================================================
// 辅助计算函数 (私有)
// ==========================================================
// 计算基本块的逆后序遍历 (Reverse Post Order, RPO) 顺序
// RPO 用于优化支配者计算和 LT 算法的效率
std::vector<BasicBlock*> computeReversePostOrder(Function* F);
// Lengauer-Tarjan 算法特定的辅助 DFS 函数
// 用于初始化 dfnum_map, vertex_vec, parent_map
void dfs_lt_helper(BasicBlock* u);
// 结合了并查集的 Find 操作和 LT 算法的 Eval 操作
// 用于在路径压缩时更新 label找到路径上 sdom 最小的节点
BasicBlock* evalAndCompress_lt_helper(BasicBlock* i);
// 并查集的 Link 操作
// 将 v_child 挂载到 u_parent 的并查集树下
void link_lt_helper(BasicBlock* u_parent, BasicBlock* v_child);
};
// 支配树分析遍
class DominatorTreeAnalysisPass : public AnalysisPass {
public:
// 唯一的 Pass ID
static void *ID;
DominatorTreeAnalysisPass() : AnalysisPass("DominatorTreeAnalysis", Pass::Granularity::Function) {}
// 实现 getPassID
void* getPassID() const override { return &ID; }
bool runOnFunction(Function* F, AnalysisManager &AM) override;
std::unique_ptr<AnalysisResultBase> getResult() override;
private:
std::unique_ptr<DominatorTree> CurrentDominatorTree;
};
} // namespace sysy

View File

@ -0,0 +1,20 @@
#pragma once
#include "IR.h"
#include "Pass.h"
#include <queue>
#include <set>
namespace sysy {
class BuildCFG : public OptimizationPass {
public:
static void *ID;
BuildCFG() : OptimizationPass("BuildCFG", Granularity::Function) {}
bool runOnFunction(Function *F, AnalysisManager &AM) override;
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
void *getPassID() const override { return &ID; }
};
} // namespace sysy

View File

@ -0,0 +1,24 @@
#pragma once
#include "../Pass.h"
namespace sysy {
class LargeArrayToGlobalPass : public OptimizationPass {
public:
static void *ID;
LargeArrayToGlobalPass() : OptimizationPass("LargeArrayToGlobal", Granularity::Module) {}
bool runOnModule(Module *M, AnalysisManager &AM) override;
void *getPassID() const override {
return &ID;
}
private:
unsigned calculateTypeSize(Type *type);
void convertAllocaToGlobal(AllocaInst *alloca, Function *F, Module *M);
std::string generateUniqueGlobalName(AllocaInst *alloca, Function *F);
};
} // namespace sysy

View File

@ -0,0 +1,114 @@
#pragma once
#include "Pass.h" // 包含Pass的基类定义
#include "IR.h" // 包含IR相关的定义如Instruction, Function, BasicBlock, AllocaInst, LoadInst, StoreInst, PhiInst等
#include "Dom.h" // 假设支配树分析的头文件,提供 DominatorTreeAnalysisResult
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <stack> // 用于变量重命名阶段的SSA值栈
namespace sysy {
// 前向声明分析结果类,确保在需要时可以引用
class DominatorTree;
// Mem2RegContext 类,封装 mem2reg 遍的核心逻辑和状态
// 这样可以避免静态变量在多线程或多次运行时的冲突,并保持代码的模块化
class Mem2RegContext {
public:
Mem2RegContext(IRBuilder *builder) : builder(builder) {}
// 运行 mem2reg 优化的主要方法
// func: 当前要优化的函数
// tp: 分析管理器,用于获取支配树等分析结果
void run(Function* func, AnalysisManager* tp);
private:
IRBuilder *builder; // IR 构建器,用于插入指令
// 存储所有需要被提升的 AllocaInst
std::vector<AllocaInst*> promotableAllocas;
// 存储每个 AllocaInst 对应的 Phi 指令列表
// 键是 AllocaInst值是该 AllocaInst 在各个基本块中插入的 Phi 指令的列表
// (实际上,一个 AllocaInst 在一个基本块中只会有一个 Phi)
std::unordered_map<AllocaInst*, std::unordered_map<BasicBlock*, PhiInst*>> allocaToPhiMap;
// 存储每个 AllocaInst 对应的当前活跃 SSA 值栈
// 用于在变量重命名阶段追踪每个 AllocaInst 在不同控制流路径上的最新值
std::unordered_map<AllocaInst*, std::stack<Value*>> allocaToValueStackMap;
// 辅助映射,存储每个 AllocaInst 的所有 store 指令
std::unordered_map<AllocaInst*, std::unordered_set<StoreInst*>> allocaToStoresMap;
// 辅助映射,存储每个 AllocaInst 对应的定义基本块(包含 store 指令的块)
std::unordered_map<AllocaInst*, std::unordered_set<BasicBlock*>> allocaToDefBlocksMap;
// 支配树分析结果,用于 Phi 插入和变量重命名
DominatorTree* dt;
// --------------------------------------------------------------------
// 阶段1: 识别可提升的 AllocaInst
// --------------------------------------------------------------------
// 判断一个 AllocaInst 是否可以被提升到寄存器
// alloca: 要检查的 AllocaInst
// 返回值: 如果可以提升,则为 true否则为 false
bool isPromotableAlloca(AllocaInst* alloca);
// 收集所有对给定 AllocaInst 进行存储的 StoreInst
// alloca: 目标 AllocaInst
void collectStores(AllocaInst* alloca);
// --------------------------------------------------------------------
// 阶段2: 插入 Phi 指令 (Phi Insertion)
// --------------------------------------------------------------------
// 为给定的 AllocaInst 插入必要的 Phi 指令
// alloca: 目标 AllocaInst
// defBlocks: 包含对该 AllocaInst 进行 store 操作的基本块集合
void insertPhis(AllocaInst* alloca, const std::unordered_set<BasicBlock*>& defBlocks);
// --------------------------------------------------------------------
// 阶段3: 变量重命名 (Variable Renaming)
// --------------------------------------------------------------------
// 对支配树进行深度优先遍历,重命名变量并替换 load/store 指令
void renameVariables(BasicBlock* currentBB);
// --------------------------------------------------------------------
// 阶段4: 清理
// --------------------------------------------------------------------
// 删除所有原始的 AllocaInst、LoadInst 和 StoreInst
void cleanup();
};
// Mem2Reg 优化遍类,继承自 OptimizationPass
// 粒度为 Function表示它在每个函数上独立运行
class Mem2Reg : public OptimizationPass {
private:
IRBuilder *builder;
public:
// 构造函数
Mem2Reg(IRBuilder *builder) : OptimizationPass("Mem2Reg", Granularity::Function), builder(builder) {}
// 静态成员作为该遍的唯一ID
static void *ID;
// 运行在函数上的优化逻辑
// F: 当前要优化的函数
// AM: 分析管理器,用于获取支配树等分析结果,或使分析结果失效
// 返回值: 如果IR被修改则为true否则为false
bool runOnFunction(Function *F, AnalysisManager& AM) override;
// 声明该遍的分析依赖和失效信息
// analysisDependencies: 该遍运行前需要哪些分析结果
// analysisInvalidations: 该遍运行后会使哪些分析结果失效
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
void *getPassID() const override { return &ID; }
};
} // namespace sysy

View File

@ -0,0 +1,59 @@
#pragma once
#include "IR.h"
#include "IRBuilder.h" // 你的 IR Builder
#include "Liveness.h"
#include "Dom.h"
#include "Pass.h" // 你的 Pass 框架基类
#include <iostream> // 调试用
#include <map> // 用于 Value 到 AllocaInst 的映射
#include <set> // 可能用于其他辅助集合
#include <string>
#include <vector>
namespace sysy {
class Reg2MemContext {
public:
Reg2MemContext(IRBuilder *b) : builder(b) {}
// 运行 Reg2Mem 优化
void run(Function *func);
private:
IRBuilder *builder; // IR 构建器
// 存储 SSA Value 到对应的 AllocaInst 的映射
// 只有那些需要被"溢出"到内存的 SSA 值才会被记录在这里
std::map<Value *, AllocaInst *> valueToAllocaMap;
// 辅助函数:
// 1. 识别并为 SSA Value 分配 AllocaInst
void allocateMemoryForSSAValues(Function *func);
// 2. 将 SSA 值的使用替换为 Load/Store
void insertLoadsAndStores(Function *func);
// 3. 处理 Phi 指令,将其转换为 Load/Store
void rewritePhis(Function *func);
// 4. 清理 (例如,可能删除不再需要的 Phi 指令)
void cleanup(Function *func);
// 判断一个 Value 是否是 AllocaInst 可以为其分配内存的目标
// 通常指非指针类型的Instruction结果和Argument
bool isPromotableToMemory(Value *val);
};
class Reg2Mem : public OptimizationPass {
private:
IRBuilder *builder; ///< IR构建器用于插入指令
public:
static void *ID; ///< Pass的唯一标识符
Reg2Mem(IRBuilder* builder) : OptimizationPass("Reg2Mem", Pass::Granularity::Function), builder(builder) {}
bool runOnFunction(Function *F, AnalysisManager &AM) override;
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
void *getPassID() const override { return &ID; } ///< 获取 Pass ID
};
} // namespace sysy

View File

@ -0,0 +1,139 @@
#pragma once
#include "IR.h"
#include "Pass.h"
#include "SysYIROptUtils.h"
#include <cassert>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <unordered_set>
#include <vector>
#include <variant>
#include <functional>
namespace sysy {
// 定义三值格 (Three-valued Lattice) 的状态
enum class LatticeVal {
Top, // (未知 / 未初始化)
Constant, // c (常量)
Bottom // ⊥ (不确定 / 变化 / 未定义)
};
// 新增枚举来区分常量的实际类型
enum class ValueType {
Integer,
Float,
Unknown // 用于 Top 和 Bottom 状态
};
// 用于表示 SSA 值的具体状态(包含格值和常量值)
struct SSAPValue {
LatticeVal state;
std::variant<int, float> constantVal; // 使用 std::variant 存储 int 或 float
ValueType constant_type; // 记录常量是整数还是浮点数
// 默认构造函数,初始化为 Top
SSAPValue() : state(LatticeVal::Top), constantVal(0), constant_type(ValueType::Unknown) {}
// 构造函数,用于创建 Bottom 状态
SSAPValue(LatticeVal s) : state(s), constantVal(0), constant_type(ValueType::Unknown) {
assert((s == LatticeVal::Top || s == LatticeVal::Bottom) && "SSAPValue(LatticeVal) only for Top/Bottom");
}
// 构造函数,用于创建 int Constant 状态
SSAPValue(int c) : state(LatticeVal::Constant), constantVal(c), constant_type(ValueType::Integer) {}
// 构造函数,用于创建 float Constant 状态
SSAPValue(float c) : state(LatticeVal::Constant), constantVal(c), constant_type(ValueType::Float) {}
// 比较操作符,用于判断状态是否改变
bool operator==(const SSAPValue &other) const {
if (state != other.state)
return false;
if (state == LatticeVal::Constant) {
if (constant_type != other.constant_type) return false; // 类型必须匹配
return constantVal == other.constantVal; // std::variant 会比较内部值
}
return true; // Top == Top, Bottom == Bottom
}
bool operator!=(const SSAPValue &other) const { return !(*this == other); }
};
// SCCP 上下文类,持有每个函数运行时的状态
class SCCPContext {
private:
IRBuilder *builder; // IR 构建器,用于插入指令和创建常量
// 工作列表
// 存储需要重新评估的指令
std::queue<Instruction *> instWorkList;
// 存储需要重新评估的控制流边 (pair: from_block, to_block)
std::queue<std::pair<BasicBlock *, BasicBlock *>> edgeWorkList;
// 格值映射SSA Value 到其当前状态
std::map<Value *, SSAPValue> valueState;
// 可执行基本块集合
std::unordered_set<BasicBlock *> executableBlocks;
// 追踪已访问的CFG边防止重复添加使用 SysYIROptUtils::PairHash
std::unordered_set<std::pair<BasicBlock*, BasicBlock*>, SysYIROptUtils::PairHash> visitedCFGEdges;
// 辅助函数:格操作 Meet
SSAPValue Meet(const SSAPValue &a, const SSAPValue &b);
// 辅助函数:获取值的当前状态,如果不存在则默认为 Top
SSAPValue GetValueState(Value *v);
// 辅助函数:更新值的状态,如果状态改变,将所有用户加入指令工作列表
void UpdateState(Value *v, SSAPValue newState);
// 辅助函数:将边加入边工作列表,并更新可执行块
void AddEdgeToWorkList(BasicBlock *fromBB, BasicBlock *toBB);
// 辅助函数:标记一个块为可执行
void MarkBlockExecutable(BasicBlock* block);
// 辅助函数:对二元操作进行常量折叠
SSAPValue ComputeConstant(BinaryInst *binaryinst, SSAPValue lhsVal, SSAPValue rhsVal);
// 辅助函数:对一元操作进行常量折叠
SSAPValue ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVal);
// 主要优化阶段
// 阶段1: 常量传播与折叠
bool PropagateConstants(Function *func);
// 阶段2: 控制流简化
bool SimplifyControlFlow(Function *func);
// 辅助函数:处理单条指令
void ProcessInstruction(Instruction *inst);
// 辅助函数:处理单条控制流边
void ProcessEdge(const std::pair<BasicBlock *, BasicBlock *> &edge);
// 控制流简化辅助函数
// 查找所有可达的基本块 (基于常量条件)
std::unordered_set<BasicBlock *> FindReachableBlocks(Function *func);
// 移除死块
void RemoveDeadBlock(BasicBlock *bb, Function *func);
// 简化分支(将条件分支替换为无条件分支)
void SimplifyBranch(CondBrInst*brInst, bool condVal); // 保持 BranchInst
// 更新前驱块的终结指令(当一个后继块被移除时)
void UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc);
// 移除 Phi 节点的入边(当其前驱块被移除时)
void RemovePhiIncoming(BasicBlock *phiParentBB, BasicBlock *removedPred);
public:
SCCPContext(IRBuilder *builder) : builder(builder) {}
// 运行 SCCP 优化
void run(Function *func, AnalysisManager &AM);
};
// SCCP 优化遍类,继承自 OptimizationPass
class SCCP : public OptimizationPass {
private:
IRBuilder *builder; // IR 构建器,作为 Pass 的成员,传入 Context
public:
SCCP(IRBuilder *builder) : OptimizationPass("SCCP", Granularity::Function), builder(builder) {}
static void *ID;
bool runOnFunction(Function *F, AnalysisManager &AM) override;
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
void *getPassID() const override { return &ID; }
};
} // namespace sysy

View File

@ -0,0 +1,112 @@
#pragma once
#include "IR.h"
extern int DEBUG;
namespace sysy {
// 优化工具类,包含一些通用的优化方法
// 这些方法可以在不同的优化 pass 中复用
// 例如删除use关系,判断是否是全局变量等
class SysYIROptUtils{
public:
struct PairHash {
template <class T1, class T2>
std::size_t operator () (const std::pair<T1, T2>& p) const {
auto h1 = std::hash<T1>{}(p.first);
auto h2 = std::hash<T2>{}(p.second);
// 简单的组合哈希值,可以更复杂以减少冲突
// 使用 boost::hash_combine 的简化版本
return h1 ^ (h2 << 1);
}
};
static void RemoveUserOperandUses(User *user) {
if (!user) {
return;
}
// 遍历 User 的 operands 列表。
// 由于 operands 是 protected 成员,我们需要一个临时方法来访问它,
// 或者在 User 类中添加一个 friend 声明。
// 假设 User 内部有一个像 getOperands() 这样的公共方法返回 operands 的引用,
// 或者将 SysYIROptUtils 声明为 User 的 friend。
// 为了示例,我将假设可以直接访问 user->operands 或通过一个getter。
// 如果无法直接访问,请在 IR.h 的 User 类中添加:
// public: const std::vector<std::shared_ptr<Use>>& getOperands() const { return operands; }
// 迭代 copies of shared_ptr to avoid issues if removeUse modifies the list
// (though remove should handle it, iterating a copy is safer or reverse iteration).
// Since we'll clear the vector at the end, iterating forward is fine.
for (const auto& use_ptr : user->getOperands()) { // 假设 getOperands() 可用
if (use_ptr) {
Value *val = use_ptr->getValue(); // 获取 Use 指向的 Value (如 AllocaInst)
if (val) {
val->removeUse(use_ptr); // 通知 Value 从其 uses 列表中移除此 Use 关系
}
}
}
}
static void usedelete(Instruction *inst) {
assert(inst && "Instruction to delete cannot be null.");
BasicBlock *parentBlock = inst->getParent();
assert(parentBlock && "Instruction must have a parent BasicBlock to be deleted.");
// 步骤1: 处理所有使用者,将他们从使用 inst 变为使用 UndefinedValue
// 这将清理 inst 作为 Value 时的 uses 列表
if (!inst->getUses().empty()) {
inst->replaceAllUsesWith(UndefinedValue::get(inst->getType()));
}
// 步骤2: 清理 inst 作为 User 时的操作数关系
// 通知 inst 所使用的所有 Value (如 AllocaInst),移除对应的 Use 关系。
// 这里的 inst 实际上是一个 User*,所以可以安全地向下转型。
RemoveUserOperandUses(static_cast<User*>(inst));
// 步骤3: 物理删除指令
// 这会导致 Instruction 对象的 unique_ptr 销毁,从而调用其析构函数链。
parentBlock->removeInst(inst);
}
static BasicBlock::iterator usedelete(BasicBlock::iterator inst_it) {
Instruction *inst_to_delete = inst_it->get();
BasicBlock *parentBlock = inst_to_delete->getParent();
assert(parentBlock && "Instruction must have a parent BasicBlock for iterator deletion.");
// 步骤1: 处理所有使用者
if (!inst_to_delete->getUses().empty()) {
inst_to_delete->replaceAllUsesWith(UndefinedValue::get(inst_to_delete->getType()));
}
// 步骤2: 清理操作数关系
RemoveUserOperandUses(static_cast<User*>(inst_to_delete));
// 步骤3: 物理删除指令并返回下一个迭代器
return parentBlock->removeInst(inst_it);
}
// 判断是否是全局变量
static bool isGlobal(Value *val) {
auto gval = dynamic_cast<GlobalValue *>(val);
return gval != nullptr;
}
// 判断是否是数组
static bool isArr(Value *val) {
auto aval = dynamic_cast<AllocaInst *>(val);
// 如果是 AllocaInst 且通过Type::isArray()判断为数组类型
return aval && aval->getType()->as<PointerType>()->getBaseType()->isArray();
}
// 判断是否是指向数组的指针
static bool isArrPointer(Value *val) {
auto aval = dynamic_cast<AllocaInst *>(val);
// 如果是 AllocaInst 且通过Type::isPointer()判断为指针;
auto baseType = aval->getType()->as<PointerType>()->getBaseType();
// 在sysy中函数的数组参数会退化成指针
// 所以当AllocaInst的basetype是PointerType时一维数组或者是指向ArrayType的PointerType多位数组返回true
return aval && (baseType->isPointer() || baseType->as<PointerType>()->getBaseType()->isArray());
}
};
}// namespace sysy

View File

@ -11,6 +11,8 @@
#include "IR.h"
#include "IRBuilder.h"
extern int DEBUG; // 全局调试标志
namespace sysy {
//前向声明
@ -149,6 +151,9 @@ public:
}
AnalysisPass *analysisPass = static_cast<AnalysisPass *>(basePass.get());
if(DEBUG){
std::cout << "Running Analysis Pass: " << analysisPass->getName() << "\n";
}
// 根据分析遍的粒度处理
switch (analysisPass->getGranularity()) {
case Pass::Granularity::Module: {
@ -274,7 +279,7 @@ private:
IRBuilder *pBuilder;
public:
PassManager() = default;
PassManager() = delete;
~PassManager() = default;
PassManager(Module *module, IRBuilder *builder) : pmodule(module) ,pBuilder(builder), analysisManager(module) {}
@ -292,6 +297,9 @@ public:
AnalysisManager &getAnalysisManager() { return analysisManager; }
void clearPasses();
// 输出pass列表并打印IR信息供观察优化遍效果
void printPasses() const;
};
// ======================================================================

View File

@ -59,6 +59,88 @@ private:
std::unique_ptr<Module> module;
IRBuilder builder;
using ValueOrOperator = std::variant<Value*, int>;
std::vector<ValueOrOperator> BinaryExpStack; ///< 用于存储二元表达式的中缀表达式
std::vector<int> BinaryExpLenStack; ///< 用于存储该层次的二元表达式的长度
// 下面是用于后缀表达式的计算的数据结构
std::vector<ValueOrOperator> BinaryRPNStack; ///< 用于存储二元表达式的后缀表达式
std::vector<int> BinaryOpStack; ///< 用于存储二元表达式中缀表达式转换到后缀表达式的操作符栈
std::vector<Value *> BinaryValueStack; ///< 用于存储后缀表达式计算的操作数栈
// 约定操作符:
// 1: 'ADD', 2: 'SUB', 3: 'MUL', 4: 'DIV', 5: '%', 6: 'PLUS', 7: 'NEG', 8: 'NOT', 9: 'LPAREN', 10: 'RPAREN'
// 这里的操作符是为了方便后缀表达式的计算而设计
// 其中,'ADD', 'SUB', 'MUL', 'DIV', '%'
// 分别对应加法、减法、乘法、除法和取模
// 'PLUS' 和 'NEG' 分别对应一元加法和一元减法
// 'NOT' 对应逻辑非
// 'LPAREN' 和 'RPAREN' 分别对应左括号和右括号
enum BinaryOp {
ADD = 1, SUB = 2, MUL = 3, DIV = 4, MOD = 5, PLUS = 6, NEG = 7, NOT = 8, LPAREN = 9, RPAREN = 10,
};
int getOperatorPrecedence(int op) {
switch (op) {
case MUL: case DIV: case MOD: return 2;
case ADD: case SUB: return 1;
case PLUS: case NEG: case NOT: return 3;
case LPAREN: case RPAREN: return 0; // Parentheses have lowest precedence for stack logic
default: return -1; // Unknown operator
}
};
struct ExpKey {
BinaryOp op; ///< 操作符
Value *left; ///< 左操作数
Value *right; ///< 右操作数
ExpKey(BinaryOp op, Value *left, Value *right) : op(op), left(left), right(right) {}
bool operator<(const ExpKey &other) const {
if (op != other.op)
return op < other.op; ///< 比较操作符
if (left != other.left)
return left < other.left; ///< 比较左操作
return right < other.right; ///< 比较右操作数
} ///< 重载小于运算符用于比较ExpKey
};
struct UnExpKey {
BinaryOp op; ///< 一元操作符
Value *operand; ///< 操作数
UnExpKey(BinaryOp op, Value *operand) : op(op), operand(operand) {}
bool operator<(const UnExpKey &other) const {
if (op != other.op)
return op < other.op; ///< 比较操作符
return operand < other.operand; ///< 比较操作数
} ///< 重载小于运算符用于比较UnExpKey
};
struct GEPKey {
Value *basePointer;
std::vector<Value *> indices;
// 为 std::map 定义比较运算符,使得 GEPKey 可以作为键
bool operator<(const GEPKey &other) const {
if (basePointer != other.basePointer) {
return basePointer < other.basePointer;
}
// 逐个比较索引,确保顺序一致
if (indices.size() != other.indices.size()) {
return indices.size() < other.indices.size();
}
for (size_t i = 0; i < indices.size(); ++i) {
if (indices[i] != other.indices[i]) {
return indices[i] < other.indices[i];
}
}
return false; // 如果 basePointer 和所有索引都相同,则认为相等
}
};
std::map<GEPKey, Value*> availableGEPs; ///< 用于存储 GEP 的缓存
std::map<ExpKey, Value*> availableBinaryExpressions;
std::map<UnExpKey, Value*> availableUnaryExpressions;
std::map<Value*, Value*> availableLoads;
public:
SysYIRGenerator() = default;
@ -97,7 +179,7 @@ public:
std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override;
// std::any visitStmt(SysYParser::StmtContext *ctx) override;
std::any visitAssignStmt(SysYParser::AssignStmtContext *ctx) override;
// std::any visitExpStmt(SysYParser::ExpStmtContext *ctx) override;
std::any visitExpStmt(SysYParser::ExpStmtContext *ctx) override;
// std::any visitBlkStmt(SysYParser::BlkStmtContext *ctx) override;
std::any visitIfStmt(SysYParser::IfStmtContext *ctx) override;
std::any visitWhileStmt(SysYParser::WhileStmtContext *ctx) override;
@ -131,8 +213,22 @@ public:
std::any visitLAndExp(SysYParser::LAndExpContext *ctx) override;
std::any visitLOrExp(SysYParser::LOrExpContext *ctx) override;
// std::any visitConstExp(SysYParser::ConstExpContext *ctx) override;
std::any visitConstExp(SysYParser::ConstExpContext *ctx) override;
bool isRightAssociative(int op);
Value* promoteType(Value* value, Type* targetType);
Value* computeExp(SysYParser::ExpContext *ctx, Type* targetType = nullptr);
Value* computeAddExp(SysYParser::AddExpContext *ctx, Type* targetType = nullptr);
void compute();
// 参数是发生 store 操作的目标地址/变量的 Value*
void invalidateExpressionsOnStore(Value* storedAddress);
// 清除因函数调用而失效的表达式缓存(保守策略)
void invalidateExpressionsOnCall();
// 在进入新的基本块时清空所有表达式缓存
void enterNewBasicBlock();
public:
// 获取GEP指令的地址
Value* getGEPAddressInst(Value* basePointer, const std::vector<Value*>& indices);
@ -141,6 +237,7 @@ public:
unsigned countArrayDimensions(Type* type);
}; // class SysYIRGenerator
} // namespace sysy

View File

@ -15,6 +15,7 @@ public:
public:
void printIR();
void printGlobalVariable();
void printGlobalConstant();
public:
@ -22,6 +23,8 @@ public:
static void printInst(Instruction *pInst);
static void printType(Type *type);
static void printValue(Value *value);
static void printBlock(BasicBlock *block);
static std::string getBlockName(BasicBlock *block);
static std::string getOperandName(Value *operand);
static std::string getTypeString(Type *type);
static std::string getValueName(Value *value);

26
src/midend/CMakeLists.txt Normal file
View File

@ -0,0 +1,26 @@
# src/midend/CMakeLists.txt
add_library(midend_lib STATIC
IR.cpp
SysYIRGenerator.cpp
SysYIRPrinter.cpp
Pass/Pass.cpp
Pass/Analysis/Dom.cpp
Pass/Analysis/Liveness.cpp
Pass/Optimize/DCE.cpp
Pass/Optimize/Mem2Reg.cpp
Pass/Optimize/Reg2Mem.cpp
Pass/Optimize/SysYIRCFGOpt.cpp
Pass/Optimize/SCCP.cpp
Pass/Optimize/BuildCFG.cpp
Pass/Optimize/LargeArrayToGlobal.cpp
)
# 包含中端模块所需的头文件路径
target_include_directories(midend_lib PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../include/midend # 中端顶层头文件
${CMAKE_CURRENT_SOURCE_DIR}/../include/midend/Pass # 增加 Pass 头文件路径
${CMAKE_CURRENT_SOURCE_DIR}/../include/midend/Pass/Analysis # 增加 Pass/Analysis 头文件路径
${CMAKE_CURRENT_SOURCE_DIR}/../include/midend/Pass/Optimize # 增加 Pass/Optimize 头文件路径
${CMAKE_CURRENT_SOURCE_DIR}/../include/frontend # 增加 frontend 头文件路径 (已存在)
${ANTLR_RUNTIME}/runtime/src # ANTLR运行时库头文件
)

1421
src/midend/IR.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,486 @@
#include "Dom.h"
#include <algorithm> // for std::set_intersection, std::reverse
#include <iostream> // for debug output
#include <limits> // for std::numeric_limits
#include <queue>
#include <functional> // for std::function
#include <map>
#include <vector>
#include <set>
namespace sysy {
// ==============================================================
// DominatorTreeAnalysisPass 的静态ID
// ==============================================================
void *DominatorTreeAnalysisPass::ID = (void *)&DominatorTreeAnalysisPass::ID;
// ==============================================================
// DominatorTree 结果类的实现
// ==============================================================
// 构造函数:初始化关联函数,但不进行计算
DominatorTree::DominatorTree(Function *F) : AssociatedFunction(F) {
// 构造时不需要计算,在分析遍运行里计算并填充
}
// Getter 方法 (保持不变)
const std::set<BasicBlock *> *DominatorTree::getDominators(BasicBlock *BB) const {
auto it = Dominators.find(BB);
if (it != Dominators.end()) {
return &(it->second);
}
return nullptr;
}
BasicBlock *DominatorTree::getImmediateDominator(BasicBlock *BB) const {
auto it = IDoms.find(BB);
if (it != IDoms.end()) {
return it->second;
}
return nullptr;
}
const std::set<BasicBlock *> *DominatorTree::getDominanceFrontier(BasicBlock *BB) const {
auto it = DominanceFrontiers.find(BB);
if (it != DominanceFrontiers.end()) {
return &(it->second);
}
return nullptr;
}
const std::set<BasicBlock *> *DominatorTree::getDominatorTreeChildren(BasicBlock *BB) const {
auto it = DominatorTreeChildren.find(BB);
if (it != DominatorTreeChildren.end()) {
return &(it->second);
}
return nullptr;
}
// 辅助函数:打印 BasicBlock 集合 (保持不变)
void printBBSet(const std::string &prefix, const std::set<BasicBlock *> &s) {
if (!DEBUG)
return;
std::cout << prefix << "{";
bool first = true;
for (const auto &bb : s) {
if (!first)
std::cout << ", ";
std::cout << bb->getName();
first = false;
}
std::cout << "}" << std::endl;
}
// 辅助函数:计算逆后序遍历 (RPO) - 保持不变
std::vector<BasicBlock*> DominatorTree::computeReversePostOrder(Function* F) {
std::vector<BasicBlock*> postOrder;
std::set<BasicBlock*> visited;
std::function<void(BasicBlock*)> dfs_rpo =
[&](BasicBlock* bb) {
visited.insert(bb);
for (BasicBlock* succ : bb->getSuccessors()) {
if (visited.find(succ) == visited.end()) {
dfs_rpo(succ);
}
}
postOrder.push_back(bb);
};
dfs_rpo(F->getEntryBlock());
std::reverse(postOrder.begin(), postOrder.end());
if (DEBUG) {
std::cout << "--- Computed RPO: ";
for (BasicBlock* bb : postOrder) {
std::cout << bb->getName() << " ";
}
std::cout << "---" << std::endl;
}
return postOrder;
}
// computeDominators 方法 (保持不变因为它它是独立于IDom算法的)
void DominatorTree::computeDominators(Function *F) {
if (DEBUG)
std::cout << "--- Computing Dominators ---" << std::endl;
BasicBlock *entryBlock = F->getEntryBlock();
std::vector<BasicBlock*> bbs_rpo = computeReversePostOrder(F);
for (BasicBlock *bb : bbs_rpo) {
if (bb == entryBlock) {
Dominators[bb].clear();
Dominators[bb].insert(bb);
if (DEBUG) std::cout << "Init Dominators[" << bb->getName() << "]: {" << bb->getName() << "}" << std::endl;
} else {
Dominators[bb].clear();
for (BasicBlock *all_bb : bbs_rpo) {
Dominators[bb].insert(all_bb);
}
if (DEBUG) {
std::cout << "Init Dominators[" << bb->getName() << "]: ";
printBBSet("", Dominators[bb]);
}
}
}
bool changed = true;
int iteration = 0;
while (changed) {
changed = false;
iteration++;
if (DEBUG) std::cout << "Iteration " << iteration << std::endl;
for (BasicBlock *bb : bbs_rpo) {
if (bb == entryBlock) continue;
std::set<BasicBlock *> newDom;
bool firstPredProcessed = false;
for (BasicBlock *pred : bb->getPredecessors()) {
if(DEBUG){
std::cout << " Processing predecessor: " << pred->getName() << std::endl;
}
if (!firstPredProcessed) {
newDom = Dominators[pred];
firstPredProcessed = true;
} else {
std::set<BasicBlock *> intersection;
std::set_intersection(newDom.begin(), newDom.end(), Dominators[pred].begin(), Dominators[pred].end(),
std::inserter(intersection, intersection.begin()));
newDom = intersection;
}
}
newDom.insert(bb);
if (newDom != Dominators[bb]) {
if (DEBUG) {
std::cout << " Dominators[" << bb->getName() << "] changed from ";
printBBSet("", Dominators[bb]);
std::cout << " to ";
printBBSet("", newDom);
}
Dominators[bb] = newDom;
changed = true;
}
}
}
if (DEBUG)
std::cout << "--- Dominators Computation Finished ---" << std::endl;
}
// ==============================================================
// Lengauer-Tarjan 算法辅助数据结构和函数 (私有成员)
// ==============================================================
// DFS 遍历,填充 dfnum_map, vertex_vec, parent_map
// 对应用户代码的 dfs 函数
void DominatorTree::dfs_lt_helper(BasicBlock* u) {
dfnum_map[u] = df_counter;
if (df_counter >= vertex_vec.size()) { // 动态调整大小
vertex_vec.resize(df_counter + 1);
}
vertex_vec[df_counter] = u;
if (DEBUG) std::cout << " DFS: Visiting " << u->getName() << ", dfnum = " << df_counter << std::endl;
df_counter++;
for (BasicBlock* v : u->getSuccessors()) {
if (dfnum_map.find(v) == dfnum_map.end()) { // 如果 v 未访问过
parent_map[v] = u;
if (DEBUG) std::cout << " DFS: Setting parent[" << v->getName() << "] = " << u->getName() << std::endl;
dfs_lt_helper(v);
}
}
}
// 并查集:找到集合的代表,并进行路径压缩
// 同时更新 label确保 label[i] 总是指向其祖先链中 sdom_map 最小的节点
// 对应用户代码的 find 函数,也包含了 eval 的逻辑
BasicBlock* DominatorTree::evalAndCompress_lt_helper(BasicBlock* i) {
if (DEBUG) std::cout << " Eval: Processing " << i->getName() << std::endl;
// 如果 i 是根 (ancestor_map[i] == nullptr)
if (ancestor_map.find(i) == ancestor_map.end() || ancestor_map[i] == nullptr) {
if (DEBUG) std::cout << " Eval: " << i->getName() << " is root, returning itself." << std::endl;
return i; // 根节点自身就是路径上sdom最小的因为它没有祖先
}
// 如果 i 的祖先不是根,则递归查找并进行路径压缩
BasicBlock* root_ancestor = evalAndCompress_lt_helper(ancestor_map[i]);
// 路径压缩时,根据 sdom_map 比较并更新 label_map
// 确保 label_map[i] 存储的是 i 到 root_ancestor 路径上 sdom_map 最小的节点
// 注意:这里的 ancestor_map[i] 已经被递归调用压缩过一次了所以是root_ancestor的旧路径
// 应该比较的是 label_map[ancestor_map[i]] 和 label_map[i]
if (sdom_map.count(label_map[ancestor_map[i]]) && // 确保 label_map[ancestor_map[i]] 存在 sdom
sdom_map.count(label_map[i]) && // 确保 label_map[i] 存在 sdom
dfnum_map[sdom_map[label_map[ancestor_map[i]]]] < dfnum_map[sdom_map[label_map[i]]]) {
if (DEBUG) std::cout << " Eval: Updating label for " << i->getName() << " from "
<< label_map[i]->getName() << " to " << label_map[ancestor_map[i]]->getName() << std::endl;
label_map[i] = label_map[ancestor_map[i]];
}
ancestor_map[i] = root_ancestor; // 执行路径压缩:将 i 直接指向其所属集合的根
if (DEBUG) std::cout << " Eval: Path compression for " << i->getName() << ", new ancestor = "
<< (root_ancestor ? root_ancestor->getName() : "nullptr") << std::endl;
return label_map[i]; // <-- **将这里改为返回 label_map[i]**
}
// Link 函数:将 v 加入 u 的 DFS 树子树中 (实际上是并查集操作)
// 对应用户代码的 fa[u] = fth[u];
void DominatorTree::link_lt_helper(BasicBlock* u_parent, BasicBlock* v_child) {
ancestor_map[v_child] = u_parent; // 设置并查集父节点
label_map[v_child] = v_child; // 初始化 label 为自身
if (DEBUG) std::cout << " Link: " << v_child->getName() << " linked to " << u_parent->getName() << std::endl;
}
// ==============================================================
// Lengauer-Tarjan 算法实现 computeIDoms
// ==============================================================
void DominatorTree::computeIDoms(Function *F) {
if (DEBUG) std::cout << "--- Computing Immediate Dominators (IDoms) using Lengauer-Tarjan ---" << std::endl;
BasicBlock *entryBlock = F->getEntryBlock();
// 1. 初始化所有 LT 相关的数据结构
dfnum_map.clear();
vertex_vec.clear();
parent_map.clear();
sdom_map.clear();
idom_map.clear();
bucket_map.clear();
ancestor_map.clear();
label_map.clear();
df_counter = 0; // DFS 计数器从 0 开始
// 预分配 vertex_vec 的大小避免频繁resize
vertex_vec.resize(F->getBasicBlocks().size() + 1);
// 在 DFS 遍历之前,先为所有基本块初始化 sdom 和 label
// 这是 Lengauer-Tarjan 算法的要求,确保所有节点在 Phase 2 开始前都在 map 中
for (auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock* bb = bb_ptr.get();
sdom_map[bb] = bb; // sdom(bb) 初始化为 bb 自身
label_map[bb] = bb; // label(bb) 初始化为 bb 自身 (用于 Union-Find 的路径压缩)
}
// 确保入口块也被正确初始化(如果它不在 F->getBasicBlocks() 的正常迭代中)
sdom_map[entryBlock] = entryBlock;
label_map[entryBlock] = entryBlock;
// Phase 1: DFS 遍历并预处理
// 对应用户代码的 dfs(st)
dfs_lt_helper(entryBlock);
idom_map[entryBlock] = nullptr; // 入口块没有即时支配者
if (DEBUG) std::cout << " IDom[" << entryBlock->getName() << "] = nullptr" << std::endl;
if (DEBUG) std::cout << " Sdom[" << entryBlock->getName() << "] = " << entryBlock->getName() << std::endl;
// 初始化并查集的祖先和 label
for (auto const& [bb_key, dfn_val] : dfnum_map) {
ancestor_map[bb_key] = nullptr; // 初始为独立集合的根
label_map[bb_key] = bb_key; // 初始 label 为自身
}
if (DEBUG) {
std::cout << " --- DFS Phase Complete ---" << std::endl;
std::cout << " dfnum_map:" << std::endl;
for (auto const& [bb, dfn] : dfnum_map) {
std::cout << " " << bb->getName() << " -> " << dfn << std::endl;
}
std::cout << " vertex_vec (by dfnum):" << std::endl;
for (size_t k = 0; k < df_counter; ++k) {
if (vertex_vec[k]) std::cout << " [" << k << "] -> " << vertex_vec[k]->getName() << std::endl;
}
std::cout << " parent_map:" << std::endl;
for (auto const& [child, parent] : parent_map) {
std::cout << " " << child->getName() << " -> " << (parent ? parent->getName() : "nullptr") << std::endl;
}
std::cout << " ------------------------" << std::endl;
}
// Phase 2: 计算半支配者 (sdom)
// 对应用户代码的 for (int i = dfc; i >= 2; --i) 循环的上半部分
// 按照 DFS 编号递减的顺序遍历所有节点 (除了 entryBlock它的 DFS 编号是 0)
if (DEBUG) std::cout << "--- Phase 2: Computing Semi-Dominators (sdom) ---" << std::endl;
for (int i = df_counter - 1; i >= 1; --i) { // 从 DFS 编号最大的节点开始,到 1
BasicBlock* w = vertex_vec[i]; // 当前处理的节点
if (DEBUG) std::cout << " Processing node w: " << w->getName() << " (dfnum=" << i << ")" << std::endl;
// 对于 w 的每个前驱 v
for (BasicBlock* v : w->getPredecessors()) {
if (DEBUG) std::cout << " Considering predecessor v: " << v->getName() << std::endl;
// 如果前驱 v 未被 DFS 访问过 (即不在 dfnum_map 中),则跳过
if (dfnum_map.find(v) == dfnum_map.end()) {
if (DEBUG) std::cout << " Predecessor " << v->getName() << " not in DFS tree, skipping." << std::endl;
continue;
}
// 调用 evalAndCompress 来找到 v 在其 DFS 树祖先链上具有最小 sdom 的节点
BasicBlock* u_with_min_sdom_on_path = evalAndCompress_lt_helper(v);
if (DEBUG) std::cout << " Eval(" << v->getName() << ") returned "
<< u_with_min_sdom_on_path->getName() << std::endl;
if (DEBUG && sdom_map.count(u_with_min_sdom_on_path) && sdom_map.count(w)) {
std::cout << " Comparing sdom: dfnum[" << sdom_map[u_with_min_sdom_on_path]->getName() << "] (" << dfnum_map[sdom_map[u_with_min_sdom_on_path]]
<< ") vs dfnum[" << sdom_map[w]->getName() << "] (" << dfnum_map[sdom_map[w]] << ")" << std::endl;
}
// 比较 sdom(u) 和 sdom(w)
if (sdom_map.count(u_with_min_sdom_on_path) && sdom_map.count(w) &&
dfnum_map[sdom_map[u_with_min_sdom_on_path]] < dfnum_map[sdom_map[w]]) {
if (DEBUG) std::cout << " Updating sdom[" << w->getName() << "] from "
<< sdom_map[w]->getName() << " to "
<< sdom_map[u_with_min_sdom_on_path]->getName() << std::endl;
sdom_map[w] = sdom_map[u_with_min_sdom_on_path]; // 更新 sdom(w)
if (DEBUG) std::cout << " Sdom update applied. New sdom[" << w->getName() << "] = " << sdom_map[w]->getName() << std::endl;
}
}
// 将 w 加入 sdom(w) 对应的桶中
bucket_map[sdom_map[w]].push_back(w);
if (DEBUG) std::cout << " Adding " << w->getName() << " to bucket of sdom(" << w->getName() << "): "
<< sdom_map[w]->getName() << std::endl;
// 将 w 的父节点加入并查集 (link 操作)
if (parent_map.count(w) && parent_map[w] != nullptr) {
link_lt_helper(parent_map[w], w);
}
// Phase 3-part 1: 处理 parent[w] 的桶中所有节点,确定部分 idom
if (parent_map.count(w) && parent_map[w] != nullptr) {
BasicBlock* p = parent_map[w]; // p 是 w 的父节点
if (DEBUG) std::cout << " Processing bucket for parent " << p->getName() << std::endl;
// 注意这里需要复制桶的内容因为原始桶在循环中会被clear
std::vector<BasicBlock*> nodes_in_p_bucket_copy = bucket_map[p];
for (BasicBlock* y : nodes_in_p_bucket_copy) {
if (DEBUG) std::cout << " Processing node y from bucket: " << y->getName() << std::endl;
// 找到 y 在其 DFS 树祖先链上具有最小 sdom 的节点
BasicBlock* u = evalAndCompress_lt_helper(y);
if (DEBUG) std::cout << " Eval(" << y->getName() << ") returned " << u->getName() << std::endl;
// 确定 idom(y)
// if sdom(eval(y)) == sdom(parent(w)), then idom(y) = parent(w)
// else idom(y) = eval(y)
if (sdom_map.count(u) && sdom_map.count(p) &&
dfnum_map[sdom_map[u]] < dfnum_map[sdom_map[p]]) {
idom_map[y] = u; // 确定的 idom
if (DEBUG) std::cout << " IDom[" << y->getName() << "] set to " << u->getName() << std::endl;
} else {
idom_map[y] = p; // p 是 y 的 idom
if (DEBUG) std::cout << " IDom[" << y->getName() << "] set to " << p->getName() << std::endl;
}
}
bucket_map[p].clear(); // 清空桶,防止重复处理
if (DEBUG) std::cout << " Cleared bucket for parent " << p->getName() << std::endl;
}
}
// Phase 3-part 2: 最终确定 idom (处理那些 idom != sdom 的节点)
if (DEBUG) std::cout << "--- Phase 3: Finalizing Immediate Dominators (idom) ---" << std::endl;
for (int i = 1; i < df_counter; ++i) { // 从 DFS 编号最小的节点 (除了 entryBlock) 开始
BasicBlock* w = vertex_vec[i];
if (DEBUG) std::cout << " Finalizing node w: " << w->getName() << std::endl;
if (idom_map.count(w) && sdom_map.count(w) && idom_map[w] != sdom_map[w]) {
// idom[w] 的 idom 是其真正的 idom
if (DEBUG) std::cout << " idom[" << w->getName() << "] (" << idom_map[w]->getName()
<< ") != sdom[" << w->getName() << "] (" << sdom_map[w]->getName() << ")" << std::endl;
if (idom_map.count(idom_map[w])) {
idom_map[w] = idom_map[idom_map[w]];
if (DEBUG) std::cout << " Updating idom[" << w->getName() << "] to idom(idom(w)): "
<< idom_map[w]->getName() << std::endl;
} else {
if (DEBUG) std::cout << " Warning: idom(idom(" << w->getName() << ")) not found, leaving idom[" << w->getName() << "] as is." << std::endl;
}
}
if (DEBUG) {
std::cout << " Final IDom[" << w->getName() << "] = " << (idom_map[w] ? idom_map[w]->getName() : "nullptr") << std::endl;
}
}
// 将计算结果从 idom_map 存储到 DominatorTree 的成员变量 IDoms 中
IDoms = idom_map;
if (DEBUG) std::cout << "--- Immediate Dominators Computation Finished ---" << std::endl;
}
// ==============================================================
// computeDominanceFrontiers 和 computeDominatorTreeChildren (保持不变)
// ==============================================================
void DominatorTree::computeDominanceFrontiers(Function *F) {
if (DEBUG)
std::cout << "--- Computing Dominance Frontiers ---" << std::endl;
for (const auto &bb_ptr_X : F->getBasicBlocks()) {
BasicBlock *X = bb_ptr_X.get();
DominanceFrontiers[X].clear();
for (const auto &bb_ptr_Z : F->getBasicBlocks()) {
BasicBlock *Z = bb_ptr_Z.get();
const std::set<BasicBlock *> *domsOfZ = getDominators(Z);
if (!domsOfZ || domsOfZ->find(X) == domsOfZ->end()) { // Z 不被 X 支配
continue;
}
for (BasicBlock *Y : Z->getSuccessors()) {
const std::set<BasicBlock *> *domsOfY = getDominators(Y);
// 如果 Y == X或者 Y 不被 X 严格支配 (即 Y 不被 X 支配)
if (Y == X || (domsOfY && domsOfY->find(X) == domsOfY->end())) {
DominanceFrontiers[X].insert(Y);
}
}
}
if (DEBUG) {
std::cout << " DF(" << X->getName() << "): ";
printBBSet("", DominanceFrontiers[X]);
}
}
if (DEBUG)
std::cout << "--- Dominance Frontiers Computation Finished ---" << std::endl;
}
void DominatorTree::computeDominatorTreeChildren(Function *F) {
if (DEBUG)
std::cout << "--- Computing Dominator Tree Children ---" << std::endl;
// 首先清空,确保重新计算时是空的
for (auto &bb_ptr : F->getBasicBlocks()) {
DominatorTreeChildren[bb_ptr.get()].clear();
}
for (auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *B = bb_ptr.get();
BasicBlock *A = getImmediateDominator(B); // A 是 B 的即时支配者
if (A) { // 如果 B 有即时支配者 A (即 B 不是入口块)
DominatorTreeChildren[A].insert(B);
if (DEBUG) {
std::cout << " " << B->getName() << " is child of " << A->getName() << std::endl;
}
}
}
if (DEBUG)
std::cout << "--- Dominator Tree Children Computation Finished ---" << std::endl;
}
// ==============================================================
// DominatorTreeAnalysisPass 的实现 (保持不变)
// ==============================================================
bool DominatorTreeAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
// 每次运行时清空旧数据,确保重新计算
CurrentDominatorTree = std::make_unique<DominatorTree>(F);
CurrentDominatorTree->computeDominators(F);
CurrentDominatorTree->computeIDoms(F); // 修正后的LT算法
CurrentDominatorTree->computeDominanceFrontiers(F);
CurrentDominatorTree->computeDominatorTreeChildren(F);
return false;
}
std::unique_ptr<AnalysisResultBase> DominatorTreeAnalysisPass::getResult() {
return std::move(CurrentDominatorTree);
}
} // namespace sysy

View File

@ -0,0 +1,79 @@
#include "BuildCFG.h"
#include "Dom.h"
#include "Liveness.h"
#include <iostream>
#include <queue>
#include <set>
namespace sysy {
void *BuildCFG::ID = (void *)&BuildCFG::ID; // 定义唯一的 Pass ID
// 声明Pass的分析使用
void BuildCFG::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
// BuildCFG不依赖其他分析
// analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); // 错误的例子
// BuildCFG会使所有依赖于CFG的分析结果失效所以它必须声明这些失效
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID);
analysisInvalidations.insert(&LivenessAnalysisPass::ID);
}
bool BuildCFG::runOnFunction(Function *F, AnalysisManager &AM) {
if (DEBUG) {
std::cout << "Running BuildCFG pass on function: " << F->getName() << std::endl;
}
bool changed = false;
// 1. 清空所有基本块的前驱和后继列表
for (auto &bb : F->getBasicBlocks()) {
bb->clearPredecessors();
bb->clearSuccessors();
}
// 2. 遍历每个基本块重建CFG
for (auto &bb : F->getBasicBlocks()) {
// 获取基本块的最后一条指令
auto &inst = *bb->terminator();
Instruction *termInst = inst.get();
// 确保基本块有终结指令
if (!termInst) {
continue;
}
// 根据终结指令类型,建立前驱后继关系
if (termInst->isBranch()) {
// 无条件跳转
if (termInst->isUnconditional()) {
auto brInst = dynamic_cast<UncondBrInst *>(termInst);
BasicBlock *succ = dynamic_cast<BasicBlock *>(brInst->getBlock());
assert(succ && "Branch instruction's target must be a BasicBlock");
bb->addSuccessor(succ);
succ->addPredecessor(bb.get());
changed = true;
// 条件跳转
} else if (termInst->isConditional()) {
auto brInst = dynamic_cast<CondBrInst *>(termInst);
BasicBlock *trueSucc = dynamic_cast<BasicBlock *>(brInst->getThenBlock());
BasicBlock *falseSucc = dynamic_cast<BasicBlock *>(brInst->getElseBlock());
assert(trueSucc && falseSucc && "Branch instruction's targets must be BasicBlocks");
bb->addSuccessor(trueSucc);
trueSucc->addPredecessor(bb.get());
bb->addSuccessor(falseSucc);
falseSucc->addPredecessor(bb.get());
changed = true;
}
} else if (auto retInst = dynamic_cast<ReturnInst *>(termInst)) {
// RetInst没有后继无需处理
// ...
}
}
return changed;
}
} // namespace sysy

View File

@ -51,10 +51,8 @@ void DCEContext::run(Function *func, AnalysisManager *AM, bool &changed) {
// 如果指令不在活跃集合中,则删除它。
// 分支和返回指令由 isAlive 处理,并会被保留。
if (alive_insts.count(currentInst) == 0) {
// 删除指令,保留用户风格的 SysYIROptUtils::usedelete 和 erase
instIter = SysYIROptUtils::usedelete(instIter); // 删除后返回下一个迭代器
changed = true; // 标记 IR 已被修改
SysYIROptUtils::usedelete(currentInst);
instIter = basicBlock->getInstructions().erase(instIter); // 删除后返回下一个迭代器
} else {
++instIter; // 指令活跃,移动到下一个
}

View File

@ -0,0 +1,145 @@
#include "../../include/midend/Pass/Optimize/LargeArrayToGlobal.h"
#include "../../IR.h"
#include <unordered_map>
#include <sstream>
#include <string>
namespace sysy {
// Helper function to convert type to string
static std::string typeToString(Type *type) {
if (!type) return "null";
switch (type->getKind()) {
case Type::kInt:
return "int";
case Type::kFloat:
return "float";
case Type::kPointer:
return "ptr";
case Type::kArray: {
auto *arrayType = type->as<ArrayType>();
return "[" + std::to_string(arrayType->getNumElements()) + " x " +
typeToString(arrayType->getElementType()) + "]";
}
default:
return "unknown";
}
}
void *LargeArrayToGlobalPass::ID = &LargeArrayToGlobalPass::ID;
bool LargeArrayToGlobalPass::runOnModule(Module *M, AnalysisManager &AM) {
bool changed = false;
if (!M) {
return false;
}
// Collect all alloca instructions from all functions
std::vector<std::pair<AllocaInst*, Function*>> allocasToConvert;
for (auto &funcPair : M->getFunctions()) {
Function *F = funcPair.second.get();
if (!F || F->getBasicBlocks().begin() == F->getBasicBlocks().end()) {
continue;
}
for (auto &BB : F->getBasicBlocks()) {
for (auto &inst : BB->getInstructions()) {
if (auto *alloca = dynamic_cast<AllocaInst*>(inst.get())) {
Type *allocatedType = alloca->getAllocatedType();
// Calculate the size of the allocated type
unsigned size = calculateTypeSize(allocatedType);
if(DEBUG){
// Debug: print size information
std::cout << "LargeArrayToGlobalPass: Found alloca with size " << size
<< " for type " << typeToString(allocatedType) << std::endl;
}
// Convert arrays of 1KB (1024 bytes) or larger to global variables
if (size >= 1024) {
if(DEBUG)
std::cout << "LargeArrayToGlobalPass: Converting array of size " << size << " to global" << std::endl;
allocasToConvert.emplace_back(alloca, F);
}
}
}
}
}
// Convert the collected alloca instructions to global variables
for (auto [alloca, F] : allocasToConvert) {
convertAllocaToGlobal(alloca, F, M);
changed = true;
}
return changed;
}
unsigned LargeArrayToGlobalPass::calculateTypeSize(Type *type) {
if (!type) return 0;
switch (type->getKind()) {
case Type::kInt:
case Type::kFloat:
return 4;
case Type::kPointer:
return 8;
case Type::kArray: {
auto *arrayType = type->as<ArrayType>();
return arrayType->getNumElements() * calculateTypeSize(arrayType->getElementType());
}
default:
return 0;
}
}
void LargeArrayToGlobalPass::convertAllocaToGlobal(AllocaInst *alloca, Function *F, Module *M) {
Type *allocatedType = alloca->getAllocatedType();
// Create a unique name for the global variable
std::string globalName = generateUniqueGlobalName(alloca, F);
// Create the global variable - GlobalValue expects pointer type
Type *pointerType = Type::getPointerType(allocatedType);
GlobalValue *globalVar = M->createGlobalValue(globalName, pointerType);
if (!globalVar) {
return;
}
// Replace all uses of the alloca with the global variable
alloca->replaceAllUsesWith(globalVar);
// Remove the alloca instruction from its basic block
for (auto &BB : F->getBasicBlocks()) {
auto &instructions = BB->getInstructions();
for (auto it = instructions.begin(); it != instructions.end(); ++it) {
if (it->get() == alloca) {
instructions.erase(it);
break;
}
}
}
}
std::string LargeArrayToGlobalPass::generateUniqueGlobalName(AllocaInst *alloca, Function *F) {
std::string baseName = alloca->getName();
if (baseName.empty()) {
baseName = "array";
}
// Ensure uniqueness by appending function name and counter
static std::unordered_map<std::string, int> nameCounter;
std::string key = F->getName() + "." + baseName;
int counter = nameCounter[key]++;
std::ostringstream oss;
oss << key << "." << counter;
return oss.str();
}
} // namespace sysy

View File

@ -0,0 +1,428 @@
#include "Mem2Reg.h" // 包含 Mem2Reg 遍的头文件
#include "Dom.h" // 包含支配树分析的头文件
#include "Liveness.h"
#include "IR.h" // 包含 IR 相关的定义
#include "SysYIROptUtils.h"
#include <cassert> // 用于断言
#include <iostream> // 用于调试输出
namespace sysy {
void *Mem2Reg::ID = (void *)&Mem2Reg::ID;
void Mem2RegContext::run(Function *func, AnalysisManager *AM) {
if (func->getBasicBlocks().empty()) {
return;
}
// 清空所有状态,确保每次运行都是新的状态
promotableAllocas.clear();
allocaToPhiMap.clear();
allocaToValueStackMap.clear();
allocaToStoresMap.clear();
allocaToDefBlocksMap.clear();
// 获取支配树分析结果
dt = AM->getAnalysisResult<DominatorTree, DominatorTreeAnalysisPass>(func);
assert(dt && "DominatorTreeAnalysisResult not available for Mem2Reg!");
// --------------------------------------------------------------------
// 阶段1: 识别可提升的 AllocaInst 并收集其 Store 指令
// --------------------------------------------------------------------
// 遍历函数入口块?中的所有指令,寻找 AllocaInst
// 必须是要入口块的吗
for (auto &inst : func->getEntryBlock()->getInstructions_Range()) {
Value *allocainst = inst.get();
if (auto alloca = dynamic_cast<AllocaInst *>(allocainst)) {
if (isPromotableAlloca(alloca)) {
promotableAllocas.push_back(alloca);
collectStores(alloca); // 收集所有对该 alloca 的 store
}
}
}
// --------------------------------------------------------------------
// 阶段2: 插入 Phi 指令
// --------------------------------------------------------------------
for (auto alloca : promotableAllocas) {
// 为每个可提升的 alloca 插入 Phi 指令
insertPhis(alloca, allocaToDefBlocksMap[alloca]);
}
// --------------------------------------------------------------------
// 阶段3: 变量重命名
// --------------------------------------------------------------------
// 为每个可提升的 alloca 初始化其值栈
for (auto alloca : promotableAllocas) {
// 初始值通常是 undef 或 null取决于 IR 类型系统
UndefinedValue *undefValue = UndefinedValue::get(alloca->getType()->as<PointerType>()->getBaseType());
allocaToValueStackMap[alloca].push(undefValue); // 压入一个初始的“未定义”值
}
// 从入口基本块开始,对支配树进行 DFS 遍历,进行变量重命名
renameVariables(func->getEntryBlock()); // 第一个参数 alloca 在这里不使用,因为是递归入口点
// --------------------------------------------------------------------
// 阶段4: 清理
// --------------------------------------------------------------------
cleanup();
}
// 判断一个 AllocaInst 是否可以被提升到寄存器
bool Mem2RegContext::isPromotableAlloca(AllocaInst *alloca) {
// 1. 必须是标量类型非数组、非结构体sysy不支持结构体
if (alloca->getType()->as<PointerType>()->getBaseType()->isArray()) {
return false;
}
// 2. 其所有用途都必须是 LoadInst 或 StoreInst
// (或 GetElementPtrInst但 GEP 的结果也必须只被 Load/Store 使用)
for (auto use : alloca->getUses()) {
auto user = use->getUser();
if (!user)
return false; // 用户无效
if (dynamic_cast<LoadInst *>(user)) {
// OK
} else if (dynamic_cast<StoreInst *>(user)) {
// OK
} else if (auto gep = dynamic_cast<GetElementPtrInst *>(user)) {
// 如果是 GetElementPtrInst (GEP)
// 需要判断这个 GEP 是否代表了数组元素的访问,而非简单的指针操作
// LLVM 的 mem2reg 通常不提升用于数组元素访问的 alloca。
// 启发式判断:
// 如果 GEP 有多个索引(例如 `getelementptr i32, i32* %ptr, i32 0, i32 %idx`
// 或者第一个索引(对于指针类型)不是常量 0则很可能是数组访问。
// 对于 `alloca i32* %a.param` (对应 `int a[]` 参数),其 `allocatedType()` 是 `i32*`。
// 访问 `a[i]` 会生成类似 `getelementptr i32, i32* %a.param, i32 %i` 的 GEP。
// 这种 GEP 有两个操作数:基指针和索引。
// 检查 GEP 的操作数数量和索引值
// GEP 的操作数通常是:<base_pointer>, <index_1>, <index_2>, ...
// 对于一个 `i32*` 类型的 `alloca`,如果它被 GEP 使用,那么 GEP 的第一个索引通常是 `0`
// (表示解引用指针本身),后续索引才是数组元素的索引。
// 如果 GEP 的操作数数量大于 2 (即 `base_ptr` 和 `index_0` 之外还有其他索引)
// 或者 `index_0` 不是常量 0则它可能是一个复杂的数组访问。
// 假设 `gep->getNumOperands()` 和 `gep->getOperand(idx)->getValue()`
// 假设 `ConstantInt` 类用于表示常量整数值
if (gep->getNumOperands() > 2) { // 如果有超过一个索引(除了基指针的第一个隐式索引)
// std::cerr << "Mem2Reg: Not promotable (GEP with multiple indices): " << alloca->name() << std::endl;
return false; // 复杂 GEP通常表示数组或结构体字段访问
}
if (gep->getNumOperands() == 2) { // 只有基指针和一个索引
Value *firstIndexVal = gep->getOperand(1); // 获取第一个索引值
if (auto constInt = dynamic_cast<ConstantInteger *>(firstIndexVal)) {
if (constInt->getInt() != 0) {
// std::cerr << "Mem2Reg: Not promotable (GEP with non-zero first index): " << alloca->name() << std::endl;
return false; // 索引不是0表示访问数组的非第一个元素
}
} else {
// std::cerr << "Mem2Reg: Not promotable (GEP with non-constant first index): " << alloca->name() <<
// std::endl;
return false; // 索引不是常量,表示动态数组访问
}
}
// 此外GEP 的结果也必须只被 LoadInst 或 StoreInst 使用
for (auto gep_use : gep->getUses()) {
auto gep_user = gep_use->getUser();
if (!gep_user) {
// std::cerr << "Mem2Reg: Not promotable (GEP result null user): " << alloca->name() << std::endl;
return false;
}
if (!dynamic_cast<LoadInst *>(gep_user) && !dynamic_cast<StoreInst *>(gep_user)) {
// std::cerr << "Mem2Reg: Not promotable (GEP result used by non-load/store): " << alloca->name() <<
// std::endl;
return false; // GEP 结果被其他指令使用,地址逃逸或复杂用途
}
}
} else {
// 其他类型的用户,如 CallInst (如果地址逃逸),则不能提升
return false;
}
}
// 3. 不能是 volatile 内存访问 (假设 AllocaInst 有 isVolatile() 方法)
// if (alloca->isVolatile()) return false; // 如果有这样的属性
return true;
}
// 收集所有对给定 AllocaInst 进行存储的 StoreInst
void Mem2RegContext::collectStores(AllocaInst *alloca) {
// 遍历 alloca 的所有用途
for (auto use : alloca->getUses()) {
auto user = use->getUser();
if (!user)
continue;
if (auto storeInst = dynamic_cast<StoreInst *>(user)) {
allocaToStoresMap[alloca].insert(storeInst);
allocaToDefBlocksMap[alloca].insert(storeInst->getParent());
} else if (auto gep = dynamic_cast<GetElementPtrInst *>(user)) {
// 如果是 GEP递归收集其下游的 store
for (auto gep_use : gep->getUses()) {
if (auto gep_store = dynamic_cast<StoreInst *>(gep_use->getUser())) {
allocaToStoresMap[alloca].insert(gep_store);
allocaToDefBlocksMap[alloca].insert(gep_store->getParent());
}
}
}
}
}
// 为给定的 AllocaInst 插入必要的 Phi 指令
void Mem2RegContext::insertPhis(AllocaInst *alloca, const std::unordered_set<BasicBlock *> &defBlocks) {
std::queue<BasicBlock *> workQueue;
std::unordered_set<BasicBlock *> phiHasBeenInserted; // 记录已插入 Phi 的基本块
// 将所有定义块加入工作队列
for (auto bb : defBlocks) {
workQueue.push(bb);
}
while (!workQueue.empty()) {
BasicBlock *currentDefBlock = workQueue.front();
workQueue.pop();
// 遍历当前定义块的支配边界 (Dominance Frontier)
const std::set<BasicBlock *> *frontierBlocks = dt->getDominanceFrontier(currentDefBlock);
for (auto frontierBlock : *frontierBlocks) {
// 如果该支配边界块还没有为当前 alloca 插入 Phi 指令
if (phiHasBeenInserted.find(frontierBlock) == phiHasBeenInserted.end()) {
// 在支配边界块的开头插入一个新的 Phi 指令
// Phi 指令的类型与 alloca 的类型指向的类型相同
builder->setPosition(frontierBlock, frontierBlock->begin()); // 设置插入位置为基本块开头
PhiInst *phiInst = builder->createPhiInst(alloca->getAllocatedType(), {}, {}, "");
allocaToPhiMap[alloca][frontierBlock] = phiInst; // 记录 Phi 指令
phiHasBeenInserted.insert(frontierBlock); // 标记已插入 Phi
// 如果这个支配边界块本身也是一个定义块(即使没有 store但插入了 Phi
// 那么它的支配边界也可能需要插入 Phi
// 例如一个xx型的cfg如果在第一个交叉处插入phi节点那么第二个交叉处可能也需要插入phi
workQueue.push(frontierBlock);
}
}
}
}
// 对支配树进行深度优先遍历,重命名变量并替换 load/store 指令
// 移除了 AllocaInst *currentAlloca 参数,因为这个函数是为整个基本块处理所有可提升的 Alloca
void Mem2RegContext::renameVariables(BasicBlock *currentBB) {
// 1. 在函数开始时,记录每个 promotableAlloca 的当前栈深度。
// 这将用于在函数返回时精确地回溯栈状态。
std::map<AllocaInst *, size_t> originalStackSizes;
for (auto alloca : promotableAllocas) {
originalStackSizes[alloca] = allocaToValueStackMap[alloca].size();
}
// --------------------------------------------------------------------
// 处理当前基本块的指令
// --------------------------------------------------------------------
for (auto instIter = currentBB->getInstructions().begin(); instIter != currentBB->getInstructions().end();) {
Instruction *inst = instIter->get();
bool instDeleted = false;
// 处理 Phi 指令 (如果是当前 alloca 的 Phi)
if (auto phiInst = dynamic_cast<PhiInst *>(inst)) {
// 检查这个 Phi 是否是为某个可提升的 alloca 插入的
for (auto alloca : promotableAllocas) {
if (allocaToPhiMap[alloca].count(currentBB) && allocaToPhiMap[alloca][currentBB] == phiInst) {
// 为 Phi 指令的输出创建一个新的 SSA 值,并压入值栈
allocaToValueStackMap[alloca].push(phiInst);
if (DEBUG) {
std::cout << "Mem2Reg: Pushed Phi " << (phiInst->getName().empty() ? "anonymous" : phiInst->getName()) << " for alloca " << alloca->getName()
<< ". Stack size: " << allocaToValueStackMap[alloca].size() << std::endl;
}
break; // 找到对应的 alloca处理下一个指令
}
}
}
// 处理 LoadInst
else if (auto loadInst = dynamic_cast<LoadInst *>(inst)) {
for (auto alloca : promotableAllocas) {
// 检查 LoadInst 的指针是否直接是 alloca或者是指向 alloca 的 GEP
Value *ptrOperand = loadInst->getPointer();
if (ptrOperand == alloca || (dynamic_cast<GetElementPtrInst *>(ptrOperand) &&
dynamic_cast<GetElementPtrInst *>(ptrOperand)->getBasePointer() == alloca)) {
assert(!allocaToValueStackMap[alloca].empty() && "Value stack empty for alloca during load replacement!");
if (DEBUG) {
std::cout << "Mem2Reg: Replacing load "
<< (ptrOperand->getName().empty() ? "anonymous" : ptrOperand->getName()) << " with SSA value "
<< (allocaToValueStackMap[alloca].top()->getName().empty()
? "anonymous"
: allocaToValueStackMap[alloca].top()->getName())
<< " for alloca " << alloca->getName() << std::endl;
std::cout << "Mem2Reg: allocaToValueStackMap[" << alloca->getName()
<< "] size: " << allocaToValueStackMap[alloca].size() << std::endl;
}
loadInst->replaceAllUsesWith(allocaToValueStackMap[alloca].top());
instIter = SysYIROptUtils::usedelete(instIter);
instDeleted = true;
break;
}
}
}
// 处理 StoreInst
else if (auto storeInst = dynamic_cast<StoreInst *>(inst)) {
for (auto alloca : promotableAllocas) {
// 检查 StoreInst 的指针是否直接是 alloca或者是指向 alloca 的 GEP
Value *ptrOperand = storeInst->getPointer();
if (ptrOperand == alloca || (dynamic_cast<GetElementPtrInst *>(ptrOperand) &&
dynamic_cast<GetElementPtrInst *>(ptrOperand)->getBasePointer() == alloca)) {
if (DEBUG) {
std::cout << "Mem2Reg: Replacing store to "
<< (ptrOperand->getName().empty() ? "anonymous" : ptrOperand->getName()) << " with SSA value "
<< (storeInst->getValue()->getName().empty() ? "anonymous" : storeInst->getValue()->getName())
<< " for alloca " << alloca->getName() << std::endl;
std::cout << "Mem2Reg: allocaToValueStackMap[" << alloca->getName()
<< "] size before push: " << allocaToValueStackMap[alloca].size() << std::endl;
}
allocaToValueStackMap[alloca].push(storeInst->getValue());
instIter = SysYIROptUtils::usedelete(instIter);
instDeleted = true;
if (DEBUG) {
std::cout << "Mem2Reg: allocaToValueStackMap[" << alloca->getName()
<< "] size after push: " << allocaToValueStackMap[alloca].size() << std::endl;
}
break;
}
}
}
if (!instDeleted) {
++instIter; // 如果指令没有被删除,移动到下一个
}
}
// --------------------------------------------------------------------
// 处理后继基本块的 Phi 指令参数
// --------------------------------------------------------------------
for (auto successorBB : currentBB->getSuccessors()) {
if (!successorBB)
continue;
for (auto alloca : promotableAllocas) {
// 如果后继基本块包含为当前 alloca 插入的 Phi 指令
if (allocaToPhiMap[alloca].count(successorBB)) {
auto phiInst = allocaToPhiMap[alloca][successorBB];
// 为 Phi 指令添加来自当前基本块的参数
// 参数值是当前 alloca 值栈顶部的 SSA 值
assert(!allocaToValueStackMap[alloca].empty() && "Value stack empty for alloca when setting phi operand!");
phiInst->addIncoming(allocaToValueStackMap[alloca].top(), currentBB);
if (DEBUG) {
std::cout << "Mem2Reg: Added incoming arg to Phi "
<< (phiInst->getName().empty() ? "anonymous" : phiInst->getName()) << " from "
<< currentBB->getName() << " with value "
<< (allocaToValueStackMap[alloca].top()->getName().empty()
? "anonymous"
: allocaToValueStackMap[alloca].top()->getName())
<< std::endl;
}
}
}
}
// --------------------------------------------------------------------
// 递归访问支配树的子节点
// --------------------------------------------------------------------
const std::set<BasicBlock *> *dominatedBlocks = dt->getDominatorTreeChildren(currentBB);
if (dominatedBlocks) { // 检查是否存在子节点
if(DEBUG){
std::cout << "Mem2Reg: Processing dominated blocks for " << currentBB->getName() << std::endl;
for (auto dominatedBB : *dominatedBlocks) {
std::cout << "Mem2Reg: Dominated block: " << (dominatedBB ? dominatedBB->getName() : "null") << std::endl;
}
}
for (auto dominatedBB : *dominatedBlocks) {
if (dominatedBB) { // 确保子块有效
if (DEBUG) {
std::cout << "Mem2Reg: Recursively renaming variables in dominated block: " << dominatedBB->getName()
<< std::endl;
}
renameVariables(dominatedBB); // 递归调用,不再传递 currentAlloca
}
}
}
// --------------------------------------------------------------------
// 退出基本块时,弹出在此块中压入值栈的 SSA 值,恢复栈到进入该块时的状态
// --------------------------------------------------------------------
for (auto alloca : promotableAllocas) {
while (allocaToValueStackMap[alloca].size() > originalStackSizes[alloca]) {
if (DEBUG) {
std::cout << "Mem2Reg: Popping value "
<< (allocaToValueStackMap[alloca].top()->getName().empty()
? "anonymous"
: allocaToValueStackMap[alloca].top()->getName())
<< " for alloca " << alloca->getName() << ". Stack size: " << allocaToValueStackMap[alloca].size()
<< " -> " << (allocaToValueStackMap[alloca].size() - 1) << std::endl;
}
allocaToValueStackMap[alloca].pop();
}
}
}
// 删除所有原始的 AllocaInst、LoadInst 和 StoreInst
void Mem2RegContext::cleanup() {
for (auto alloca : promotableAllocas) {
if (alloca && alloca->getParent()) {
// 删除 alloca 指令本身
SysYIROptUtils::usedelete(alloca);
// std::cerr << "Mem2Reg: Deleted alloca " << alloca->name() << std::endl;
}
}
// LoadInst 和 StoreInst 已经在 renameVariables 阶段被删除了
}
// Mem2Reg 遍的 runOnFunction 方法实现
bool Mem2Reg::runOnFunction(Function *F, AnalysisManager &AM) {
// 记录初始的指令数量,用于判断优化是否发生了改变
size_t initial_inst_count = 0;
for (auto &bb : F->getBasicBlocks()) {
initial_inst_count += bb->getInstructions().size();
}
Mem2RegContext ctx(builder);
ctx.run(F, &AM); // 运行 Mem2Reg 优化
// 运行优化后,再次计算指令数量
size_t final_inst_count = 0;
for (auto &bb : F->getBasicBlocks()) {
final_inst_count += bb->getInstructions().size();
}
// 如果指令数量发生变化(通常是减少,因为 load/store 被删除phi 被添加),说明 IR 被修改了
// TODO不保险后续修改为更精确的判断
// 直接在添加和删除指令时维护changed值
bool changed = (initial_inst_count != final_inst_count);
// 如果 IR 被修改,则使相关的分析结果失效
if (changed) {
// Mem2Reg 会显著改变 IR 结构,特别是数据流和控制流(通过 Phi
// 这会使几乎所有数据流分析和部分控制流分析失效。
// AM.invalidateAnalysis(&DominatorTreeAnalysisPass::ID, F); // 支配树可能间接改变(如果基本块被删除)
// AM.invalidateAnalysis(&LivenessAnalysisPass::ID, F); // 活跃性分析肯定失效
// AM.invalidateAnalysis(&LoopInfoAnalysisPass::ID, F); // 循环信息可能失效
// AM.invalidateAnalysis(&SideEffectInfoAnalysisPass::ID); // 副作用分析可能失效(如果 Alloca/Load/Store
// 被替换为寄存器)
// ... 其他数据流分析,如到达定义、可用表达式等,也应失效
}
return changed;
}
// 声明Mem2Reg遍的分析依赖和失效信息
void Mem2Reg::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
// Mem2Reg 强烈依赖于支配树分析来插入 Phi 指令
analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); // 假设 DominatorTreeAnalysisPass 的 ID
// Mem2Reg 会删除 Alloca/Load/Store 指令,插入 Phi 指令,这会大幅改变 IR 结构。
// 因此,它会使许多分析结果失效。
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树可能受影响
analysisInvalidations.insert(&LivenessAnalysisPass::ID); // 活跃性分析肯定失效
// analysisInvalidations.insert(&LoopInfoAnalysisPass::ID); // 循环信息可能失效
// analysisInvalidations.insert(&SideEffectInfoAnalysisPass::ID); // 副作用分析可能失效
// 其他所有依赖于数据流或 IR 结构的分析都可能失效。
}
} // namespace sysy

View File

@ -0,0 +1,288 @@
#include "Reg2Mem.h"
#include "SysYIROptUtils.h"
#include "SysYIRPrinter.h"
extern int DEBUG; // 全局调试标志
namespace sysy {
void *Reg2Mem::ID = (void *)&Reg2Mem::ID;
void Reg2MemContext::run(Function *func) {
if (func->getBasicBlocks().empty()) {
return;
}
// 清空状态,确保每次运行都是新的
valueToAllocaMap.clear();
// 阶段1: 识别并为 SSA Value 分配 AllocaInst
allocateMemoryForSSAValues(func);
// 阶段2: 将 Phi 指令转换为 Load/Store 逻辑 (此阶段需要先于通用 Load/Store 插入)
// 这样做是因为 Phi 指令的特殊性,它需要在前驱块的末尾插入 Store
// 如果先处理通用 Load/Store可能无法正确处理 Phi 的复杂性
rewritePhis(func); // Phi 指令可能在 rewritePhis 中被删除或标记删除
// 阶段3: 将其他 SSA Value 的使用替换为 Load/Store
insertLoadsAndStores(func);
// 阶段4: 清理(删除不再需要的 Phi 指令)
cleanup(func);
}
bool Reg2MemContext::isPromotableToMemory(Value *val) {
// 参数和指令结果是 SSA 值
if(DEBUG){
// if(val->getName() == ""){
// assert(false && "Value name should not be empty in Reg2MemContext::isPromotableToMemory");
// }
// std::cout << "Checking if value is promotable to memory: " << val->getName() << std::endl;
}
// if (dynamic_cast<Argument *>(val) || dynamic_cast<Instruction *>(val)) {
// // 如果值已经是指针类型,则通常不为其分配额外的内存,因为它已经是一个地址。
// // (除非我们想将其值也存储起来,这通常不用于 Reg2Mem
// // // Reg2Mem 关注的是将非指针值从寄存器语义转换为内存语义。
// if (val->getType()->isPointer()) {
// return false;
// }
// return true;
// }
// 1. 如果是 Argument则可以提升到内存
if (dynamic_cast<Argument *>(val)) {
// 参数类型i32, i32* 等)都可以为其分配内存
// 因为它们在 Mem2Reg 逆操作中,被认为是从寄存器分配到内存
return true;
}
if (dynamic_cast<PhiInst *>(val)) {
// Phi 指令的结果也是一个 SSA 值,需要将其转换为 Load/Store
return true;
}
return false;
}
void Reg2MemContext::allocateMemoryForSSAValues(Function *func) {
// AllocaInst 必须在函数的入口基本块中
BasicBlock *entryBlock = func->getEntryBlock();
if (!entryBlock) {
return; // 函数可能没有入口块 (例如声明)
}
// 1. 为函数参数分配内存
builder->setPosition(entryBlock, entryBlock->begin()); // 确保在入口块的开始位置插入
for (auto arg : func->getArguments()) {
// 默认情况下,将所有参数是提升到内存
if (isPromotableToMemory(arg)) {
// 参数的类型就是 AllocaInst 需要分配的类型
AllocaInst *alloca = builder->createAllocaInst(Type::getPointerType(arg->getType()), arg->getName() + ".reg2mem");
// 将参数值 store 到 alloca 中 (这是 Mem2Reg 逆转的关键一步)
valueToAllocaMap[arg] = alloca;
// 确保 alloca 位于入口块的顶部,但在所有参数的 store 指令之前
// 通常 alloca 都在 entry block 的最开始
// 这里我们只是创建,并让 builder 决定插入位置 (通常在当前插入点)
// 如果需要严格控制顺序,可能需要手动 insert 到 instruction list
}
}
// 2. 为指令结果分配内存
// 遍历所有基本块和指令,找出所有需要分配 Alloca 的指令结果
for (auto &bb : func->getBasicBlocks()) {
for (auto &inst : bb->getInstructions_Range()) {
// SysYPrinter::printInst(inst.get());
// 只有有结果的指令才可能需要分配内存
// (例如 BinaryInst, CallInst, LoadInst, PhiInst 等)
// StoreInst, BranchInst, ReturnInst 等没有结果的指令不需要
if (dynamic_cast<AllocaInst*>(inst.get()) || inst.get()->getType()->isVoid()) {
continue;
}
if (isPromotableToMemory(inst.get())) {
// 为指令的结果分配内存
// AllocaInst 应该在入口块,而不是当前指令所在块
// 这里我们只是创建,并稍后调整其位置
// 通常的做法是在循环结束后统一将 alloca 放到 entryBlock 的顶部
AllocaInst *alloca = builder->createAllocaInst(Type::getPointerType(inst.get()->getType()), inst.get()->getName() + ".reg2mem");
valueToAllocaMap[inst.get()] = alloca;
}
}
}
Instruction *firstNonAlloca = nullptr;
for (auto instIter = entryBlock->getInstructions().begin(); instIter != entryBlock->getInstructions().end(); instIter++) {
if (!dynamic_cast<AllocaInst*>(instIter->get())) {
firstNonAlloca = instIter->get();
break;
}
}
if (firstNonAlloca) {
builder->setPosition(entryBlock, entryBlock->findInstIterator(firstNonAlloca));
} else { // 如果 entryBlock 只有 AllocaInst 或为空,则设置到 terminator 前
builder->setPosition(entryBlock, entryBlock->terminator());
}
// 插入所有参数的初始 Store 指令
for (auto arg : func->getArguments()) {
if (valueToAllocaMap.count(arg)) { // 检查是否为其分配了 alloca
builder->createStoreInst(arg, valueToAllocaMap[arg]);
}
}
builder->setPosition(entryBlock, entryBlock->terminator());
}
void Reg2MemContext::rewritePhis(Function *func) {
std::vector<PhiInst *> phisToErase; // 收集要删除的 Phi
// 遍历所有基本块和其中的指令,查找 Phi 指令
for (auto &bb : func->getBasicBlocks()) {
// auto insts = bb->getInstructions(); // 复制一份,因为要修改
for (auto instIter = bb->getInstructions().begin(); instIter != bb->getInstructions().end(); instIter++) {
Instruction *inst = instIter->get();
if (auto phiInst = dynamic_cast<PhiInst *>(inst)) {
// 检查 Phi 指令是否是需要处理的 SSA 值
if (valueToAllocaMap.count(phiInst)) {
AllocaInst *alloca = valueToAllocaMap[phiInst];
// 1. 为 Phi 指令的每个入边,在前驱块的末尾插入 Store 指令
// PhiInst 假设有 getIncomingValues() 和 getIncomingBlocks()
for (unsigned i = 0; i < phiInst->getNumIncomingValues(); ++i) { // 假设 PhiInst 是通过操作数来管理入边的
Value *incomingValue = phiInst->getIncomingValue(i); // 获取入值
BasicBlock *incomingBlock = phiInst->getIncomingBlock(i); // 获取对应的入块
// 在入块的跳转指令之前插入 StoreInst
// 需要找到 incomingBlock 的终结指令 (Terminator Instruction)
// 并将 StoreInst 插入到它前面
if (incomingBlock->terminator()->get()->isTerminator()) {
builder->setPosition(incomingBlock, incomingBlock->terminator());
} else {
// 如果没有终结指令,插入到末尾
builder->setPosition(incomingBlock, incomingBlock->end());
}
builder->createStoreInst(incomingValue, alloca);
}
// 2. 在当前 Phi 所在基本块的开头,插入 Load 指令
// 将 Load 指令插入到 Phi 指令之后,因为 Phi 指令即将被删除
builder->setPosition(bb.get(), bb.get()->findInstIterator(phiInst));
LoadInst *newLoad = builder->createLoadInst(alloca);
// 3. 将 Phi 指令的所有用途替换为新的 Load 指令
phiInst->replaceAllUsesWith(newLoad);
// 标记 Phi 指令待删除
phisToErase.push_back(phiInst);
}
}
}
}
// 实际删除 Phi 指令
for (auto phi : phisToErase) {
if (phi && phi->getParent()) {
SysYIROptUtils::usedelete(phi);
}
}
}
void Reg2MemContext::insertLoadsAndStores(Function *func) {
// 收集所有需要替换的 uses避免在迭代时修改 use 链表
std::vector<std::pair<Use *, LoadInst *>> usesToReplace;
std::vector<Instruction *> instsToStore; // 收集需要插入 Store 的指令
// 遍历所有基本块和指令
for (auto &bb : func->getBasicBlocks()) {
for (auto instIter = bb->getInstructions().begin(); instIter != bb->getInstructions().end(); instIter++) {
Instruction *inst = instIter->get();
// 如果指令有结果且我们为其分配了 alloca (Phi 已在 rewritePhis 处理)
// 并且其类型不是 void
if (!inst->getType()->isVoid() && valueToAllocaMap.count(inst)) {
// 在指令之后插入 Store 指令
// StoreInst 应该插入到当前指令之后
builder->setPosition(bb.get(), bb.get()->findInstIterator(inst));
builder->createStoreInst(inst, valueToAllocaMap[inst]);
}
// 处理指令的操作数:如果操作数是一个 SSA 值,且为其分配了 alloca
// (并且这个操作数不是 Phi Inst 的 incoming value因为 Phi 的 incoming value 已经在 rewritePhis 中处理了)
// 注意Phi Inst 的操作数是特殊的,它们表示来自不同前驱块的值。
// 这里的处理主要是针对非 Phi 指令的操作数。
for (auto use = inst->getUses().begin(); use != inst->getUses().end(); ++use) {
// 如果当前 use 的 Value 是一个 Instruction 或 Argument
Value *operand = use->get()->getValue();
if (isPromotableToMemory(operand) && valueToAllocaMap.count(operand)) {
// 确保这个 operand 不是一个即将被删除的 Phi 指令
// (在 rewritePhis 阶段Phi 已经被处理并可能被标记删除)
// 或者检查 use 的 user 不是 PhiInst
if (dynamic_cast<PhiInst *>(inst)) {
continue; // Phi 的操作数已在 rewritePhis 中处理
}
AllocaInst *alloca = valueToAllocaMap[operand];
// 在使用点之前插入 Load 指令
// LoadInst 应该插入到使用它的指令之前
builder->setPosition(bb.get(), bb.get()->findInstIterator(inst));
LoadInst *newLoad = builder->createLoadInst(alloca);
// 记录要替换的 use
usesToReplace.push_back({use->get(), newLoad});
}
}
}
}
// 执行所有替换操作
for (auto &pair : usesToReplace) {
pair.first->setValue(pair.second); // 替换 use 的 Value
}
}
void Reg2MemContext::cleanup(Function *func) {
// 此时,所有原始的 Phi 指令应该已经被删除。
// 如果有其他需要删除的临时指令,可以在这里处理。
// 通常Reg2Mem 的清理比 Mem2Reg 简单,因为主要是在插入指令。
// 这里可以作为一个占位符,以防未来有其他清理需求。
}
bool Reg2Mem::runOnFunction(Function *F, AnalysisManager &AM) {
// 记录初始指令数量
size_t initial_inst_count = 0;
for (auto &bb : F->getBasicBlocks()) {
initial_inst_count += bb->getInstructions().size();
}
Reg2MemContext ctx(builder); // 假设 builder 是一个全局或可访问的 IRBuilder 实例
ctx.run(F);
// 记录最终指令数量
size_t final_inst_count = 0;
for (auto &bb : F->getBasicBlocks()) {
final_inst_count += bb->getInstructions().size();
}
// TODO: 添加更精确的变化检测逻辑例如在run函数中维护changed状态
bool changed = (initial_inst_count != final_inst_count); // 粗略判断是否改变
if (changed) {
// Reg2Mem 会显著改变 IR 结构,特别是数据流。
// 它会插入大量的 Load/Store 指令,改变 Value 的来源。
// 这会使几乎所有数据流分析失效。
// 例如:
// AM.invalidateAnalysis(&DominatorTreeAnalysisPass::ID, F); // 如果基本块结构改变,可能失效
// AM.invalidateAnalysis(&LivenessAnalysisPass::ID, F); // 活跃性分析肯定失效
// AM.invalidateAnalysis(&DCEPass::ID, F); // 可能产生新的死代码
// ... 其他所有数据流分析
}
return changed;
}
void Reg2Mem::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
// Reg2Mem 通常不需要特定的分析作为依赖,因为它主要是一个转换。
// 但它会使许多分析失效。
analysisInvalidations.insert(&LivenessAnalysisPass::ID); // 例如
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID);
}
} // namespace sysy

View File

@ -0,0 +1,984 @@
#include "SCCP.h"
#include "Dom.h"
#include "Liveness.h"
#include <algorithm>
#include <cassert>
#include <cmath> // For std::fmod, std::fabs
#include <limits> // For std::numeric_limits
namespace sysy {
// Pass ID for SCCP
void *SCCP::ID = (void *)&SCCP::ID;
// SCCPContext methods
SSAPValue SCCPContext::Meet(const SSAPValue &a, const SSAPValue &b) {
if (a.state == LatticeVal::Bottom || b.state == LatticeVal::Bottom) {
return SSAPValue(LatticeVal::Bottom);
}
if (a.state == LatticeVal::Top) {
return b;
}
if (b.state == LatticeVal::Top) {
return a;
}
// Both are constants
if (a.constant_type != b.constant_type) {
return SSAPValue(LatticeVal::Bottom); // 不同类型的常量,结果为 Bottom
}
if (a.constantVal == b.constantVal) {
return a; // 相同常量
}
return SSAPValue(LatticeVal::Bottom); // 相同类型但值不同,结果为 Bottom
}
SSAPValue SCCPContext::GetValueState(Value *v) {
if (auto constVal = dynamic_cast<ConstantValue *>(v)) {
// 特殊处理 UndefinedValue将其视为 Bottom
if (dynamic_cast<UndefinedValue *>(constVal)) {
return SSAPValue(LatticeVal::Bottom);
}
// 处理常规的 ConstantInteger 和 ConstantFloating
if (constVal->getType()->isInt()) {
return SSAPValue(constVal->getInt());
} else if (constVal->getType()->isFloat()) {
return SSAPValue(constVal->getFloat());
} else {
// 对于其他 ConstantValue 类型例如ConstantArray 等),
// 如果它们的具体值不能用于标量常量传播,则保守地视为 Bottom。
return SSAPValue(LatticeVal::Bottom);
}
}
if (valueState.count(v)) {
return valueState[v];
}
return SSAPValue(); // 默认初始化为 Top
}
void SCCPContext::UpdateState(Value *v, SSAPValue newState) {
SSAPValue oldState = GetValueState(v);
if (newState != oldState) {
if (DEBUG) {
std::cout << "Updating state for " << v->getName() << " from (";
if (oldState.state == LatticeVal::Top)
std::cout << "Top";
else if (oldState.state == LatticeVal::Constant) {
if (oldState.constant_type == ValueType::Integer)
std::cout << "Const<int>(" << std::get<int>(oldState.constantVal) << ")";
else
std::cout << "Const<float>(" << std::get<float>(oldState.constantVal) << ")";
} else
std::cout << "Bottom";
std::cout << ") to (";
if (newState.state == LatticeVal::Top)
std::cout << "Top";
else if (newState.state == LatticeVal::Constant) {
if (newState.constant_type == ValueType::Integer)
std::cout << "Const<int>(" << std::get<int>(newState.constantVal) << ")";
else
std::cout << "Const<float>(" << std::get<float>(newState.constantVal) << ")";
} else
std::cout << "Bottom";
std::cout << ")" << std::endl;
}
valueState[v] = newState;
// 如果状态发生变化,将所有使用者添加到指令工作列表
for (auto &use_ptr : v->getUses()) {
if (auto userInst = dynamic_cast<Instruction *>(use_ptr->getUser())) {
instWorkList.push(userInst);
}
}
}
}
void SCCPContext::AddEdgeToWorkList(BasicBlock *fromBB, BasicBlock *toBB) {
// 检查边是否已经访问过,防止重复处理
if (visitedCFGEdges.count({fromBB, toBB})) {
return;
}
visitedCFGEdges.insert({fromBB, toBB});
if (DEBUG) {
std::cout << "Adding edge to worklist: " << fromBB->getName() << " -> " << toBB->getName() << std::endl;
}
edgeWorkList.push({fromBB, toBB});
}
void SCCPContext::MarkBlockExecutable(BasicBlock *block) {
if (executableBlocks.insert(block).second) { // insert 返回 pairsecond 为 true 表示插入成功
if (DEBUG) {
std::cout << "Marking block " << block->getName() << " as executable." << std::endl;
}
// 将新可执行块中的所有指令添加到指令工作列表
for (auto &inst_ptr : block->getInstructions()) {
instWorkList.push(inst_ptr.get());
}
}
}
// 辅助函数:对二元操作进行常量折叠
SSAPValue SCCPContext::ComputeConstant(BinaryInst *binaryInst, SSAPValue lhsVal, SSAPValue rhsVal) {
// 确保操作数是常量
if (lhsVal.state != LatticeVal::Constant || rhsVal.state != LatticeVal::Constant) {
return SSAPValue(LatticeVal::Bottom); // 如果不是常量,则不能折叠
}
// 处理整数运算 (kAdd, kSub, kMul, kDiv, kRem, kICmp*, kAnd, kOr)
if (lhsVal.constant_type == ValueType::Integer && rhsVal.constant_type == ValueType::Integer) {
int lhs = std::get<int>(lhsVal.constantVal);
int rhs = std::get<int>(rhsVal.constantVal);
int result = 0;
switch (binaryInst->getKind()) {
case Instruction::kAdd:
result = lhs + rhs;
break;
case Instruction::kSub:
result = lhs - rhs;
break;
case Instruction::kMul:
result = lhs * rhs;
break;
case Instruction::kDiv:
if (rhs == 0)
return SSAPValue(LatticeVal::Bottom); // 除零
result = lhs / rhs;
break;
case Instruction::kRem:
if (rhs == 0)
return SSAPValue(LatticeVal::Bottom); // 模零
result = lhs % rhs;
break;
case Instruction::kICmpEQ:
result = (lhs == rhs);
break;
case Instruction::kICmpNE:
result = (lhs != rhs);
break;
case Instruction::kICmpLT:
result = (lhs < rhs);
break;
case Instruction::kICmpGT:
result = (lhs > rhs);
break;
case Instruction::kICmpLE:
result = (lhs <= rhs);
break;
case Instruction::kICmpGE:
result = (lhs >= rhs);
break;
case Instruction::kAnd:
result = (lhs && rhs);
break;
case Instruction::kOr:
result = (lhs || rhs);
break;
default:
return SSAPValue(LatticeVal::Bottom); // 未知或不匹配的二元操作
}
return SSAPValue(result);
}
// 处理浮点运算 (kFAdd, kFSub, kFMul, kFDiv, kFCmp*)
else if (lhsVal.constant_type == ValueType::Float && rhsVal.constant_type == ValueType::Float) {
float lhs = std::get<float>(lhsVal.constantVal);
float rhs = std::get<float>(rhsVal.constantVal);
float f_result = 0.0f;
int i_result = 0; // For comparison results
switch (binaryInst->getKind()) {
case Instruction::kFAdd:
f_result = lhs + rhs;
break;
case Instruction::kFSub:
f_result = lhs - rhs;
break;
case Instruction::kFMul:
f_result = lhs * rhs;
break;
case Instruction::kFDiv:
if (rhs == 0.0f)
return SSAPValue(LatticeVal::Bottom); // 除零
f_result = lhs / rhs;
break;
// kRem 不支持浮点数,但如果你的 IR 定义了浮点模运算,需要使用 std::fmod
case Instruction::kFCmpEQ:
i_result = (lhs == rhs);
return SSAPValue(i_result);
case Instruction::kFCmpNE:
i_result = (lhs != rhs);
return SSAPValue(i_result);
case Instruction::kFCmpLT:
i_result = (lhs < rhs);
return SSAPValue(i_result);
case Instruction::kFCmpGT:
i_result = (lhs > rhs);
return SSAPValue(i_result);
case Instruction::kFCmpLE:
i_result = (lhs <= rhs);
return SSAPValue(i_result);
case Instruction::kFCmpGE:
i_result = (lhs >= rhs);
return SSAPValue(i_result);
default:
return SSAPValue(LatticeVal::Bottom); // 未知或不匹配的浮点二元操作
}
return SSAPValue(f_result);
}
return SSAPValue(LatticeVal::Bottom); // 类型不匹配或不支持的类型组合
}
// 辅助函数:对一元操作进行常量折叠
SSAPValue SCCPContext::ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVal) {
if (operandVal.state != LatticeVal::Constant) {
return SSAPValue(LatticeVal::Bottom);
}
if (operandVal.constant_type == ValueType::Integer) {
int val = std::get<int>(operandVal.constantVal);
switch (unaryInst->getKind()) {
case Instruction::kAdd:
return SSAPValue(val);
case Instruction::kNeg:
return SSAPValue(-val);
case Instruction::kNot:
return SSAPValue(!val);
default:
return SSAPValue(LatticeVal::Bottom);
}
} else if (operandVal.constant_type == ValueType::Float) {
float val = std::get<float>(operandVal.constantVal);
switch (unaryInst->getKind()) {
case Instruction::kAdd:
return SSAPValue(val);
case Instruction::kFNeg:
return SSAPValue(-val);
case Instruction::kFNot:
return SSAPValue(static_cast<int>(val == 0.0f)); // 浮点数非0.0f 为真,其他为假
default:
return SSAPValue(LatticeVal::Bottom);
}
}
return SSAPValue(LatticeVal::Bottom);
}
// 辅助函数:处理单条指令
void SCCPContext::ProcessInstruction(Instruction *inst) {
SSAPValue oldState = GetValueState(inst);
SSAPValue newState;
if (!executableBlocks.count(inst->getParent())) {
// 如果指令所在的块不可执行,其值应保持 Top
// 除非它之前已经是 Bottom因为 Bottom 是单调的
if (oldState.state != LatticeVal::Bottom) {
newState = SSAPValue(); // Top
} else {
newState = oldState; // 保持 Bottom
}
UpdateState(inst, newState);
return; // 不处理不可达块中的指令的实际值
}
if(DEBUG) {
std::cout << "Processing instruction: " << inst->getName() << " in block " << inst->getParent()->getName() << std::endl;
std::cout << "Old state: ";
if (oldState.state == LatticeVal::Top) {
std::cout << "Top";
} else if (oldState.state == LatticeVal::Constant) {
if (oldState.constant_type == ValueType::Integer) {
std::cout << "Const<int>(" << std::get<int>(oldState.constantVal) << ")";
} else {
std::cout << "Const<float>(" << std::get<float>(oldState.constantVal) << ")";
}
} else {
std::cout << "Bottom";
}
}
switch (inst->getKind()) {
case Instruction::kAdd:
case Instruction::kSub:
case Instruction::kMul:
case Instruction::kDiv:
case Instruction::kRem:
case Instruction::kICmpEQ:
case Instruction::kICmpNE:
case Instruction::kICmpLT:
case Instruction::kICmpGT:
case Instruction::kICmpLE:
case Instruction::kICmpGE:
case Instruction::kFAdd:
case Instruction::kFSub:
case Instruction::kFMul:
case Instruction::kFDiv:
case Instruction::kFCmpEQ:
case Instruction::kFCmpNE:
case Instruction::kFCmpLT:
case Instruction::kFCmpGT:
case Instruction::kFCmpLE:
case Instruction::kFCmpGE:
case Instruction::kAnd:
case Instruction::kOr: {
BinaryInst *binaryInst = static_cast<BinaryInst *>(inst);
SSAPValue lhs = GetValueState(binaryInst->getOperand(0));
SSAPValue rhs = GetValueState(binaryInst->getOperand(1));
// 如果任一操作数是 Bottom结果就是 Bottom
if (lhs.state == LatticeVal::Bottom || rhs.state == LatticeVal::Bottom) {
newState = SSAPValue(LatticeVal::Bottom);
} else if (lhs.state == LatticeVal::Top || rhs.state == LatticeVal::Top) {
newState = SSAPValue(); // Top
} else { // 都是常量
newState = ComputeConstant(binaryInst, lhs, rhs);
}
break;
}
case Instruction::kNeg:
case Instruction::kNot:
case Instruction::kFNeg:
case Instruction::kFNot: {
UnaryInst *unaryInst = static_cast<UnaryInst *>(inst);
SSAPValue operand = GetValueState(unaryInst->getOperand());
if (operand.state == LatticeVal::Bottom) {
newState = SSAPValue(LatticeVal::Bottom);
} else if (operand.state == LatticeVal::Top) {
newState = SSAPValue(); // Top
} else { // 是常量
newState = ComputeConstant(unaryInst, operand);
}
break;
}
// 直接处理类型转换指令
case Instruction::kFtoI: {
SSAPValue operand = GetValueState(inst->getOperand(0));
if (operand.state == LatticeVal::Constant && operand.constant_type == ValueType::Float) {
newState = SSAPValue(static_cast<int>(std::get<float>(operand.constantVal)));
} else if (operand.state == LatticeVal::Bottom) {
newState = SSAPValue(LatticeVal::Bottom);
} else { // Top
newState = SSAPValue();
}
break;
}
case Instruction::kItoF: {
SSAPValue operand = GetValueState(inst->getOperand(0));
if (operand.state == LatticeVal::Constant && operand.constant_type == ValueType::Integer) {
newState = SSAPValue(static_cast<float>(std::get<int>(operand.constantVal)));
} else if (operand.state == LatticeVal::Bottom) {
newState = SSAPValue(LatticeVal::Bottom);
} else { // Top
newState = SSAPValue();
}
break;
}
case Instruction::kBitFtoI: {
SSAPValue operand = GetValueState(inst->getOperand(0));
if (operand.state == LatticeVal::Constant && operand.constant_type == ValueType::Float) {
float fval = std::get<float>(operand.constantVal);
newState = SSAPValue(*reinterpret_cast<int *>(&fval));
} else if (operand.state == LatticeVal::Bottom) {
newState = SSAPValue(LatticeVal::Bottom);
} else { // Top
newState = SSAPValue();
}
break;
}
case Instruction::kBitItoF: {
SSAPValue operand = GetValueState(inst->getOperand(0));
if (operand.state == LatticeVal::Constant && operand.constant_type == ValueType::Integer) {
int ival = std::get<int>(operand.constantVal);
newState = SSAPValue(*reinterpret_cast<float *>(&ival));
} else if (operand.state == LatticeVal::Bottom) {
newState = SSAPValue(LatticeVal::Bottom);
} else { // Top
newState = SSAPValue();
}
break;
}
case Instruction::kLoad: {
// 对于 Load 指令,除非我们有特殊的别名分析,否则假定为 Bottom
// 或者如果它加载的是一个已知常量地址的全局常量
Value *ptr = inst->getOperand(0);
if (auto globalVal = dynamic_cast<GlobalValue *>(ptr)) {
// 如果 GlobalValue 有初始化器,并且它是常量,我们可以传播
// 这需要额外的逻辑来检查 globalVal 的初始化器
// 暂时保守地设置为 Bottom
newState = SSAPValue(LatticeVal::Bottom);
} else {
newState = SSAPValue(LatticeVal::Bottom);
}
break;
}
case Instruction::kStore:
// Store 指令不产生值,其 SSAPValue 不重要
newState = SSAPValue(); // 保持 Top
break;
case Instruction::kCall:
// TODO: 处理 Call 指令根据副作用分析可以推断的常量
// 大多数 Call 指令都假定为 Bottom除非是纯函数且所有参数都是常量
newState = SSAPValue(LatticeVal::Bottom);
break;
case Instruction::kGetElementPtr: {
// GEP 指令计算地址,通常其结果值(地址指向的内容)是 Bottom
// 除非所有索引和基指针都是常量,指向一个确定常量值的内存位置
bool all_ops_constant = true;
for (unsigned i = 0; i < inst->getNumOperands(); ++i) {
if (GetValueState(inst->getOperand(i)).state != LatticeVal::Constant) {
all_ops_constant = false;
break;
}
}
// 即使地址是常量,地址处的内容通常不是。所以通常是 Bottom
newState = SSAPValue(LatticeVal::Bottom);
break;
}
case Instruction::kPhi: {
PhiInst *phi = static_cast<PhiInst *>(inst);
if(DEBUG) {
std::cout << "Processing Phi node: " << phi->getName() << std::endl;
}
// 标准SCCP的phi节点处理
// 只考虑可执行前驱,但要保证单调性
SSAPValue currentPhiState = GetValueState(phi);
SSAPValue phiResult = SSAPValue(); // 初始为 Top
bool hasAnyExecutablePred = false;
for (unsigned i = 0; i < phi->getNumIncomingValues(); ++i) {
BasicBlock *incomingBlock = phi->getIncomingBlock(i);
if (executableBlocks.count(incomingBlock)) {
hasAnyExecutablePred = true;
Value *incomingVal = phi->getIncomingValue(i);
SSAPValue incomingState = GetValueState(incomingVal);
if(DEBUG) {
std::cout << " Incoming from block " << incomingBlock->getName()
<< " with value " << incomingVal->getName() << " state: ";
if (incomingState.state == LatticeVal::Top)
std::cout << "Top";
else if (incomingState.state == LatticeVal::Constant) {
if (incomingState.constant_type == ValueType::Integer)
std::cout << "Const<int>(" << std::get<int>(incomingState.constantVal) << ")";
else
std::cout << "Const<float>(" << std::get<float>(incomingState.constantVal) << ")";
} else
std::cout << "Bottom";
std::cout << std::endl;
}
phiResult = Meet(phiResult, incomingState);
if (phiResult.state == LatticeVal::Bottom) {
break; // 提前退出优化
}
}
// 不可执行前驱暂时被忽略
// 这是标准SCCP的做法依赖于单调性保证正确性
}
if (!hasAnyExecutablePred) {
// 没有可执行前驱保持Top状态
newState = SSAPValue();
} else {
// 关键修复:使用严格的单调性
// 确保phi的值只能从Top -> Constant -> Bottom单向变化
if (currentPhiState.state == LatticeVal::Top) {
// 从Top状态可以变为任何计算结果
newState = phiResult;
} else if (currentPhiState.state == LatticeVal::Constant) {
// 从Constant状态只能保持相同常量或变为Bottom
if (phiResult.state == LatticeVal::Constant &&
currentPhiState.constantVal == phiResult.constantVal &&
currentPhiState.constant_type == phiResult.constant_type) {
// 保持相同的常量
newState = currentPhiState;
} else {
// 不同的值必须变为Bottom
newState = SSAPValue(LatticeVal::Bottom);
}
} else {
// 已经是Bottom保持Bottom
newState = currentPhiState;
}
}
break;
}
case Instruction::kAlloca: // 对应 kAlloca
// Alloca 分配内存,返回一个指针,其内容是 Bottom
newState = SSAPValue(LatticeVal::Bottom);
break;
case Instruction::kBr: // 对应 kBr
case Instruction::kCondBr: // 对应 kCondBr
case Instruction::kReturn: // 对应 kReturn
case Instruction::kUnreachable: // 对应 kUnreachable
// 终结符指令不产生值
newState = SSAPValue(); // 保持 Top
break;
case Instruction::kMemset:
// Memset 不产生值,但有副作用,不进行常量传播
newState = SSAPValue(LatticeVal::Bottom);
break;
default:
if (DEBUG) {
std::cout << "Unimplemented instruction kind in SCCP: " << inst->getKind() << std::endl;
}
newState = SSAPValue(LatticeVal::Bottom); // 未知指令保守处理为 Bottom
break;
}
UpdateState(inst, newState);
// 特殊处理终结符指令,影响 CFG 边的可达性
if (inst->isTerminator()) {
if (inst->isBranch()) {
if (inst->isCondBr()) { // 使用 kCondBr
CondBrInst *branchInst = static_cast<CondBrInst *>(inst);
SSAPValue condVal = GetValueState(branchInst->getOperand(0));
if (condVal.state == LatticeVal::Constant) {
bool condition_is_true = false;
if (condVal.constant_type == ValueType::Integer) {
condition_is_true = (std::get<int>(condVal.constantVal) != 0);
} else if (condVal.constant_type == ValueType::Float) {
condition_is_true = (std::get<float>(condVal.constantVal) != 0.0f);
}
if (condition_is_true) {
AddEdgeToWorkList(branchInst->getParent(), branchInst->getThenBlock());
} else {
AddEdgeToWorkList(branchInst->getParent(), branchInst->getElseBlock());
}
} else { // 条件是 Top 或 Bottom两条路径都可能
AddEdgeToWorkList(branchInst->getParent(), branchInst->getThenBlock());
AddEdgeToWorkList(branchInst->getParent(), branchInst->getElseBlock());
}
} else { // 无条件分支 (kBr)
UncondBrInst *branchInst = static_cast<UncondBrInst *>(inst);
AddEdgeToWorkList(branchInst->getParent(), branchInst->getBlock());
}
}
}
if (DEBUG) {
std::cout << "New state: ";
if (newState.state == LatticeVal::Top) {
std::cout << "Top";
} else if (newState.state == LatticeVal::Constant) {
if (newState.constant_type == ValueType::Integer) {
std::cout << "Const<int>(" << std::get<int>(newState.constantVal) << ")";
} else {
std::cout << "Const<float>(" << std::get<float>(newState.constantVal) << ")";
}
} else {
std::cout << "Bottom";
}
std::cout << std::endl;
}
}
// 辅助函数:处理单条控制流边
void SCCPContext::ProcessEdge(const std::pair<BasicBlock *, BasicBlock *> &edge) {
BasicBlock *fromBB = edge.first;
BasicBlock *toBB = edge.second;
// 检查目标块是否已经可执行
bool wasAlreadyExecutable = executableBlocks.count(toBB) > 0;
// 标记目标块为可执行(如果还不是的话)
MarkBlockExecutable(toBB);
// 如果目标块之前就已经可执行那么需要重新处理其中的phi节点
// 因为现在有新的前驱变为可执行phi节点的值可能需要更新
if (wasAlreadyExecutable) {
for (auto &inst_ptr : toBB->getInstructions()) {
if (dynamic_cast<PhiInst *>(inst_ptr.get())) {
instWorkList.push(inst_ptr.get());
}
}
}
// 如果目标块是新变为可执行的MarkBlockExecutable已经添加了所有指令
}
// 阶段1: 常量传播与折叠
bool SCCPContext::PropagateConstants(Function *func) {
bool changed = false;
// 初始化:所有值 Top所有块不可执行
for (auto &bb_ptr : func->getBasicBlocks()) {
executableBlocks.erase(bb_ptr.get());
for (auto &inst_ptr : bb_ptr->getInstructions()) {
valueState[inst_ptr.get()] = SSAPValue(); // Top
}
}
// 初始化函数参数为Bottom因为它们在编译时是未知的
for (auto arg : func->getArguments()) {
valueState[arg] = SSAPValue(LatticeVal::Bottom);
if (DEBUG) {
std::cout << "Initializing function argument " << arg->getName() << " to Bottom" << std::endl;
}
}
// 标记入口块为可执行
if (!func->getBasicBlocks().empty()) {
MarkBlockExecutable(func->getEntryBlock());
}
// 主循环标准的SCCP工作列表算法
// 交替处理边工作列表和指令工作列表直到不动点
while (!instWorkList.empty() || !edgeWorkList.empty()) {
// 处理所有待处理的CFG边
while (!edgeWorkList.empty()) {
ProcessEdge(edgeWorkList.front());
edgeWorkList.pop();
}
// 处理所有待处理的指令
while (!instWorkList.empty()) {
Instruction *inst = instWorkList.front();
instWorkList.pop();
ProcessInstruction(inst);
}
}
// 应用常量替换和死代码消除
std::vector<Instruction *> instsToDelete;
for (auto &bb_ptr : func->getBasicBlocks()) {
BasicBlock *bb = bb_ptr.get();
if (!executableBlocks.count(bb)) {
// 整个块是死块,标记所有指令删除
for (auto &inst_ptr : bb->getInstructions()) {
instsToDelete.push_back(inst_ptr.get());
}
changed = true;
continue;
}
for (auto it = bb->begin(); it != bb->end();) {
Instruction *inst = it->get();
SSAPValue ssaPVal = GetValueState(inst);
if (ssaPVal.state == LatticeVal::Constant) {
ConstantValue *constVal = nullptr;
if (ssaPVal.constant_type == ValueType::Integer) {
constVal = ConstantInteger::get(std::get<int>(ssaPVal.constantVal));
} else if (ssaPVal.constant_type == ValueType::Float) {
constVal = ConstantFloating::get(std::get<float>(ssaPVal.constantVal));
} else {
constVal = UndefinedValue::get(inst->getType()); // 不应发生
}
if (DEBUG) {
std::cout << "Replacing " << inst->getName() << " with constant ";
if (ssaPVal.constant_type == ValueType::Integer)
std::cout << std::get<int>(ssaPVal.constantVal);
else
std::cout << std::get<float>(ssaPVal.constantVal);
std::cout << std::endl;
}
inst->replaceAllUsesWith(constVal);
instsToDelete.push_back(inst);
++it;
changed = true;
} else {
// 如果操作数是常量,直接替换为常量值(常量折叠)
for (unsigned i = 0; i < inst->getNumOperands(); ++i) {
Value *operand = inst->getOperand(i);
SSAPValue opVal = GetValueState(operand);
if (opVal.state == LatticeVal::Constant) {
ConstantValue *constOp = nullptr;
if (opVal.constant_type == ValueType::Integer) {
constOp = ConstantInteger::get(std::get<int>(opVal.constantVal));
} else if (opVal.constant_type == ValueType::Float) {
constOp = ConstantFloating::get(std::get<float>(opVal.constantVal));
} else {
constOp = UndefinedValue::get(operand->getType());
}
if (constOp != operand) {
inst->setOperand(i, constOp);
changed = true;
}
}
}
++it;
}
}
}
// 实际删除指令
// TODO: 删除的逻辑需要考虑修改
for (Instruction *inst : instsToDelete) {
// 在尝试删除之前,先检查指令是否仍然附加到其父基本块。
// 如果它已经没有父块,可能说明它已被其他方式处理或已处于无效状态。
if (inst->getParent() != nullptr) {
// 调用负责完整删除的函数该函数应负责清除uses并将其从父块中移除。
SysYIROptUtils::usedelete(inst);
}
else {
// 指令已不属于任何父块,无需再次删除。
if (DEBUG) {
std::cerr << "Info: Instruction " << inst->getName() << " was already detached or is not in a parent block." << std::endl;
}
}
}
return changed;
}
// 阶段2: 控制流简化
bool SCCPContext::SimplifyControlFlow(Function *func) {
bool changed = false;
// 重新确定可达块,因为 PropagateConstants 可能改变了分支条件
std::unordered_set<BasicBlock *> newReachableBlocks = FindReachableBlocks(func);
// 移除不可达块
std::vector<BasicBlock *> blocksToDelete;
for (auto &bb_ptr : func->getBasicBlocks()) {
if (bb_ptr.get() == func->getEntryBlock())
continue; // 入口块不能删除
if (newReachableBlocks.find(bb_ptr.get()) == newReachableBlocks.end()) {
blocksToDelete.push_back(bb_ptr.get());
changed = true;
}
}
for (BasicBlock *bb : blocksToDelete) {
RemoveDeadBlock(bb, func);
}
// 简化分支指令
for (auto &bb_ptr : func->getBasicBlocks()) {
BasicBlock *bb = bb_ptr.get();
if (!newReachableBlocks.count(bb))
continue; // 只处理可达块
Instruction *terminator = bb->terminator()->get();
if (terminator->isBranch()) {
if (terminator->isCondBr()) { // 检查是否是条件分支 (kCondBr)
CondBrInst *branchInst = static_cast<CondBrInst *>(terminator);
SSAPValue condVal = GetValueState(branchInst->getOperand(0));
if (condVal.state == LatticeVal::Constant) {
bool condition_is_true = false;
if (condVal.constant_type == ValueType::Integer) {
condition_is_true = (std::get<int>(condVal.constantVal) != 0);
} else if (condVal.constant_type == ValueType::Float) {
condition_is_true = (std::get<float>(condVal.constantVal) != 0.0f);
}
SimplifyBranch(branchInst, condition_is_true);
changed = true;
}
}
}
}
return changed;
}
// 查找所有可达的基本块 (基于常量条件)
std::unordered_set<BasicBlock *> SCCPContext::FindReachableBlocks(Function *func) {
std::unordered_set<BasicBlock *> reachable;
std::queue<BasicBlock *> q;
if (func->getEntryBlock()) {
q.push(func->getEntryBlock());
reachable.insert(func->getEntryBlock());
}
while (!q.empty()) {
BasicBlock *currentBB = q.front();
q.pop();
Instruction *terminator = currentBB->terminator()->get();
if (!terminator)
continue;
if (terminator->isBranch()) {
if (terminator->isCondBr()) { // 检查是否是条件分支 (kCondBr)
CondBrInst *branchInst = static_cast<CondBrInst *>(terminator);
SSAPValue condVal = GetValueState(branchInst->getOperand(0));
if (condVal.state == LatticeVal::Constant) {
bool condition_is_true = false;
if (condVal.constant_type == ValueType::Integer) {
condition_is_true = (std::get<int>(condVal.constantVal) != 0);
} else if (condVal.constant_type == ValueType::Float) {
condition_is_true = (std::get<float>(condVal.constantVal) != 0.0f);
}
if (condition_is_true) {
BasicBlock *trueBlock = branchInst->getThenBlock();
if (reachable.find(trueBlock) == reachable.end()) {
reachable.insert(trueBlock);
q.push(trueBlock);
}
} else {
BasicBlock *falseBlock = branchInst->getElseBlock();
if (reachable.find(falseBlock) == reachable.end()) {
reachable.insert(falseBlock);
q.push(falseBlock);
}
}
} else { // 条件是 Top 或 Bottom两条路径都可达
for (auto succ : branchInst->getSuccessors()) {
if (reachable.find(succ) == reachable.end()) {
reachable.insert(succ);
q.push(succ);
}
}
}
} else { // 无条件分支 (kBr)
UncondBrInst *branchInst = static_cast<UncondBrInst *>(terminator);
BasicBlock *targetBlock = branchInst->getBlock();
if (reachable.find(targetBlock) == reachable.end()) {
reachable.insert(targetBlock);
q.push(targetBlock);
}
}
} else if (terminator->isReturn() || terminator->isUnreachable()) {
// ReturnInst 没有后继,不需要处理
// UnreachableInst 也没有后继,不需要处理
}
}
return reachable;
}
// 移除死块
void SCCPContext::RemoveDeadBlock(BasicBlock *bb, Function *func) {
if (DEBUG) {
std::cout << "Removing dead block: " << bb->getName() << std::endl;
}
// 首先更新其所有前驱的终结指令,移除指向死块的边
std::vector<BasicBlock *> preds_to_update;
for (auto &pred : bb->getPredecessors()) {
if (pred != nullptr) { // 检查是否为空指针
preds_to_update.push_back(pred);
}
}
for (BasicBlock *pred : preds_to_update) {
if (executableBlocks.count(pred)) {
UpdateTerminator(pred, bb);
}
}
// 移除其后继的 Phi 节点的入边
std::vector<BasicBlock *> succs_to_update;
for (auto succ : bb->getSuccessors()) {
succs_to_update.push_back(succ);
}
for (BasicBlock *succ : succs_to_update) {
RemovePhiIncoming(succ, bb);
succ->removePredecessor(bb);
}
func->removeBasicBlock(bb); // 从函数中移除基本块
}
// 简化分支(将条件分支替换为无条件分支)
void SCCPContext::SimplifyBranch(CondBrInst *brInst, bool condVal) {
BasicBlock *parentBB = brInst->getParent();
BasicBlock *trueBlock = brInst->getThenBlock();
BasicBlock *falseBlock = brInst->getElseBlock();
if (DEBUG) {
std::cout << "Simplifying branch in " << parentBB->getName() << ": cond is " << (condVal ? "true" : "false")
<< std::endl;
}
builder->setPosition(parentBB, parentBB->findInstIterator(brInst));
if (condVal) { // 条件为真,跳转到真分支
builder->createUncondBrInst(trueBlock); // 插入无条件分支 kBr
SysYIROptUtils::usedelete(brInst); // 移除旧的条件分支指令
parentBB->removeSuccessor(falseBlock);
falseBlock->removePredecessor(parentBB);
RemovePhiIncoming(falseBlock, parentBB);
} else { // 条件为假,跳转到假分支
builder->createUncondBrInst(falseBlock); // 插入无条件分支 kBr
SysYIROptUtils::usedelete(brInst); // 移除旧的条件分支指令
parentBB->removeSuccessor(trueBlock);
trueBlock->removePredecessor(parentBB);
RemovePhiIncoming(trueBlock, parentBB);
}
}
// 更新前驱块的终结指令(当一个后继块被移除时)
void SCCPContext::UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc) {
Instruction *terminator = predBB->terminator()->get();
if (!terminator)
return;
if (terminator->isBranch()) {
if (terminator->isCondBr()) { // 如果是条件分支
CondBrInst *branchInst = static_cast<CondBrInst *>(terminator);
if (branchInst->getThenBlock() == removedSucc) {
if (DEBUG) {
std::cout << "Updating cond br in " << predBB->getName() << ": True block (" << removedSucc->getName()
<< ") removed. Converting to Br to " << branchInst->getElseBlock()->getName() << std::endl;
}
builder->setPosition(predBB, predBB->findInstIterator(branchInst));
builder->createUncondBrInst(branchInst->getElseBlock());
SysYIROptUtils::usedelete(branchInst);
predBB->removeSuccessor(removedSucc);
} else if (branchInst->getElseBlock() == removedSucc) {
if (DEBUG) {
std::cout << "Updating cond br in " << predBB->getName() << ": False block (" << removedSucc->getName()
<< ") removed. Converting to Br to " << branchInst->getThenBlock()->getName() << std::endl;
}
builder->setPosition(predBB, predBB->findInstIterator(branchInst));
builder->createUncondBrInst(branchInst->getThenBlock());
SysYIROptUtils::usedelete(branchInst);
predBB->removeSuccessor(removedSucc);
}
} else { // 无条件分支 (kBr)
UncondBrInst *branchInst = static_cast<UncondBrInst *>(terminator);
if (branchInst->getBlock() == removedSucc) {
if (DEBUG) {
std::cout << "Updating unconditional br in " << predBB->getName() << ": Target block ("
<< removedSucc->getName() << ") removed. Replacing with Unreachable." << std::endl;
}
SysYIROptUtils::usedelete(branchInst);
predBB->removeSuccessor(removedSucc);
builder->setPosition(predBB, predBB->end());
builder->createUnreachableInst();
}
}
}
}
// 移除 Phi 节点的入边(当其前驱块被移除时)
void SCCPContext::RemovePhiIncoming(BasicBlock *phiParentBB, BasicBlock *removedPred) { // 修正 removedPred 类型
std::vector<Instruction *> insts_to_check;
for (auto &inst_ptr : phiParentBB->getInstructions()) {
insts_to_check.push_back(inst_ptr.get());
}
for (Instruction *inst : insts_to_check) {
if (auto phi = dynamic_cast<PhiInst *>(inst)) {
phi->removeIncomingBlock(removedPred);
}
}
}
// 运行 SCCP 优化
void SCCPContext::run(Function *func, AnalysisManager &AM) {
bool changed_constant_propagation = PropagateConstants(func);
bool changed_control_flow = SimplifyControlFlow(func);
// 如果任何一个阶段修改了 IR标记分析结果为失效
if (changed_constant_propagation || changed_control_flow) {
// AM.invalidate(); // 假设有这样的方法来使所有分析结果失效
}
}
// SCCP Pass methods
bool SCCP::runOnFunction(Function *F, AnalysisManager &AM) {
if (DEBUG) {
std::cout << "Running SCCP on function: " << F->getName() << std::endl;
}
SCCPContext context(builder);
context.run(F, AM);
return true;
}
void SCCP::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
// analysisInvalidations.insert(nullptr); // 表示使所有默认分析失效
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树可能受影响
analysisInvalidations.insert(&LivenessAnalysisPass::ID); // 活跃性分析很可能失效
}
} // namespace sysy

View File

@ -0,0 +1,720 @@
#include "SysYIRCFGOpt.h"
#include "SysYIROptUtils.h"
#include <cassert>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <queue> // 引入队列SysYDelNoPreBLock需要
#include <string>
namespace sysy {
// 定义静态ID
void *SysYDelInstAfterBrPass::ID = (void *)&SysYDelInstAfterBrPass::ID;
void *SysYDelEmptyBlockPass::ID = (void *)&SysYDelEmptyBlockPass::ID;
void *SysYDelNoPreBLockPass::ID = (void *)&SysYDelNoPreBLockPass::ID;
void *SysYBlockMergePass::ID = (void *)&SysYBlockMergePass::ID;
void *SysYAddReturnPass::ID = (void *)&SysYAddReturnPass::ID;
void *SysYCondBr2BrPass::ID = (void *)&SysYCondBr2BrPass::ID;
// ======================================================================
// SysYCFGOptUtils: 辅助工具类包含实际的CFG优化逻辑
// ======================================================================
// 删除br后的无用指令
bool SysYCFGOptUtils::SysYDelInstAfterBr(Function *func) {
bool changed = false;
auto basicBlocks = func->getBasicBlocks();
for (auto &basicBlock : basicBlocks) {
bool Branch = false;
auto &instructions = basicBlock->getInstructions();
auto Branchiter = instructions.end();
for (auto iter = instructions.begin(); iter != instructions.end(); ++iter) {
if ((*iter)->isTerminator()) {
Branch = true;
Branchiter = iter;
break;
}
}
if (Branchiter != instructions.end())
++Branchiter;
while (Branchiter != instructions.end()) {
changed = true;
Branchiter = SysYIROptUtils::usedelete(Branchiter); // 删除指令
}
if (Branch) { // 更新前驱后继关系
auto thelastinstinst = basicBlock->terminator();
auto &Successors = basicBlock->getSuccessors();
for (auto iterSucc = Successors.begin(); iterSucc != Successors.end();) {
(*iterSucc)->removePredecessor(basicBlock.get());
basicBlock->removeSuccessor(*iterSucc);
}
if (thelastinstinst->get()->isUnconditional()) {
auto brinst = dynamic_cast<UncondBrInst *>(thelastinstinst->get());
BasicBlock *branchBlock = dynamic_cast<BasicBlock *>(brinst->getBlock());
basicBlock->addSuccessor(branchBlock);
branchBlock->addPredecessor(basicBlock.get());
} else if (thelastinstinst->get()->isConditional()) {
auto brinst = dynamic_cast<CondBrInst *>(thelastinstinst->get());
BasicBlock *thenBlock = dynamic_cast<BasicBlock *>(brinst->getThenBlock());
BasicBlock *elseBlock = dynamic_cast<BasicBlock *>(brinst->getElseBlock());
basicBlock->addSuccessor(thenBlock);
basicBlock->addSuccessor(elseBlock);
thenBlock->addPredecessor(basicBlock.get());
elseBlock->addPredecessor(basicBlock.get());
}
}
}
return changed;
}
// 合并基本块
bool SysYCFGOptUtils::SysYBlockMerge(Function *func) {
bool changed = false;
for (auto blockiter = func->getBasicBlocks().begin(); blockiter != func->getBasicBlocks().end();) {
// 检查当前块是是不是entry块
if( blockiter->get() == func->getEntryBlock() ) {
blockiter++;
continue; // 跳过入口块
}
if (blockiter->get()->getNumSuccessors() == 1) {
// 如果当前块只有一个后继块
// 且后继块只有一个前驱块
// 则将当前块和后继块合并
if (((blockiter->get())->getSuccessors()[0])->getNumPredecessors() == 1) {
// std::cout << "merge block: " << blockiter->get()->getName() << std::endl;
BasicBlock *block = blockiter->get();
BasicBlock *nextBlock = blockiter->get()->getSuccessors()[0];
// auto nextarguments = nextBlock->getArguments();
// 删除block的br指令
if (block->getNumInstructions() != 0) {
auto thelastinstinst = block->terminator();
if (thelastinstinst->get()->isUnconditional()) {
thelastinstinst = SysYIROptUtils::usedelete(thelastinstinst);
} else if (thelastinstinst->get()->isConditional()) {
// 按道理不会走到这个分支
// 如果是条件分支查看then else是否相同
auto brinst = dynamic_cast<CondBrInst *>(thelastinstinst->get());
if (brinst->getThenBlock() == brinst->getElseBlock()) {
thelastinstinst = SysYIROptUtils::usedelete(thelastinstinst);
}
else{
assert(false && "SysYBlockMerge: unexpected conditional branch with different then and else blocks");
}
}
}
// 将后继块的指令移动到当前块
// 并将后继块的父指针改为当前块
for (auto institer = nextBlock->begin(); institer != nextBlock->end();) {
// institer->get()->setParent(block);
// block->getInstructions().emplace_back(institer->release());
// 用usedelete删除会导致use关系被删除我只希望移动指令到当前块
// institer = SysYIROptUtils::usedelete(institer);
// institer = nextBlock->getInstructions().erase(institer);
institer = nextBlock->moveInst(institer, block->getInstructions().end(), block);
}
// 更新前驱后继关系,类似树节点操作
block->removeSuccessor(nextBlock);
nextBlock->removePredecessor(block);
std::list<BasicBlock *> succshoulddel;
for (auto &succ : nextBlock->getSuccessors()) {
block->addSuccessor(succ);
succ->replacePredecessor(nextBlock, block);
succshoulddel.push_back(succ);
}
for (auto del : succshoulddel) {
nextBlock->removeSuccessor(del);
}
func->removeBasicBlock(nextBlock);
changed = true;
} else {
blockiter++;
}
} else {
blockiter++;
}
}
return changed;
}
// 删除无前驱块兼容SSA后的处理
bool SysYCFGOptUtils::SysYDelNoPreBLock(Function *func) {
bool changed = false; // 标记是否有基本块被删除
std::set<BasicBlock *> reachableBlocks; // 用于存储所有可达的基本块
std::queue<BasicBlock *> blockQueue; // BFS 遍历队列
BasicBlock *entryBlock = func->getEntryBlock();
if (entryBlock) { // 确保函数有入口块
reachableBlocks.insert(entryBlock); // 将入口块标记为可达
blockQueue.push(entryBlock); // 入口块入队
}
// 如果没有入口块(比如一个空函数),则没有块是可达的,所有块都将被删除。
while (!blockQueue.empty()) { // BFS 遍历:只要队列不空
BasicBlock *currentBlock = blockQueue.front();
blockQueue.pop(); // 取出当前块
for (auto &succ : currentBlock->getSuccessors()) { // 遍历当前块的所有后继
// 如果后继块不在 reachableBlocks 中(即尚未被访问过)
if (reachableBlocks.find(succ) == reachableBlocks.end()) {
reachableBlocks.insert(succ); // 标记为可达
blockQueue.push(succ); // 入队,以便继续遍历
}
}
}
std::vector<BasicBlock *> blocksToDelete; // 用于存储所有不可达的基本块
for (auto &blockPtr : func->getBasicBlocks()) {
BasicBlock *block = blockPtr.get();
// 如果当前块不在 reachableBlocks 集合中,说明它是不可达的
if (reachableBlocks.find(block) == reachableBlocks.end()) {
blocksToDelete.push_back(block); // 将其加入待删除列表
changed = true; // 只要找到一个不可达块,就说明函数发生了改变
}
}
for (BasicBlock *unreachableBlock : blocksToDelete) {
// 遍历不可达块中的所有指令,并删除它们
for (auto instIter = unreachableBlock->getInstructions().begin();
instIter != unreachableBlock->getInstructions().end();) {
instIter = SysYIROptUtils::usedelete(instIter);
}
}
for (BasicBlock *unreachableBlock : blocksToDelete) {
for (BasicBlock *succBlock : unreachableBlock->getSuccessors()) {
// 只有当后继块自身是可达的(没有被删除)时才需要处理
if (reachableBlocks.count(succBlock)) {
for (auto &phiInstPtr : succBlock->getInstructions()) {
// Phi 指令总是在基本块的开头。一旦遇到非 Phi 指令即可停止。
if (phiInstPtr->getKind() != Instruction::kPhi) {
break;
}
// 将这个 Phi 节点中来自不可达前驱unreachableBlock的输入参数删除
dynamic_cast<PhiInst *>(phiInstPtr.get())->removeIncomingBlock(unreachableBlock);
}
}
}
}
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();) {
BasicBlock *currentBlock = blockIter->get();
// 如果当前块不在可达块集合中,则将其从函数中移除
if (reachableBlocks.find(currentBlock) == reachableBlocks.end()) {
// func->removeBasicBlock 应该返回下一个有效的迭代器
func->removeBasicBlock((blockIter++)->get());
} else {
blockIter++; // 如果可达,则移动到下一个块
}
}
return changed;
}
bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
bool changed = false;
// 步骤 1: 识别并映射所有符合“空块”定义的基本块及其目标后继
// 使用 std::map 来存储 <空块, 空块跳转目标>
// 这样可以处理空块链A -> B -> C如果 B 是空块A 应该跳到 C
std::map<BasicBlock *, BasicBlock *> emptyBlockRedirectMap;
// 为了避免在遍历 func->getBasicBlocks() 时修改它导致迭代器失效,
// 我们先收集所有的基本块。
std::vector<BasicBlock *> allBlocks;
for (auto &blockPtr : func->getBasicBlocks()) {
allBlocks.push_back(blockPtr.get());
}
for (BasicBlock *block : allBlocks) {
// 入口块通常不应该被认为是空块并删除,除非它没有实际指令且只有一个后继,
// 但为了安全起见,通常会跳过入口块的删除。
// 如果入口块是空的,它应该被合并到它的后继,但处理起来更复杂,这里先不处理入口块为空的情况
if (block == func->getEntryBlock()) {
continue;
}
// 检查基本块是否是空的除了Phi指令外只包含一个终止指令 (Terminator)
// 且该终止指令必须是无条件跳转。
// 空块必须只有一个后继才能被简化
if (block->getNumSuccessors() == 1) {
bool hasNonPhiNonTerminator = false;
// 遍历除了最后一个指令之外的指令
for (auto instIter = block->getInstructions().begin(); instIter != block->getInstructions().end();) {
// 如果是终止指令(例如 br, ret且不是最后一个指令则该块有问题
if ((*instIter)->isTerminator() && instIter != block->terminator()) {
hasNonPhiNonTerminator = true;
break;
}
// 如果不是 Phi 指令且不是终止指令
if (!(*instIter)->isPhi() && !(*instIter)->isTerminator()) {
hasNonPhiNonTerminator = true;
break;
}
++instIter;
if (!hasNonPhiNonTerminator &&
instIter == block->getInstructions().end()) { // 如果块中只有 Phi 指令和一个 Terminator
// 确保最后一个指令是无条件跳转
auto lastInst = block->terminator()->get();
if (lastInst && lastInst->isUnconditional()) {
emptyBlockRedirectMap[block] = block->getSuccessors().front();
}
}
}
}
}
// 步骤 2: 遍历 emptyBlockRedirectMap处理空块链
// 确保每个空块都直接重定向到其最终的非空后继块
for (auto const &[emptyBlock, directSucc] : emptyBlockRedirectMap) {
BasicBlock *targetBlock = directSucc;
// 沿着空块链一直找到最终的非空块目标
while (emptyBlockRedirectMap.count(targetBlock)) {
targetBlock = emptyBlockRedirectMap[targetBlock];
}
emptyBlockRedirectMap[emptyBlock] = targetBlock; // 更新映射到最终目标
}
// 步骤 3: 遍历所有基本块,重定向其终止指令,绕过空块
// 注意:这里需要再次遍历所有块,包括可能成为新目标的块
for (BasicBlock *currentBlock : allBlocks) {
// 如果 currentBlock 本身就是个空块,它会通过其前驱的重定向被处理,这里跳过
if (emptyBlockRedirectMap.count(currentBlock)) {
continue;
}
// 获取当前块的最后一个指令(终止指令)
if (currentBlock->getInstructions().empty()) {
// 理论上,除了入口块和可能被合并的空块外,所有块都应该有终止指令
// 如果这里碰到空块,可能是逻辑错误或者需要特殊处理
continue;
}
std::function<Value *(Value *, BasicBlock *)> getUltimateSourceValue = [&](Value *val, BasicBlock *currentDefBlock) -> Value * {
if(!dynamic_cast<Instruction *>(val)) {
// 如果 val 不是指令,直接返回它
return val;
}
Instruction *inst = dynamic_cast<Instruction *>(val);
// 如果定义指令不在任何空块中,它就是最终来源
if (!emptyBlockRedirectMap.count(currentDefBlock)) {
return val;
}
// 如果是 Phi 指令,且它在空块中,则继续追溯其在空块链中前驱的传入值
if (inst->getKind() == Instruction::kPhi) {
PhiInst *phi = dynamic_cast<PhiInst *>(inst);
// 查找哪个前驱是空块链中的上一个块
for (size_t i = 0; i < phi->getNumOperands(); i += 2) {
BasicBlock *incomingBlock = dynamic_cast<BasicBlock *>(phi->getOperand(i + 1));
// 检查 incomingBlock 是否是当前空块的前驱,且也在空块映射中(或就是 P
// 找到在空块链中导致 currentDefBlock 的那个前驱块
if (emptyBlockRedirectMap.count(incomingBlock) || incomingBlock == currentBlock) {
// 递归追溯该传入值
return getUltimateSourceValue(phi->getValfromBlk(incomingBlock), incomingBlock);
}
}
}
// 如果是其他指令或者无法追溯到Phi链则认为它在空块中产生无法安全传播返回null或原值
// 在严格的空块定义下除了Phi和Terminator不应有其他指令产生值。
return val; // Fallback: If not a Phi, or unable to trace, return itself (may be dangling)
};
auto lastInst = currentBlock->getInstructions().back().get();
if (lastInst->isUnconditional()) { // 无条件跳转
UncondBrInst *brInst = dynamic_cast<UncondBrInst *>(lastInst);
BasicBlock *oldTarget = dynamic_cast<BasicBlock *>(brInst->getBlock()); // 原始跳转目标
if (emptyBlockRedirectMap.count(oldTarget)) { // 如果目标是空块
BasicBlock *newTarget = emptyBlockRedirectMap[oldTarget]; // 获取最终目标
// 更新 CFG 关系
currentBlock->removeSuccessor(oldTarget);
oldTarget->removePredecessor(currentBlock);
brInst->replaceOperand(0, newTarget); // 更新跳转指令的操作数
currentBlock->addSuccessor(newTarget);
newTarget->addPredecessor(currentBlock);
changed = true; // 标记发生改变
for (auto &phiInstPtr : newTarget->getInstructions()) {
if (phiInstPtr->getKind() == Instruction::kPhi) {
PhiInst *phiInst = dynamic_cast<PhiInst *>(phiInstPtr.get());
BasicBlock *actualEmptyPredecessorOfS = nullptr;
for (size_t i = 0; i < phiInst->getNumOperands(); i += 2) {
BasicBlock *incomingBlock = dynamic_cast<BasicBlock *>(phiInst->getOperand(i + 1));
if (incomingBlock && emptyBlockRedirectMap.count(incomingBlock) &&
emptyBlockRedirectMap[incomingBlock] == newTarget) {
actualEmptyPredecessorOfS = incomingBlock;
break;
}
}
if (actualEmptyPredecessorOfS) {
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
Value *valueFromEmptyPredecessor = phiInst->getValfromBlk(actualEmptyPredecessorOfS);
// 追溯这个值,找到它在非空块中的最终来源
// currentBlock 是 P
// oldTarget 是 E1 (链的起点)
// actualEmptyPredecessorOfS 是 En (链的终点S 的前驱)
Value *ultimateSourceValue = getUltimateSourceValue(valueFromEmptyPredecessor, actualEmptyPredecessorOfS);
// 替换 Phi 节点的传入块和传入值
if (ultimateSourceValue) { // 确保成功追溯到有效来源
// phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
phiInst->replaceIncomingBlock(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
} else {
assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction");
// 无法追溯到有效来源,这可能是个错误或特殊情况
// 此时可能需要移除该 Phi 项,或者插入一个 undef 值
phiInst->getValfromBlk(actualEmptyPredecessorOfS);
}
}
} else {
break;
}
}
}
} else if (lastInst->getKind() == Instruction::kCondBr) { // 条件跳转
CondBrInst *condBrInst = dynamic_cast<CondBrInst *>(lastInst);
BasicBlock *oldThenTarget = dynamic_cast<BasicBlock *>(condBrInst->getThenBlock());
BasicBlock *oldElseTarget = dynamic_cast<BasicBlock *>(condBrInst->getElseBlock());
bool thenPathChanged = false;
bool elsePathChanged = false;
// 处理 Then 分支
if (emptyBlockRedirectMap.count(oldThenTarget)) {
BasicBlock *newThenTarget = emptyBlockRedirectMap[oldThenTarget];
condBrInst->replaceOperand(1, newThenTarget); // 更新跳转指令操作数
currentBlock->removeSuccessor(oldThenTarget);
oldThenTarget->removePredecessor(currentBlock);
currentBlock->addSuccessor(newThenTarget);
newThenTarget->addPredecessor(currentBlock);
thenPathChanged = true;
changed = true;
// 处理新 Then 目标块中的 Phi 指令
// for (auto &phiInstPtr : newThenTarget->getInstructions()) {
// if (phiInstPtr->getKind() == Instruction::kPhi) {
// dynamic_cast<PhiInst *>(phiInstPtr.get())->delBlk(oldThenTarget);
// } else {
// break;
// }
// }
for (auto &phiInstPtr : newThenTarget->getInstructions()) {
if (phiInstPtr->getKind() == Instruction::kPhi) {
PhiInst *phiInst = dynamic_cast<PhiInst *>(phiInstPtr.get());
BasicBlock *actualEmptyPredecessorOfS = nullptr;
for (size_t i = 0; i < phiInst->getNumOperands(); i += 2) {
BasicBlock *incomingBlock = dynamic_cast<BasicBlock *>(phiInst->getOperand(i + 1));
if (incomingBlock && emptyBlockRedirectMap.count(incomingBlock) &&
emptyBlockRedirectMap[incomingBlock] == newThenTarget) {
actualEmptyPredecessorOfS = incomingBlock;
break;
}
}
if (actualEmptyPredecessorOfS) {
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
Value *valueFromEmptyPredecessor = phiInst->getValfromBlk(actualEmptyPredecessorOfS);
// 追溯这个值,找到它在非空块中的最终来源
// currentBlock 是 P
// oldTarget 是 E1 (链的起点)
// actualEmptyPredecessorOfS 是 En (链的终点S 的前驱)
Value *ultimateSourceValue = getUltimateSourceValue(valueFromEmptyPredecessor, actualEmptyPredecessorOfS);
// 替换 Phi 节点的传入块和传入值
if (ultimateSourceValue) { // 确保成功追溯到有效来源
// phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
phiInst->replaceIncomingBlock(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
} else {
assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction");
// 无法追溯到有效来源,这可能是个错误或特殊情况
// 此时可能需要移除该 Phi 项,或者插入一个 undef 值
phiInst->removeIncomingBlock(actualEmptyPredecessorOfS);
}
}
} else {
break;
}
}
}
// 处理 Else 分支
if (emptyBlockRedirectMap.count(oldElseTarget)) {
BasicBlock *newElseTarget = emptyBlockRedirectMap[oldElseTarget];
condBrInst->replaceOperand(2, newElseTarget); // 更新跳转指令操作数
currentBlock->removeSuccessor(oldElseTarget);
oldElseTarget->removePredecessor(currentBlock);
currentBlock->addSuccessor(newElseTarget);
newElseTarget->addPredecessor(currentBlock);
elsePathChanged = true;
changed = true;
// 处理新 Else 目标块中的 Phi 指令
// for (auto &phiInstPtr : newElseTarget->getInstructions()) {
// if (phiInstPtr->getKind() == Instruction::kPhi) {
// dynamic_cast<PhiInst *>(phiInstPtr.get())->delBlk(oldElseTarget);
// } else {
// break;
// }
// }
for (auto &phiInstPtr : newElseTarget->getInstructions()) {
if (phiInstPtr->getKind() == Instruction::kPhi) {
PhiInst *phiInst = dynamic_cast<PhiInst *>(phiInstPtr.get());
BasicBlock *actualEmptyPredecessorOfS = nullptr;
for (size_t i = 0; i < phiInst->getNumOperands(); i += 2) {
BasicBlock *incomingBlock = dynamic_cast<BasicBlock *>(phiInst->getOperand(i + 1));
if (incomingBlock && emptyBlockRedirectMap.count(incomingBlock) &&
emptyBlockRedirectMap[incomingBlock] == newElseTarget) {
actualEmptyPredecessorOfS = incomingBlock;
break;
}
}
if (actualEmptyPredecessorOfS) {
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
Value *valueFromEmptyPredecessor = phiInst->getValfromBlk(actualEmptyPredecessorOfS);
// 追溯这个值,找到它在非空块中的最终来源
// currentBlock 是 P
// oldTarget 是 E1 (链的起点)
// actualEmptyPredecessorOfS 是 En (链的终点S 的前驱)
Value *ultimateSourceValue = getUltimateSourceValue(valueFromEmptyPredecessor, actualEmptyPredecessorOfS);
// 替换 Phi 节点的传入块和传入值
if (ultimateSourceValue) { // 确保成功追溯到有效来源
// phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
phiInst->replaceIncomingBlock(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
} else {
assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction");
// 无法追溯到有效来源,这可能是个错误或特殊情况
// 此时可能需要移除该 Phi 项,或者插入一个 undef 值
phiInst->removeIncomingBlock(actualEmptyPredecessorOfS);
}
}
} else {
break;
}
}
}
// 额外处理:如果条件跳转的两个分支现在指向同一个块,则可以简化为无条件跳转
if (condBrInst->getThenBlock() == condBrInst->getElseBlock()) {
BasicBlock *commonTarget = dynamic_cast<BasicBlock *>(condBrInst->getThenBlock());
SysYIROptUtils::usedelete(lastInst); // 删除旧的条件跳转指令
pBuilder->setPosition(currentBlock, currentBlock->end());
pBuilder->createUncondBrInst(commonTarget); // 插入新的无条件跳转指令
// 更安全地更新 CFG 关系
std::set<BasicBlock *> currentSuccessors;
currentSuccessors.insert(oldThenTarget);
currentSuccessors.insert(oldElseTarget);
// 移除旧的后继关系
for (BasicBlock *succ : currentSuccessors) {
currentBlock->removeSuccessor(succ);
succ->removePredecessor(currentBlock);
}
// 添加新的后继关系
currentBlock->addSuccessor(commonTarget);
commonTarget->addPredecessor(currentBlock);
changed = true;
}
}
}
// 步骤 4: 真正地删除空基本块
// 注意:只能在所有跳转和 Phi 指令都更新完毕后才能删除这些块
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();) {
BasicBlock *currentBlock = blockIter->get();
if (emptyBlockRedirectMap.count(currentBlock)) { // 如果在空块映射中
// 入口块不应该被删除,即使它符合空块定义,因为函数需要一个入口
if (currentBlock == func->getEntryBlock()) {
++blockIter;
continue;
}
// 在删除块之前,确保其内部指令被正确删除(虽然这类块指令很少)
for (auto instIter = currentBlock->getInstructions().begin();
instIter != currentBlock->getInstructions().end();) {
instIter = SysYIROptUtils::usedelete(instIter);
}
// 移除块
func->removeBasicBlock((blockIter++)->get());
changed = true;
} else {
++blockIter;
}
}
return changed;
}
// 如果函数没有返回指令,则添加一个默认返回指令(主要解决void函数没有返回指令的问题)
bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder *pBuilder) {
bool changed = false;
auto basicBlocks = func->getBasicBlocks();
for (auto &block : basicBlocks) {
if (block->getNumSuccessors() == 0) {
// 如果基本块没有后继块,则添加一个返回指令
if (block->getNumInstructions() == 0) {
pBuilder->setPosition(block.get(), block->end());
pBuilder->createReturnInst();
changed = true; // 标记IR被修改
} else {
auto thelastinst = block->getInstructions().end();
--thelastinst;
if (thelastinst->get()->getKind() != Instruction::kReturn) {
// std::cout << "Warning: Function " << func->getName() << " has no return instruction, adding default
// return." << std::endl;
pBuilder->setPosition(block.get(), block->end());
// TODO: 如果int float函数缺少返回值是否需要报错
if (func->getReturnType()->isInt()) {
pBuilder->createReturnInst(ConstantInteger::get(0));
} else if (func->getReturnType()->isFloat()) {
pBuilder->createReturnInst(ConstantFloating::get(0.0F));
} else {
pBuilder->createReturnInst();
}
changed = true; // 标记IR被修改
}
}
}
}
return changed;
}
// 条件分支转换为无条件分支
// 主要针对已知条件值的分支转换为无条件分支
// 例如 if (cond) { ... } else { ... } 中的 cond 已经
// 确定为 true 或 false 的情况
bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder *pBuilder) {
bool changed = false;
for (auto &basicblock : func->getBasicBlocks()) {
if (basicblock->getNumInstructions() == 0)
continue;
auto thelast = basicblock->terminator();
if (thelast->get()->isConditional()) {
auto condBrInst = dynamic_cast<CondBrInst *>(thelast->get());
ConstantValue *constOperand = dynamic_cast<ConstantValue *>(condBrInst->getCondition());
std::string opname;
int constint = 0;
float constfloat = 0.0F;
bool constint_Use = false;
bool constfloat_Use = false;
if (constOperand != nullptr) {
if (constOperand->isFloat()) {
constfloat = constOperand->getFloat();
constfloat_Use = true;
} else {
constint = constOperand->getInt();
constint_Use = true;
}
}
// 如果可以计算
if (constfloat_Use || constint_Use) {
changed = true;
auto thenBlock = dynamic_cast<BasicBlock *>(condBrInst->getThenBlock());
auto elseBlock = dynamic_cast<BasicBlock *>(condBrInst->getElseBlock());
thelast = SysYIROptUtils::usedelete(thelast);
if ((constfloat_Use && constfloat == 1.0F) || (constint_Use && constint == 1)) {
// cond为true或非0
pBuilder->setPosition(basicblock.get(), basicblock->end());
pBuilder->createUncondBrInst(thenBlock);
// 更新CFG关系
basicblock->removeSuccessor(elseBlock);
elseBlock->removePredecessor(basicblock.get());
// 删除elseBlock的phi指令中对应的basicblock.get()的传入值
for (auto &phiinst : elseBlock->getInstructions()) {
if (phiinst->getKind() != Instruction::kPhi) {
break;
}
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值
dynamic_cast<PhiInst *>(phiinst.get())->removeIncomingBlock(basicblock.get());
}
} else { // cond为false或0
pBuilder->setPosition(basicblock.get(), basicblock->end());
pBuilder->createUncondBrInst(elseBlock);
// 更新CFG关系
basicblock->removeSuccessor(thenBlock);
thenBlock->removePredecessor(basicblock.get());
// 删除thenBlock的phi指令中对应的basicblock.get()的传入值
for (auto &phiinst : thenBlock->getInstructions()) {
if (phiinst->getKind() != Instruction::kPhi) {
break;
}
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值
dynamic_cast<PhiInst *>(phiinst.get())->removeIncomingBlock(basicblock.get());
}
}
}
}
}
return changed;
}
// ======================================================================
// 独立的CFG优化遍的实现
// ======================================================================
bool SysYDelInstAfterBrPass::runOnFunction(Function *F, AnalysisManager &AM) {
return SysYCFGOptUtils::SysYDelInstAfterBr(F);
}
bool SysYDelEmptyBlockPass::runOnFunction(Function *F, AnalysisManager &AM) {
return SysYCFGOptUtils::SysYDelEmptyBlock(F, pBuilder);
}
bool SysYDelNoPreBLockPass::runOnFunction(Function *F, AnalysisManager &AM) {
return SysYCFGOptUtils::SysYDelNoPreBLock(F);
}
bool SysYBlockMergePass::runOnFunction(Function *F, AnalysisManager &AM) {
return SysYCFGOptUtils::SysYBlockMerge(F);
}
bool SysYAddReturnPass::runOnFunction(Function *F, AnalysisManager &AM) {
return SysYCFGOptUtils::SysYAddReturn(F, pBuilder);
}
bool SysYCondBr2BrPass::runOnFunction(Function *F, AnalysisManager &AM) {
return SysYCFGOptUtils::SysYCondBr2Br(F, pBuilder);
}
} // namespace sysy

View File

@ -3,6 +3,11 @@
#include "SysYIRCFGOpt.h"
#include "SysYIRPrinter.h"
#include "DCE.h"
#include "Mem2Reg.h"
#include "Reg2Mem.h"
#include "SCCP.h"
#include "BuildCFG.h"
#include "LargeArrayToGlobal.h"
#include "Pass.h"
#include <iostream>
#include <queue>
@ -32,10 +37,13 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
3. passid
*/
// 注册分析遍
registerAnalysisPass<sysy::DominatorTreeAnalysisPass>();
registerAnalysisPass<sysy::LivenessAnalysisPass>();
registerAnalysisPass<DominatorTreeAnalysisPass>();
registerAnalysisPass<LivenessAnalysisPass>();
// 注册优化遍
registerOptimizationPass<BuildCFG>();
registerOptimizationPass<LargeArrayToGlobalPass>();
registerOptimizationPass<SysYDelInstAfterBrPass>();
registerOptimizationPass<SysYDelNoPreBLockPass>();
registerOptimizationPass<SysYBlockMergePass>();
@ -44,11 +52,27 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
registerOptimizationPass<SysYCondBr2BrPass>(builderIR);
registerOptimizationPass<SysYAddReturnPass>(builderIR);
registerOptimizationPass<DCE>();
registerOptimizationPass<Mem2Reg>(builderIR);
registerOptimizationPass<Reg2Mem>(builderIR);
registerOptimizationPass<SCCP>(builderIR);
if (optLevel >= 1) {
//经过设计安排优化遍的执行顺序以及执行逻辑
if (DEBUG) std::cout << "Applying -O1 optimizations.\n";
if (DEBUG) std::cout << "--- Running custom optimization sequence ---\n";
if(DEBUG) {
std::cout << "=== IR Before CFGOpt Optimizations ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&BuildCFG::ID);
this->addPass(&LargeArrayToGlobalPass::ID);
this->run();
this->clearPasses();
this->addPass(&SysYDelInstAfterBrPass::ID);
this->addPass(&SysYDelNoPreBLockPass::ID);
@ -58,10 +82,53 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
this->addPass(&SysYAddReturnPass::ID);
this->run();
this->clearPasses();
this->addPass(&BuildCFG::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After CFGOpt Optimizations ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&DCE::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After DCE Optimizations ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&Mem2Reg::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After Mem2Reg Optimizations ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&SCCP::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After SCCP Optimizations ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&Reg2Mem::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After Reg2Mem Optimizations ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&BuildCFG::ID);
this->run();
if (DEBUG) std::cout << "--- Custom optimization sequence finished ---\n";
}
@ -76,6 +143,7 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
SysYPrinter printer(moduleIR);
printer.printIR();
}
}
void PassManager::clearPasses() {
@ -152,6 +220,20 @@ bool PassManager::run() {
}
void PassManager::printPasses() const {
std::cout << "Registered Passes:\n";
for (const auto &p : passes) {
std::cout << " - " << p->getName() << " (Granularity: "
<< static_cast<int>(p->getGranularity())
<< ", Kind: " << static_cast<int>(p->getPassKind()) << ")\n";
}
std::cout << "Total Passes: " << passes.size() << "\n";
if (pmodule) {
SysYPrinter printer(pmodule);
std::cout << "Module IR:\n";
printer.printIR();
}
}
template <typename AnalysisPassType> void registerAnalysisPass() {
PassRegistry::getPassRegistry().registerPass(&AnalysisPassType::ID,

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,10 @@
#include "SysYIRPrinter.h"
#include <cassert>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <limits>
#include <sstream>
#include <string>
#include "IR.h" // 确保IR.h包含了ArrayType、GetElementPtrInst等的定义
@ -13,6 +16,7 @@ void SysYPrinter::printIR() {
//TODO: Print target datalayout and triple (minimal required by LLVM)
printGlobalVariable();
printGlobalConstant();
for (const auto &iter : functions) {
if (iter.second->getName() == "main") {
@ -60,16 +64,21 @@ std::string SysYPrinter::getValueName(Value *value) {
} else if (auto constInt = dynamic_cast<ConstantInteger*>(value)) { // 优先匹配具体的常量类型
return std::to_string(constInt->getInt());
} else if (auto constFloat = dynamic_cast<ConstantFloating*>(value)) { // 优先匹配具体的常量类型
return std::to_string(constFloat->getFloat());
std::ostringstream oss;
oss << std::scientific << std::setprecision(std::numeric_limits<float>::max_digits10) << constFloat->getFloat();
return oss.str();
} else if (auto constUndef = dynamic_cast<UndefinedValue*>(value)) { // 如果有Undef类型
return "undef";
} else if (auto constVal = dynamic_cast<ConstantValue*>(value)) { // fallback for generic ConstantValue
// 这里的逻辑可能需要根据你ConstantValue的实际设计调整
// 确保它能处理所有可能的ConstantValue
if (constVal->getType()->isFloat()) {
return std::to_string(constVal->getFloat());
if (auto constInt = dynamic_cast<ConstantInteger*>(value)) { // 优先匹配具体的常量类型
return std::to_string(constInt->getInt());
} else if (auto constFloat = dynamic_cast<ConstantFloating*>(value)) { // 优先匹配具体的常量类型
std::ostringstream oss;
oss << std::scientific << std::setprecision(std::numeric_limits<float>::max_digits10) << constFloat->getFloat();
return oss.str();
}
return std::to_string(constVal->getInt());
} else if (auto constVar = dynamic_cast<ConstantVariable*>(value)) {
return constVar->getName(); // 假设ConstantVariable有自己的名字或通过getByIndices获取值
} else if (auto argVar = dynamic_cast<Argument*>(value)) {
@ -79,6 +88,15 @@ std::string SysYPrinter::getValueName(Value *value) {
return "";
}
std::string SysYPrinter::getBlockName(BasicBlock *block) {
static int blockId = 0; // 用于生成唯一的基本块ID
if (block->getName().empty()) {
return "bb" + std::to_string(blockId++); // 如果没有名字生成一个唯一的基本块ID
} else {
return block->getName();
}
}
void SysYPrinter::printType(Type *type) {
std::cout << getTypeString(type);
}
@ -128,6 +146,52 @@ void SysYPrinter::printGlobalVariable() {
}
}
void SysYPrinter::printGlobalConstant() {
auto &globalConstants = pModule->getConsts();
for (const auto &globalConstant : globalConstants) {
std::cout << "@" << globalConstant->getName() << " = global constant ";
// 全局变量的类型是一个指针,指向其基类型 (可能是 ArrayType 或 Integer/FloatType)
auto globalVarBaseType = dynamic_cast<PointerType *>(globalConstant->getType())->getBaseType();
printType(globalVarBaseType); // 打印全局变量的实际类型 (例如 i32 或 [10 x i32])
std::cout << " ";
// 检查是否是数组类型 (通过检查 globalVarBaseType 是否是 ArrayType)
if (globalVarBaseType->isArray()) {
// 数组初始化器
std::cout << "["; // LLVM IR 数组初始化器格式: [type value, type value, ...]
auto values = globalConstant->getInitValues(); // 假设 getInitValues() 返回一个 ValueCounter
const std::vector<sysy::Value *> &counterValues = values.getValues(); // 获取所有值
for (size_t i = 0; i < counterValues.size(); i++) {
if (i > 0) std::cout << ", ";
// 打印元素类型,这个元素类型应该是数组的最终元素类型,例如 i32 或 float
// 可以从 globalVarBaseType 逐层剥离得到最终元素类型,但这里简化为直接从值获取
printType(counterValues[i]->getType());
std::cout << " ";
printValue(counterValues[i]);
}
std::cout << "]";
} else {
// 标量初始化器
// 假设标量全局变量的初始化值通过 getByIndex(0) 获取
Value* initVal = globalConstant->getByIndex(0);
printType(initVal->getType()); // 打印标量值的类型
std::cout << " ";
printValue(initVal); // 打印标量值
}
std::cout << ", align 4" << std::endl;
}
}
void SysYPrinter::printBlock(BasicBlock *block) {
std::cout << getBlockName(block);
}
void SysYPrinter::printFunction(Function *function) {
// Function signature
std::cout << "define ";
@ -176,6 +240,8 @@ void SysYPrinter::printInst(Instruction *pInst) {
case Kind::kMul:
case Kind::kDiv:
case Kind::kRem:
case Kind::kSRA:
case Kind::kMulh:
case Kind::kFAdd:
case Kind::kFSub:
case Kind::kFMul:
@ -208,6 +274,8 @@ void SysYPrinter::printInst(Instruction *pInst) {
case Kind::kMul: std::cout << "mul"; break;
case Kind::kDiv: std::cout << "sdiv"; break;
case Kind::kRem: std::cout << "srem"; break;
case Kind::kSRA: std::cout << "ashr"; break;
case Kind::kMulh: std::cout << "mulh"; break;
case Kind::kFAdd: std::cout << "fadd"; break;
case Kind::kFSub: std::cout << "fsub"; break;
case Kind::kFMul: std::cout << "fmul"; break;
@ -231,7 +299,12 @@ void SysYPrinter::printInst(Instruction *pInst) {
// Types and operands
std::cout << " ";
printType(binInst->getType());
// For comparison operations, print operand types instead of result type
if (pInst->getKind() >= Kind::kICmpEQ && pInst->getKind() <= Kind::kFCmpGE) {
printType(binInst->getLhs()->getType());
} else {
printType(binInst->getType());
}
std::cout << " ";
printValue(binInst->getLhs());
std::cout << ", ";
@ -344,27 +417,22 @@ void SysYPrinter::printInst(Instruction *pInst) {
}
std::cout << std::endl;
} break;
case Kind::kUnreachable: {
std::cout << "Unreachable" << std::endl;
} break;
case Kind::kAlloca: {
auto allocaInst = dynamic_cast<AllocaInst *>(pInst);
std::cout << "%" << allocaInst->getName() << " = alloca ";
// AllocaInst 的类型现在应该是一个 PointerType指向正确的 ArrayType 或 ScalarType
// 例如alloca i32, align 4 或者 alloca [10 x i32], align 4
auto allocatedType = dynamic_cast<PointerType *>(allocaInst->getType())->getBaseType();
// auto allocatedType = dynamic_cast<PointerType *>(allocaInst->getType())->getBaseType();
auto allocatedType = allocaInst->getAllocatedType();
printType(allocatedType);
// 仍然打印维度信息,如果存在的话
if (allocaInst->getNumDims() > 0) {
std::cout << ", ";
for (size_t i = 0; i < allocaInst->getNumDims(); i++) {
if (i > 0) std::cout << ", ";
printType(Type::getIntType()); // 维度大小通常是 i32 类型
std::cout << " ";
printValue(allocaInst->getDim(i));
}
}
std::cout << ", align 4" << std::endl;
} break;
@ -377,17 +445,6 @@ void SysYPrinter::printInst(Instruction *pInst) {
std::cout << " ";
printValue(loadInst->getPointer()); // 要加载的地址
// 仍然打印索引信息,如果存在的话
if (loadInst->getNumIndices() > 0) {
std::cout << ", indices "; // 或者其他分隔符,取决于你期望的格式
for (size_t i = 0; i < loadInst->getNumIndices(); i++) {
if (i > 0) std::cout << ", ";
printType(loadInst->getIndex(i)->getType());
std::cout << " ";
printValue(loadInst->getIndex(i));
}
}
std::cout << ", align 4" << std::endl;
} break;
@ -402,16 +459,6 @@ void SysYPrinter::printInst(Instruction *pInst) {
std::cout << " ";
printValue(storeInst->getPointer()); // 目标地址
// 仍然打印索引信息,如果存在的话
if (storeInst->getNumIndices() > 0) {
std::cout << ", indices "; // 或者其他分隔符
for (size_t i = 0; i < storeInst->getNumIndices(); i++) {
if (i > 0) std::cout << ", ";
printType(storeInst->getIndex(i)->getType());
std::cout << " ";
printValue(storeInst->getIndex(i));
}
}
std::cout << ", align 4" << std::endl;
} break;
@ -466,13 +513,13 @@ void SysYPrinter::printInst(Instruction *pInst) {
// 如果你的 PhiInst 存储方式是 getIncomingValues() 和 getIncomingBlocks(),请相应调整
// LLVM IR 格式: phi type [value1, block1], [value2, block2]
bool firstPair = true;
for (unsigned i = 0; i < phiInst->getNumOperands() / 2; ++i) { // 遍历成对的操作数
for (unsigned i = 0; i < phiInst->getNumIncomingValues(); ++i) { // 遍历成对的操作数
if (!firstPair) std::cout << ", ";
firstPair = false;
std::cout << "[ ";
printValue(phiInst->getOperand(i * 2)); // value
printValue(phiInst->getIncomingValue(i));
std::cout << ", %";
printValue(phiInst->getOperand(i * 2 + 1)); // block
printBlock(phiInst->getIncomingBlock(i));
std::cout << " ]";
}
std::cout << std::endl;

View File

@ -16,12 +16,13 @@ using namespace antlr4;
#include "SysYIRCFGOpt.h" // 包含 CFG 优化
#include "RISCv64Backend.h"
#include "Pass.h" // 包含新的 Pass 框架
#include "AddressCalculationExpansion.h"
using namespace sysy;
int DEBUG = 0;
int DEEPDEBUG = 0;
int DEEPERDEBUG = 0;
int DEBUGLENGTH = 50;
static string argStopAfter;
static string argInputFile;
@ -109,6 +110,7 @@ int main(int argc, char **argv) {
// 如果指定停止在 AST 阶段,则打印并退出
if (argStopAfter == "ast") {
cout << moduleAST->toStringTree(true) << '\n';
sysy::cleanupIRPools(); // 清理内存池
return EXIT_SUCCESS;
}
@ -131,7 +133,7 @@ int main(int argc, char **argv) {
if (DEBUG) {
cout << "=== Init IR ===\n";
SysYPrinter(moduleIR).printIR(); // 临时打印器用于调试
moduleIR->print(cout); // 使用新实现的print方法直接打印IR
}
// 创建 Pass 管理器并运行优化管道
@ -139,77 +141,30 @@ int main(int argc, char **argv) {
// 好像都不用传递module和builder了因为 PassManager 初始化了
passManager.runOptimizationPipeline(moduleIR, builder, optLevel);
AddressCalculationExpansion ace(moduleIR, builder);
if (ace.run()) {
if (DEBUG) cout << "AddressCalculationExpansion made changes.\n";
// 如果 ACE 改变了IR并且 DEBUG 模式开启可以考虑打印IR
if (DEBUG) {
cout << "=== After AddressCalculationExpansion ===\n";
SysYPrinter(moduleIR).printIR();
}
} else {
if (DEBUG) cout << "AddressCalculationExpansion made no changes.\n";
}
// 根据优化级别,执行额外的优化 pass
if (optLevel >= 1) {
if (DEBUG) cout << "Applying additional -O" << optLevel << " optimizations...\n";
// 放置 -O1 及其以上级别要启用的额外优化 pass
// 例如:
// MyNewOptimizationPass newOpt(moduleIR, builder);
// newOpt.run();
// 占位符注释,替换为你的具体优化 pass
// cout << "--- Additional Pass: MyCustomOpt1 ---" << endl;
// MyCustomOpt1 opt1_pass(moduleIR, builder);
// opt1_pass.run();
// cout << "--- Additional Pass: MyCustomOpt2 ---" << endl;
// MyCustomOpt2 opt2_pass(moduleIR, builder, &cfa); // 假设需要CFA
// opt2_pass.run();
// ... 更多 -O1 特有的优化
// DeadCodeElimination dce(moduleIR, &cfa, &ava);
// dce.runDCEPipeline();
// if (DEBUG) {
// cout << "=== After 1st DCE (Default) ===\n";
// SysYPrinter(moduleIR).printIR();
// }
// Mem2Reg mem2reg(moduleIR, builder, &cfa, &ava);
// mem2reg.mem2regPipeline();
// if (DEBUG) {
// cout << "=== After Mem2Reg (Default) ===\n";
// SysYPrinter(moduleIR).printIR();
// }
// Reg2Mem reg2mem(moduleIR, builder);
// reg2mem.DeletePhiInst();
// if (DEBUG) {
// cout << "=== After Reg2Mem (Default) ===\n";
// SysYPrinter(moduleIR).printIR();
// }
// dce.runDCEPipeline(); // 第二次 DCE (默认)
// if (DEBUG) {
// cout << "=== After 2nd DCE (Default) ===\n";
// SysYPrinter(moduleIR).printIR();
// }
} else {
if (DEBUG) cout << "No additional middle-end optimizations applied for -O" << optLevel << ".\n";
}
// 5. 根据 argStopAfter 决定后续操作
// a) 如果指定停止在 IR 阶段,则打印最终 IR 并退出
if (argStopAfter == "ir" || argStopAfter == "ird") {
// 打印最终 IR
cout << "=== Final IR ===\n";
SysYPrinter printer(moduleIR); // 在这里创建打印器,因为可能之前调试时用过临时打印器
printer.printIR();
if (DEBUG) cerr << "=== Final IR ===\n";
if (!argOutputFilename.empty()) {
// 输出到指定文件
ofstream fout(argOutputFilename);
if (not fout.is_open()) {
cerr << "Failed to open output file: " << argOutputFilename << endl;
moduleIR->cleanup(); // 清理模块
sysy::cleanupIRPools(); // 清理内存池
return EXIT_FAILURE;
}
moduleIR->print(fout);
fout.close();
} else {
// 输出到标准输出
moduleIR->print(cout);
}
moduleIR->cleanup(); // 清理模块
sysy::cleanupIRPools(); // 清理内存池
return EXIT_SUCCESS;
}
// b) 如果未停止在 IR 阶段,则继续生成汇编 (后端)
@ -218,6 +173,7 @@ int main(int argc, char **argv) {
DEBUG = 1;
DEEPDEBUG = 1;
}
sysy::RISCv64CodeGen codegen(moduleIR); // 传入优化后的 moduleIR
string asmCode = codegen.code_gen();
@ -227,6 +183,8 @@ int main(int argc, char **argv) {
ofstream fout(argOutputFilename);
if (not fout.is_open()) {
cerr << "Failed to open output file: " << argOutputFilename << endl;
moduleIR->cleanup(); // 清理模块
sysy::cleanupIRPools(); // 清理内存池
return EXIT_FAILURE;
}
fout << asmCode << endl;
@ -234,6 +192,8 @@ int main(int argc, char **argv) {
} else {
cout << asmCode << endl;
}
moduleIR->cleanup(); // 清理模块
sysy::cleanupIRPools(); // 清理内存池
return EXIT_SUCCESS;
}
@ -242,5 +202,7 @@ int main(int argc, char **argv) {
cout << "Compilation completed. No output specified (neither -s nor -S). Exiting.\n";
// return EXIT_SUCCESS; // 或者这里调用一个链接器生成可执行文件
moduleIR->cleanup(); // 清理模块
sysy::cleanupIRPools(); // 清理内存池
return EXIT_SUCCESS;
}

View File

@ -1,8 +0,0 @@
//test add
int main(){
int a, b;
a = 10;
b = 2;
return a + b;
}

View File

@ -1,14 +0,0 @@
//test file for backend lab
int main() {
const int a = 1;
const int b = 2;
int c;
if (a != b)
c = b - a + 20; // 21 <- this
else
c = a * b + b + b + 10; // 16
return c;
}

View File

@ -1,13 +0,0 @@
//test add
int mul(int x, int y) {
return x * y;
}
int main(){
int a, b;
a = 10;
b = 3;
a = mul(a, b); //60
return a + b; //66
}

View File

@ -1,20 +0,0 @@
//test file for loop-invariant code motion (licm) and strength reduction (sr is optional)
int main(){
const int a = 1;
const int b = 2;
int c, d, f;
int i = 0;
while(i < 100){
c = a + b;
d = c * 2;
if(i > 50){
f = i * d;
}
i = i + 1;
}
return f;
}

Some files were not shown because too many files have changed in this diff Show More