Compare commits

..

101 Commits

Author SHA1 Message Date
042b1a5d99 [midend-tco]修复命名重复问题 2025-08-19 00:13:32 +08:00
937833117e [midend-tco]添加TCO尾递归优化 2025-08-18 23:46:00 +08:00
ad74e435ba [midend-GSR]修复错误的代数简化 2025-08-18 21:55:57 +08:00
5c34cbc7b8 [midend-GSR]将魔数求解移动到utils的静态方法中。 2025-08-18 20:37:20 +08:00
c9a0c700e1 [midend]增加全局强度削弱优化遍 2025-08-18 11:30:40 +08:00
f317010d76 [midend-Loop-LICM][fix]检查load能否外提时其内存地址在循环中是否会被修改,需要判断函数调用对load内存地址的影响。 2025-08-17 17:42:19 +08:00
8ca64610eb [midend-GVN]重构GVN的值编号系统 2025-08-17 16:33:15 +08:00
969a78a088 [midend-GVN]segmentation fault是GVN引入的已修复,LICM仍然有错误 2025-08-17 14:37:27 +08:00
8763c0a11a [midend-LICM][fix]修改计算循环不变量依赖关系的排序错误,但是引入了很多Segmentation fault。 2025-08-17 01:35:03 +08:00
d83dc7a2e7 [midend-LICM][fix]修复循环不变量的识别逻辑 2025-08-17 01:19:44 +08:00
e32585fd25 [midend-GVN]修复GVN中部分逻辑问题,LICM有bug待修复 2025-08-17 00:14:47 +08:00
c4eb1c3980 [midend-GVN&SideEffect]修复GVN的部分问题和副作用分析的缺陷 2025-08-16 18:52:29 +08:00
d038884ffb [midend-GVN] commit头文件 2025-08-16 15:43:51 +08:00
467f2f6b24 [midend-GVN]初步构建GVN,能够优化部分CSE无法处理的子表达式但是有错误需要debug。 2025-08-16 15:38:41 +08:00
fa33bf5134 [midend-Loop-IVE]修复循环的死IV消除逻辑 2025-08-15 01:19:45 +08:00
a3435e7c26 [midend-Loop-IVE]循环归纳变量消除逻辑重构,修改运行顺序 2025-08-14 17:27:53 +08:00
7547d34598 [midend-IVE]参考libdivide库,实现了魔数的正确求解,如果后续出错直接用API或者不要除法强度削弱了 2025-08-14 05:12:54 +08:00
06a368db39 [midend]修复创建新归纳变量的错误逻辑,避免生成悬空phi节点的现象 2025-08-13 20:00:43 +08:00
48865fa805 [midend-IVE]增加无用归纳变量消除遍 2025-08-13 17:42:34 +08:00
8b5123460b [midend-Loop-InductionVarStrengthReduction]支持了对部分除法运算取模运算的归纳变量的强度削弱策略。(mulh+魔数,负数2的幂次除法符号修正,2的幂次取模运算and优化)。增加了了Printer对移位指令的打印支持 2025-08-13 17:41:41 +08:00
cd27f5fda9 [midend]增加部分逻辑位移指令 2025-08-13 15:28:37 +08:00
60cb8d6e49 [midend]重命名Sra指令的kind标识 2025-08-13 14:55:46 +08:00
ea944f6ba0 [midend-Loop-InductionVarStrengthReduction]增加循环规约变量强度削弱优化 2025-08-13 01:13:01 +08:00
0c8a156485 [midend-LoopCharacteristics]强化归纳变量的识别 2025-08-12 22:33:16 +08:00
debda205cc [testdata]将官方提供的RV错误样例输入替换成了ARM中正确的输入 2025-08-12 16:24:24 +08:00
baef82677b [midend-LICM]将能够外提的循环不变量进行Kanh拓扑排序保证外提后的计算顺序正确。 2025-08-12 16:18:00 +08:00
f634273852 [midend-LICM]优化了特征分析中对循环不变量的识别,实现了LICM遍,格式化副作用分析代码 2025-08-12 15:53:57 +08:00
70f6a25ebc [midend-LoopAnalysis]修复循环规范遍bug,修正部分打印格式, 2025-08-12 12:34:07 +08:00
8cb807c8b9 [midend-LoopAnalysis]修复phi指令缺失的getIncomingValues方法调用 2025-08-11 21:20:38 +08:00
1fab6a43f9 Merge branch 'midend' into midend-LoopAnalysis 2025-08-11 21:20:34 +08:00
1e3791a801 [midend-LoopNormalization]消除不必要的循环特征分析结果使用。优化phi指令处理逻辑 2025-08-11 20:51:55 +08:00
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
6a7355ed28 [midend-Loop]初步构建循环规范遍 2025-08-09 17:53:41 +08:00
be9ac89584 [midend-LoopAnalysis]将前置分析结果指针保存到循环特征分析类中消除冗余的分析指针传递 2025-08-09 16:42:31 +08:00
ac3358d7e3 [midend-LoopAnalysis]移除基本循环特征分析中的向量化并行化内容,增加循环向量化并行化特征分析遍,TODO:构建循环优化遍验证分析遍正确性 2025-08-09 13:53:00 +08:00
bd23f6154d [midend-SideEffect]将副作用分析遍重构为Module级别,更新其他优化遍用法,注册到PassMananger中,修改CMakeLists。 2025-08-08 16:25:41 +08:00
126c38a1d9 [midend-CallGraph]增加调用图分析遍 2025-08-08 16:24:13 +08:00
c4c91412d1 [midend]修改一点逻辑和注释,删除无用文件 2025-08-08 15:31:35 +08:00
f17e44f8d4 [midend-Alias]针对sysy语言设计了保守和激进的别名优化策略,设计了通过接口设置选项,后续需要验证。保留了一些激进策略接口置空待后续增加。 2025-08-08 15:08:49 +08:00
a406e44df3 [midend-Alias]应用别名分析结果,sccp现在能简单传播数组元素了 2025-08-08 02:12:32 +08:00
b1a46b7d58 [midend-LoopAnalysis]为项目添加别名分析遍,副作用分析遍,循环分析遍,循环特征分析遍 2025-08-08 00:56:50 +08:00
bd02f5f1eb [midend-LoopAnalysis]为phi指令添加新的方法供外部遍历(目前不是顺序遍历) 2025-08-08 00:55:01 +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
f083e38615 [midend-Loop]循环分析构建,增加很多统计方法和循环信息方法 2025-08-06 22:29:39 +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
ef9d7c4d03 [midend-LoopAnalysis]增加维护循环层级的逻辑,修改父子循环关系求解的逻辑。 2025-08-03 15:22:18 +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
1c7c85dd2f Merge commit 'f879a0f521e3033d3f928a5976ac095af6905942' into midend-LoopAnalysis 2025-08-03 14:30:32 +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
aa7f2bb0f5 [midend]loop分析构建 2025-08-02 17:42:43 +08:00
73 changed files with 15628 additions and 1688 deletions

View File

@ -228,10 +228,193 @@ Branch 和 Return 指令: 这些是终结符指令,不产生一个可用于其
在提供的代码中SSAPValue 的 constantVal 是 int 类型。这使得浮点数常量传播变得复杂。对于浮点数相关的指令kFAdd, kFMul, kFCmp, kFNeg, kFNot, kItoF, kFtoI 等),如果不能将浮点值准确地存储在 int 中,或者不能可靠地执行浮点运算,那么通常会保守地将结果设置为 Bottom。一个更完善的 SCCP 实现会使用 std::variant<int, float> 或独立的浮点常量存储来处理浮点数。
## LoopSR循环归纳变量强度削弱 关于魔数计算的说明
魔数除法的核心思想是:将除法转换为乘法和移位
数学原理x / d ≈ (x * m) >> (32 + s)
m 是魔数 (magic number)
s 是额外的移位量 (shift)
>> 是算术右移
2^(32+s) / d ≤ m < 2^(32+s) / d + 2^s / d
cd /home/downright/Compiler_Opt/mysysy && python3 -c "
# 真正的迭代原因:精度要求
def explain_precision_requirement():
d = 10
print('魔数算法需要找到精确的边界值')
print('目标2^p > d * (2^31 - r)其中r是余数')
print()
# 模拟我们算法的迭代过程
p = 31
two_p = 2**p
r = two_p % d # 余数
m = two_p // d # 商
print(f'初始状态 (p={p}):')
print(f' 2^{p} = {two_p:,}')
print(f' 2^{p} / {d} = {m:,} 余 {r}')
print(f' 需要检查: 2^{p} > {d} * (2^31 - {r}) = {d * (2**31 - r):,}')
print(f' 条件满足: {two_p > d * (2**31 - r)}')
print()
# 继续迭代直到条件满足
iteration = 0
while r != 0 and m < 2**31:
iteration += 1
p += 1
two_p *= 2
m *= 2
r *= 2
if r >= d:
m += 1
r -= d
print(f'迭代 {iteration} (p={p}):')
print(f' m = {m:,}, r = {r}')
print(f' m < 2^31? {m < 2**31} (2^31 = {2**31:,})')
if m >= 2**31:
print(f' ✗ 魔数 {m:,} 超出32位范围!')
break
elif r == 0:
print(f' ✓ 余数为0找到精确解')
break
if iteration > 10: # 防止无限循环
print(' ... (限制迭代次数)')
break
explain_precision_requirement()
"
问题在于精度要求。理论魔数需要非常精确,不能简单地用 2^32 / d。让我展示真正的迭代原因
cd /home/downright/Compiler_Opt/mysysy && python3 -c "
# 真正的迭代原因:精度要求
def explain_precision_requirement():
d = 10
print('魔数算法需要找到精确的边界值:')
print('目标2^p > d * (2^31 - r)其中r是余数')
print()
# 模拟我们算法的迭代过程
p = 31
two_p = 2**p
r = two_p % d # 余数
m = two_p // d # 商
print(f'初始状态 (p={p}):')
print(f' 2^{p} = {two_p:,}')
print(f' 2^{p} / {d} = {m:,} 余 {r}')
print(f' 需要检查: 2^{p} > {d} * (2^31 - {r}) = {d * (2**31 - r):,}')
print(f' 条件满足: {two_p > d * (2**31 - r)}')
print()
# 继续迭代直到条件满足
iteration = 0
while r != 0 and m < 2**31:
iteration += 1
p += 1
two_p *= 2
m *= 2
r *= 2
if r >= d:
m += 1
r -= d
print(f'迭代 {iteration} (p={p}):')
print(f' m = {m:,}, r = {r}')
print(f' m < 2^31? {m < 2**31} (2^31 = {2**31:,})')
if m >= 2**31:
print(f' ✗ 魔数 {m:,} 超出32位范围!')
break
elif r == 0:
print(f' ✓ 余数为0找到精确解')
break
if iteration > 10: # 防止无限循环
print(' ... (限制迭代次数)')
break
explain_precision_requirement()
"
cd /home/downright/Compiler_Opt/mysysy && python3 -c "
# 检查初始状态是否会溢出
def check_initial_overflow():
int32_max = 2**31 - 1
print('检查不同除数的初始魔数是否会溢出:')
print(f'32位有符号整数最大值: {int32_max:,}')
print()
# 检查各种除数
divisors = [2, 3, 5, 7, 9, 10, 11, 13, 17, 25, 100, 1000]
for d in divisors:
# 初始魔数 = 2^31 / d
initial_magic = (2**31) // d
overflow = initial_magic > int32_max
status = \"溢出\" if overflow else \"安全\"
print(f'd={d:4d}: 初始魔数 = 2^31/{d} = {initial_magic:10,} [{status}]')
print()
print('结论: 初始状态下魔数不会溢出,溢出发生在迭代过程中')
check_initial_overflow()
"
总结
迭代的必要性:
不是为了避免初始溢出(初始状态安全)
是为了找到最精确的魔数,减少舍入误差
每次迭代提高一倍精度,但魔数也翻倍
溢出发生时机:
初始状态2^31 / d 总是在32位范围内
迭代过程2^32 / d, 2^33 / d, ... 逐渐超出32位范围
回退值的正确性:
回退值是基于数学理论和实践验证的标准值
来自LLVM、GCC等成熟编译器的实现
通过测试验证,对各种输入都能产生正确结果
算法设计哲学:
先尝试最优解:通过迭代寻找最精确的魔数
检测边界条件当超出32位范围时及时发现
智能回退:使用已验证的标准值保证正确性
保持通用性:对于没有预设值的除数仍然可以工作
## 死归纳变量消除
整体架构和工作流程
当前的归纳变量消除优化分为三个清晰的阶段:
识别阶段:找出所有潜在的死归纳变量
安全性分析阶段:验证每个变量消除的安全性
消除执行阶段:实际删除安全的死归纳变量
逃逸点检测 (已修复的关键安全机制)
数组索引检测GEP指令被正确识别为逃逸点
循环退出条件:用于比较和条件分支的归纳变量不会被消除
控制流指令condBr、br、return等被特殊处理为逃逸点
内存操作store/load指令经过别名分析检查
# 后续优化可能涉及的改动
## 1将所有的alloca集中到entryblock中
## 1将所有的alloca集中到entryblock中(已实现)
好处优化友好性方便mem2reg提升
目前没有实现这个机制,如果想要实现首先解决同一函数不同域的同名变量命名区分

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 "清理完成。"
}

View File

@ -2,64 +2,67 @@
# 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 和 lib
BUILD_BIN_DIR="${SCRIPT_DIR}/../build/bin"
LIB_DIR="${SCRIPT_DIR}/../lib"
# 临时文件会存储在脚本所在目录的 tmp 子目录中
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
SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒)
GCC_TIMEOUT=10 # gcc 编译超时 (秒)
EXEC_TIMEOUT=5 # qemu 自动化执行超时 (秒)
MAX_OUTPUT_LINES=50 # 对比失败时显示的最大行数
SY_FILES=() # 存储用户提供的 .sy 文件列表
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 文件。"
echo ""
echo "如果找到对应的 .in/.out 文件,则进行自动化测试。否则,进入交互模式。"
echo "编译并测试指定的 .sy 文件。必须提供 -e 或 -eir 之一。"
echo ""
echo "选项:"
echo " -e, --executable 编译为可执行文件并运行测试 (必须)。"
echo " -e 通过汇编运行测试 (sysyc -> gcc -> qemu)。"
echo " -eir 通过IR运行测试 (sysyc -> llc -> gcc -> qemu)。"
echo " -c, --clean 清理 tmp 临时目录下的所有文件。"
echo " -sct N 设置 sysyc 编译超时为 N 秒 (默认: 10)。"
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 秒 (默认: 5)。"
echo " -ml N, --max-lines N 当输出对比失败时,最多显示 N 行内容 (默认: 50)。"
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
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"
@ -68,51 +71,79 @@ display_file_content() {
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 循环来健壮地处理任意顺序的参数
while [[ "$#" -gt 0 ]]; do
case "$1" in
-e|--executable)
EXECUTE_MODE=true
shift # 消耗选项
;;
-c|--clean)
CLEAN_MODE=true
shift # 消耗选项
;;
-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
;;
*) # 其他参数被视为文件路径
-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 # 消耗文件参数
shift
;;
esac
done
if ${CLEAN_MODE}; then
echo "检测到 -c/--clean 选项,正在清空 ${TMP_DIR}..."
if [ -d "${TMP_DIR}" ]; then
@ -121,19 +152,22 @@ if ${CLEAN_MODE}; then
else
echo "临时目录 ${TMP_DIR} 不存在,无需清理。"
fi
if [ ${#SY_FILES[@]} -eq 0 ] && ! ${EXECUTE_MODE}; then
if [ ${#SY_FILES[@]} -eq 0 ] && ! ${EXECUTE_MODE} && ! ${IR_EXECUTE_MODE}; then
exit 0
fi
fi
# --- 主逻辑开始 ---
if ! ${EXECUTE_MODE}; then
echo "错误: 请提供 -e 或 --executable 选项来运行测试。"
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
@ -144,18 +178,18 @@ mkdir -p "${TMP_DIR}"
TOTAL_CASES=${#SY_FILES[@]}
echo "SysY 单例测试运行器启动..."
echo "超时设置: sysyc=${SYSYC_TIMEOUT}s, gcc=${GCC_TIMEOUT}s, qemu=${EXEC_TIMEOUT}s"
echo "失败输出最大行数: ${MAX_OUTPUT_LINES}"
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}_sysyc_riscv64.ll"
ir_file="${TMP_DIR}/${base_name}.ll"
assembly_file="${TMP_DIR}/${base_name}.s"
assembly_debug_file="${TMP_DIR}/${base_name}_d.s"
executable_file="${TMP_DIR}/${base_name}"
input_file="${source_dir}/${base_name}.in"
output_reference_file="${source_dir}/${base_name}.out"
@ -164,47 +198,39 @@ for sy_file in "${SY_FILES[@]}"; do
echo "======================================================================"
echo "正在处理: ${sy_file}"
# --- 本次修改点: 拷贝源文件到 tmp 目录 ---
echo " 拷贝源文件到 ${TMP_DIR}..."
cp "${sy_file}" "${TMP_DIR}/$(basename "${sy_file}")"
if [ -f "${input_file}" ]; then
cp "${input_file}" "${TMP_DIR}/$(basename "${input_file}")"
fi
if [ -f "${output_reference_file}" ]; then
cp "${output_reference_file}" "${TMP_DIR}/$(basename "${output_reference_file}")"
fi
# --- 编译阶段 ---
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
# 步骤 1: sysyc 编译
echo " 使用 sysyc 编译 (超时 ${SYSYC_TIMEOUT}s)..."
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s ir "${sy_file}" > "${ir_file}"
SYSYC_STATUS=$?
if [ $SYSYC_STATUS -eq 124 ]; then
echo -e "\e[31m错误: SysY 编译 ${sy_file} IR超时\e[0m"
is_passed=0
elif [ $SYSYC_STATUS -ne 0 ]; then
echo -e "\e[31m错误: SysY 编译 ${sy_file} IR失败退出码: ${SYSYC_STATUS}\e[0m"
is_passed=0
fi
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -S "${sy_file}" -o "${assembly_file}"
if [ $? -ne 0 ]; then
echo -e "\e[31m错误: SysY 编译失败或超时。\e[0m"
is_passed=0
fi
# timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s asmd "${sy_file}" > "${assembly_debug_file}" 2>&1
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
# 步骤 2: GCC 编译
if [ "$is_passed" -eq 1 ]; then
echo " 使用 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"
is_passed=0
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
# 步骤 3: 执行与测试
if [ "$is_passed" -eq 1 ]; then
# 检查是自动化测试还是交互模式
# --- 执行与测试阶段 (公共逻辑) ---
if [ "$compilation_ok" -eq 1 ]; then
if [ -f "${input_file}" ] || [ -f "${output_reference_file}" ]; then
# --- 自动化测试模式 ---
echo " 检测到 .in/.out 文件,进入自动化测试模式..."
@ -227,24 +253,26 @@ for sy_file in "${SY_FILES[@]}"; do
EXPECTED_RETURN_CODE="$LAST_LINE_TRIMMED"
EXPECTED_STDOUT_FILE="${TMP_DIR}/${base_name}.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
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"
is_passed=0
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}"
echo -e " \e[36m----------------\e[0m"
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
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}"
echo -e " \e[36m----------------\e[0m"
fi
fi
else
@ -253,20 +281,16 @@ for sy_file in "${SY_FILES[@]}"; do
fi
else
# --- 交互模式 ---
echo -e "\e[33m"
echo " **********************************************************"
echo " ** 未找到 .in 或 .out 文件,进入交互模式。 **"
echo " ** 程序即将运行,你可以直接在终端中输入。 **"
echo " ** 按下 Ctrl+D (EOF) 或以其他方式结束程序以继续。 **"
echo " **********************************************************"
echo -e "\e[0m"
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"
echo " 注意: 交互模式的结果未经验证。"
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++))
@ -277,20 +301,4 @@ for sy_file in "${SY_FILES[@]}"; do
done
# --- 打印最终总结 ---
echo "======================================================================"
echo "所有测试完成"
echo "测试通过率: [${PASSED_CASES}/${TOTAL_CASES}]"
if [ -n "$FAILED_CASES_LIST" ]; then
echo ""
echo -e "\e[31m未通过的测例:\e[0m"
echo -e "${FAILED_CASES_LIST}"
fi
echo "======================================================================"
if [ "$PASSED_CASES" -eq "$TOTAL_CASES" ]; then
exit 0
else
exit 1
fi
print_summary

View File

@ -1,31 +1,41 @@
#!/bin/bash
# runit.sh - 用于编译和测试 SysY 程序的脚本
# 此脚本应该位于 mysysy/test_script/
# 此脚本应该位于 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"
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
SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒)
GCC_TIMEOUT=10 # gcc 编译超时 (秒)
EXEC_TIMEOUT=5 # qemu 执行超时 (秒)
MAX_OUTPUT_LINES=50 # 对比失败时显示的最大行数
TEST_SETS=() # 用于存储要运行的测试集
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="" # 用于存储未通过的测例列表
FAILED_CASES_LIST=""
INTERRUPTED=false # 新增:用于标记是否被中断
# =================================================================
# --- 函数定义 ---
# =================================================================
# 显示帮助信息的函数
show_help() {
@ -33,30 +43,32 @@ show_help() {
echo "此脚本用于按文件名前缀数字升序编译和测试 .sy 文件。"
echo ""
echo "选项:"
echo " -e, --executable 编译为可执行文件并运行测试。"
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 秒 (默认: 10)。"
echo " -sct N 设置 sysyc 编译超时为 N 秒 (默认: 30)。"
echo " -lct N 设置 llc-19 编译超时为 N 秒 (默认: 10)。"
echo " -gct N 设置 gcc 交叉编译超时为 N 秒 (默认: 10)。"
echo " -et N 设置 qemu 执行超时为 N 秒 (默认: 5)。"
echo " -ml N, --max-lines N 当输出对比失败时,最多显示 N 行内容 (默认: 50)。"
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
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"
@ -71,61 +83,90 @@ clean_tmp() {
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
;;
-c|--clean)
clean_tmp
exit 0
;;
-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 # 移过 '-set'
# 消耗所有后续参数直到遇到下一个选项
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
;;
-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
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
# --- 本次修改点: 根据 -set 参数构建查找路径 ---
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=()
# 如果未指定测试集,或指定了 'all',则搜索所有目录
if [ ${#TEST_SETS[@]} -eq 0 ] || [[ " ${TEST_SETS[@]} " =~ " all " ]]; then
SEARCH_PATHS+=("${TESTDATA_DIR}")
else
@ -138,23 +179,34 @@ else
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}"
echo "执行模式: ${EXECUTE_MODE}"
if ${EXECUTE_MODE}; then
echo "超时设置: sysyc=${SYSYC_TIMEOUT}s, gcc=${GCC_TIMEOUT}s, qemu=${EXEC_TIMEOUT}s"
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 文件并排序
sy_files=$(find "${SEARCH_PATHS[@]}" -name "*.sy" | sort -V)
if [ -z "$sy_files" ]; then
echo "在指定目录中未找到任何 .sy 文件。"
@ -162,139 +214,229 @@ if [ -z "$sy_files" ]; then
fi
TOTAL_CASES=$(echo "$sy_files" | wc -w)
# --- 修复: 使用 here-string (<<<) 代替管道 (|) 来避免子 shell 问题 ---
while IFS= read -r sy_file; do
is_passed=1 # 1 表示通过, 0 表示失败
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="${TMP_DIR}/${output_base_name}_sysyc_riscv64.s"
executable_file="${TMP_DIR}/${output_base_name}_sysyc_riscv64"
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"
output_actual_file="${TMP_DIR}/${output_base_name}_sysyc_riscv64.actual_out"
echo "正在处理: $(basename "$sy_file") (路径: ${relative_path_no_ext}.sy)"
# 步骤 1: 使用 sysyc 编译 .sy 到 .s
echo " 使用 sysyc 编译 (超时 ${SYSYC_TIMEOUT}s)..."
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -S "${sy_file}" -o "${assembly_file}"
SYSYC_STATUS=$?
if [ $SYSYC_STATUS -eq 124 ]; then
echo -e "\e[31m错误: SysY 编译 ${sy_file} 超时\e[0m"
is_passed=0
elif [ $SYSYC_STATUS -ne 0 ]; then
echo -e "\e[31m错误: SysY 编译 ${sy_file} 失败,退出码: ${SYSYC_STATUS}\e[0m"
is_passed=0
fi
# --- 模式 1: IR 执行模式 (-eir) ---
if ${IR_EXECUTE_MODE}; then
step_failed=0
test_logic_passed=0
# 只有当 EXECUTE_MODE 为 true 且上一步成功时才继续
if ${EXECUTE_MODE} && [ "$is_passed" -eq 1 ]; then
# 步骤 2: 使用 riscv64-linux-gnu-gcc 编译 .s 到可执行文件
echo " 使用 gcc 编译 (超时 ${GCC_TIMEOUT}s)..."
timeout -s KILL ${GCC_TIMEOUT} "${GCC_RISCV64}" "${assembly_file}" -o "${executable_file}" -L"${LIB_DIR}" -lsysy_riscv -static
GCC_STATUS=$?
if [ $GCC_STATUS -eq 124 ]; then
echo -e "\e[31m错误: GCC 编译 ${assembly_file} 超时\e[0m"
is_passed=0
elif [ $GCC_STATUS -ne 0 ]; then
echo -e "\e[31m错误: GCC 编译 ${assembly_file} 失败,退出码: ${GCC_STATUS}\e[0m"
is_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
elif ! ${EXECUTE_MODE}; then
echo " 跳过执行模式。仅生成汇编文件。"
if [ "$is_passed" -eq 1 ]; then
((PASSED_CASES++))
else
FAILED_CASES_LIST+="${relative_path_no_ext}.sy\n"
fi
echo ""
continue
fi
# 步骤 3, 4, 5: 只有当编译都成功时才执行
if [ "$is_passed" -eq 1 ]; then
echo " 正在执行 (超时 ${EXEC_TIMEOUT}s)..."
exec_cmd="${QEMU_RISCV64} \"${executable_file}\""
if [ -f "${input_file}" ]; then
exec_cmd+=" < \"${input_file}\""
fi
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 执行超时: ${sy_file} 运行超过 ${EXEC_TIMEOUT} 秒\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}/${output_base_name}_sysyc_riscv64.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"
is_passed=0
fi
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 [ $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}") <(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}"
echo -e " \e[36m------------------------------\e[0m"
fi
fi
else
echo " 无参考输出文件。程序返回码: ${ACTUAL_RETURN_CODE}"
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"
echo "========================================"
echo "测试完成"
echo "测试通过率: [${PASSED_CASES}/${TOTAL_CASES}]"
if [ -n "$FAILED_CASES_LIST" ]; then
echo ""
echo -e "\e[31m未通过的测例:\e[0m"
echo -e "${FAILED_CASES_LIST}"
fi
echo "========================================"
if [ "$PASSED_CASES" -eq "$TOTAL_CASES" ]; then
exit 0
else
exit 1
fi
# --- 修改:调用总结函数 ---
print_summary

View File

@ -12,6 +12,7 @@ add_library(riscv64_backend_lib STATIC
Optimize/Peephole.cpp
Optimize/PostRA_Scheduler.cpp
Optimize/PreRA_Scheduler.cpp
Optimize/DivStrengthReduction.cpp
)
# 包含后端模块所需的头文件路径

View File

@ -41,7 +41,7 @@ void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
});
frame_info.callee_saved_regs_to_store = sorted_regs;
// 3. [关键修正] 更新栈帧总大小。
// 3. 更新栈帧总大小。
// 这是初步计算PEI Pass 会进行最终的对齐。
frame_info.total_size = frame_info.locals_size +
frame_info.spill_size +

View File

@ -1,7 +1,7 @@
#include "EliminateFrameIndices.h"
#include "RISCv64ISel.h"
#include <cassert>
#include <vector> // [新增] 为插入指令而包含
#include <vector>
namespace sysy {
@ -33,11 +33,7 @@ void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) {
Function* F = mfunc->getFunc();
RISCv64ISel* isel = mfunc->getISel();
// 1. [已移除] 不再处理栈传递的参数
// 原先处理栈参数 (arg_idx >= 8) 的逻辑已被移除。
// 这项职责已完全转移到 PrologueEpilogueInsertionPass以避免逻辑冲突和错误。
// [注释更新] -> 上述注释已过时。根据新方案,我们将在这里处理栈传递的参数,
// 以便在寄存器分配前就将数据流显式化修复溢出逻辑的BUG。
// 在这里处理栈传递的参数以便在寄存器分配前就将数据流显式化修复溢出逻辑的BUG。
// 2. 只为局部变量(AllocaInst)分配栈空间和计算偏移量
// 局部变量从 s0 下方(负偏移量)开始分配,紧接着为 ra 和 s0 预留的16字节之后
@ -50,9 +46,13 @@ void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) {
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字节
// 优化栈帧大小对于大数组使用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);
@ -65,13 +65,17 @@ void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) {
// 记录仅由AllocaInst分配的局部变量的总大小
frame_info.locals_size = local_var_offset - 16;
// 记录局部变量区域分配结束的最终偏移量
frame_info.locals_end_offset = -local_var_offset;
// 3. [核心修改] 在函数入口为所有栈传递的参数插入load指令
// 在函数入口为所有栈传递的参数插入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个整型/指针参数通过寄存器传递,这里只处理超出部分。
@ -104,17 +108,50 @@ void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) {
arg_idx++;
}
// 将所有新创建的参数加载指令一次性插入到入口块的起始位置
auto& entry_instrs = entry_block->getInstructions();
entry_instrs.insert(entry_instrs.begin(),
std::make_move_iterator(arg_load_instrs.begin()),
std::make_move_iterator(arg_load_instrs.end()));
//仅当有需要加载的栈参数时,才执行插入逻辑
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()) {

View File

@ -27,8 +27,7 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
);
}
// 2. [新增] 确定需要保存的被调用者保存寄存器 (callee-saved)
// 这部分逻辑从 CalleeSavedHandler Pass 移入,以集中管理序言生成
// 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();
@ -36,38 +35,44 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
for (const auto& pair : vreg_to_preg_map) {
PhysicalReg preg = pair.second;
// 检查是否在整数或浮点 callee-saved 集合中
// 注意s0作为帧指针由序言/尾声逻辑特殊处理,不在此处保存
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 供尾声使用
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; // 每个寄存器8字节
frame_info.callee_saved_size = frame_info.callee_saved_regs_to_store.size() * 8;
// 3. 计算最终的栈帧总大小
// 3. 计算最终的栈帧总大小,包含栈溢出保护
int total_stack_size = frame_info.locals_size +
frame_info.spill_size +
frame_info.callee_saved_size +
16; // 为 ra 和 s0 固定的16字节
16;
int aligned_stack_size = (total_stack_size + 15) & ~15; // 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. 分配栈帧: addi sp, sp, -aligned_stack_size
// 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));
@ -75,7 +80,6 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
prologue_instrs.push_back(std::move(alloc_stack));
// 4.2. 保存 ra 和 s0
// sd ra, (aligned_stack_size - 8)(sp)
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>(
@ -83,7 +87,6 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
std::make_unique<ImmOperand>(aligned_stack_size - 8)
));
prologue_instrs.push_back(std::move(save_ra));
// sd s0, (aligned_stack_size - 16)(sp)
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>(
@ -92,60 +95,55 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
));
prologue_instrs.push_back(std::move(save_fp));
// 4.3. 设置新的帧指针 s0: addi s0, sp, aligned_stack_size
// 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. [新增] 保存所有使用到的被调用者保存寄存器
// 它们保存在 s0 下方,紧接着 ra/s0 的位置
int callee_saved_offset = -16;
// 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) {
callee_saved_offset -= 8;
RVOpcodes store_op = (reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31) ? RVOpcodes::FSD : RVOpcodes::SD;
// 改为“先更新,后使用”逻辑
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>(callee_saved_offset)
std::make_unique<ImmOperand>(next_available_offset) // 使用新计算出的正确偏移
));
prologue_instrs.push_back(std::move(save_cs_reg));
// 不再需要在循环末尾递减
}
// 4.5. [核心修改] 加载栈传递参数的逻辑已从此移除
// 这项工作已经前移至 `EliminateFrameIndicesPass` 中完成,
// 以确保在寄存器分配前就将相关虚拟寄存器定义从而修复溢出逻辑的bug。
// 4.6. 将所有生成的序言指令一次性插入到函数入口
// 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()) {
// [修正] 使用前向迭代器查找RET指令以确保在正确的位置RET之前插入尾声。
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. [新增] 恢复被调用者保存寄存器
callee_saved_offset = -16;
// 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) {
callee_saved_offset -= 8;
RVOpcodes load_op = (reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31) ? RVOpcodes::FLD : RVOpcodes::LD;
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>(callee_saved_offset)
std::make_unique<ImmOperand>(next_available_offset_restore) // 使用当前偏移
));
epilogue_instrs.push_back(std::move(restore_cs_reg));
}
// 5.2. 恢复 ra 和 s0 (注意基址现在是sp)
// ld ra, (aligned_stack_size - 8)(sp)
// 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>(
@ -153,7 +151,6 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
std::make_unique<ImmOperand>(aligned_stack_size - 8)
));
epilogue_instrs.push_back(std::move(restore_ra));
// ld s0, (aligned_stack_size - 16)(sp)
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>(
@ -162,7 +159,7 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
));
epilogue_instrs.push_back(std::move(restore_fp));
// 5.3. 释放栈帧: addi sp, sp, aligned_stack_size
// 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));
@ -174,7 +171,6 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
std::make_move_iterator(epilogue_instrs.begin()),
std::make_move_iterator(epilogue_instrs.end()));
// 一个基本块通常只有一个终止指令,处理完就可以跳到下一个块
goto next_block;
}
}

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

@ -634,6 +634,22 @@ void PeepholeOptimizer::runOnMachineFunction(MachineFunction *mfunc) {
}
}
}
// 8. 消除无用移动指令: mv a, a -> (删除)
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 *dst = static_cast<RegOperand *>(mi1->getOperands()[0].get());
auto *src = static_cast<RegOperand *>(mi1->getOperands()[1].get());
// 检查源和目标寄存器是否相同
if (areRegsEqual(dst, src)) {
// 删除这条无用指令
instrs.erase(instrs.begin() + i);
changed = true;
}
}
}
// 根据是否发生变化调整遍历索引
if (!changed) {

View File

@ -1,7 +1,8 @@
#include "RISCv64AsmPrinter.h"
#include "RISCv64ISel.h"
#include <stdexcept>
#include <sstream>
#include <iostream>
namespace sysy {
// 检查是否为内存加载/存储指令,以处理特殊的打印格式
@ -60,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;
@ -104,7 +105,7 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
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指令添加特殊处理逻辑
case RVOpcodes::CALL: { // 为CALL指令添加特殊处理逻辑
*OS << "call ";
// 遍历所有操作数,只寻找并打印函数名标签
for (const auto& op : instr->getOperands()) {
@ -236,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

@ -73,7 +73,7 @@ std::string RISCv64CodeGen::module_gen() {
for (const auto& global_ptr : module->getGlobals()) {
GlobalValue* global = global_ptr.get();
// [核心修改] 使用更健壮的逻辑来判断是否为大型零初始化数组
// 使用更健壮的逻辑来判断是否为大型零初始化数组
bool is_all_zeros = true;
const auto& init_values = global->getInitValues();
@ -139,7 +139,29 @@ std::string RISCv64CodeGen::module_gen() {
ss << ".type " << global->getName() << ", @object\n";
ss << ".size " << global->getName() << ", " << total_size << "\n";
ss << global->getName() << ":\n";
printInitializer(ss, global->getInitValues());
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)
@ -171,222 +193,90 @@ std::string RISCv64CodeGen::module_gen() {
}
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) {
// === 完整的后端处理流水线 ===
// 阶段 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();
// }
DEBUG = 0;
DEEPDEBUG = 0;
DEBUG = 1;
DEEPDEBUG = 1;
if (DEBUG) {
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
<< ss_after_isel.str();
}
// DEBUG = 0;
// DEEPDEBUG = 0;
// [新增] 阶段 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: 指令调度 (Instruction Scheduling)
// PreRA_Scheduler scheduler;
// scheduler.runOnMachineFunction(mfunc.get());
// DEBUG = 0;
// DEEPDEBUG = 0;
// DEBUG = 1;
// DEEPDEBUG = 1;
// 阶段 3: 物理寄存器分配 (Register Allocation)
RISCv64RegAlloc reg_alloc(mfunc.get());
reg_alloc.run();
// DEBUG = 0;
// DEEPDEBUG = 0;
DEBUG = 1;
DEEPDEBUG = 1;
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());
DEBUG = 0;
DEEPDEBUG = 0;
// 阶段 3.3: 大立即数合法化
LegalizeImmediatesPass legalizer;
legalizer.runOnMachineFunction(mfunc.get());
// 阶段 6: 代码发射 (Code Emission)
std::stringstream ss;
RISCv64AsmPrinter printer(mfunc.get());
printer.run(ss);
if (DEBUG) {
ss << "\n\n; --- Intermediate Representation after Instruction Selection ---\n"
<< ss_after_isel.str();
}
DEBUG = 1;
DEEPDEBUG = 1;
return ss.str();
std::cout << ss_after_isel.str();
}
if (DEBUG) {
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
<< ss_after_isel.str();
}
else {
// === 完整的后端处理流水线 ===
// 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
// 这个Pass必须在寄存器分配之前运行
EliminateFrameIndicesPass efi_pass;
efi_pass.runOnMachineFunction(mfunc.get());
// 阶段 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();
// }
DEBUG = 0;
DEEPDEBUG = 0;
// DEBUG = 1;
// DEEPDEBUG = 1;
if (DEBUG) {
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
<< ss_after_isel.str();
}
// DEBUG = 0;
// DEEPDEBUG = 0;
// [新增] 阶段 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: 指令调度 (Instruction Scheduling)
// PreRA_Scheduler scheduler;
// scheduler.runOnMachineFunction(mfunc.get());
DEBUG = 0;
DEEPDEBUG = 0;
// DEBUG = 1;
// DEEPDEBUG = 1;
// 阶段 3: 物理寄存器分配 (Register Allocation)
RISCv64RegAlloc reg_alloc(mfunc.get());
reg_alloc.run();
DEBUG = 0;
DEEPDEBUG = 0;
// DEBUG = 1;
// DEEPDEBUG = 1;
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());
DEBUG = 0;
DEEPDEBUG = 0;
// 阶段 3.3: 大立即数合法化
LegalizeImmediatesPass legalizer;
legalizer.runOnMachineFunction(mfunc.get());
// 阶段 6: 代码发射 (Code Emission)
std::stringstream ss;
RISCv64AsmPrinter printer(mfunc.get());
printer.run(ss);
if (DEBUG) {
ss << "\n\n; --- Intermediate Representation after Instruction Selection ---\n"
<< ss_after_isel.str();
}
return ss.str();
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

View File

@ -1,9 +1,10 @@
#include "RISCv64ISel.h"
#include "IR.h" // For GlobalValue
#include <stdexcept>
#include <set>
#include <functional>
#include <cmath> // For std::fabs
#include <limits> // For std::numeric_limits
#include <cmath>
#include <limits>
#include <iostream>
namespace sysy {
@ -167,33 +168,6 @@ void RISCv64ISel::selectBasicBlock(BasicBlock* bb) {
select_recursive(node_to_select);
}
}
if (CurMBB == MFunc->getBlocks().front().get()) { // 只对入口块操作
auto keepalive = std::make_unique<MachineInstr>(RVOpcodes::PSEUDO_KEEPALIVE);
for (Argument* arg : F->getArguments()) {
keepalive->addOperand(std::make_unique<RegOperand>(getVReg(arg)));
}
auto& instrs = CurMBB->getInstructions();
auto insert_pos = instrs.end();
// 关键:检查基本块是否以一个“终止指令”结尾
if (!instrs.empty()) {
RVOpcodes last_op = instrs.back()->getOpcode();
// 扩充了判断条件,涵盖所有可能的终止指令
if (last_op == RVOpcodes::J || last_op == RVOpcodes::RET ||
last_op == RVOpcodes::BEQ || last_op == RVOpcodes::BNE ||
last_op == RVOpcodes::BLT || last_op == RVOpcodes::BGE ||
last_op == RVOpcodes::BLTU || last_op == RVOpcodes::BGEU)
{
// 如果是,插入点就在这个终止指令之前
insert_pos = std::prev(instrs.end());
}
}
// 在计算出的正确位置插入伪指令
instrs.insert(insert_pos, std::move(keepalive));
}
}
// 核心函数为DAG节点选择并生成MachineInstr (已修复和增强的完整版本)
@ -209,8 +183,12 @@ void RISCv64ISel::selectNode(DAGNode* node) {
case DAGNode::CONSTANT:
case DAGNode::ALLOCA_ADDR:
if (node->value) {
// 确保它有一个关联的虚拟寄存器即可,不生成代码。
getVReg(node->value);
// GlobalValue objects (global variables) should not get virtual registers
// since they represent memory addresses, not register-allocated values
if (dynamic_cast<GlobalValue*>(node->value) == nullptr) {
// 确保它有一个关联的虚拟寄存器即可,不生成代码。
getVReg(node->value);
}
}
break;
@ -402,7 +380,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
Value* base = nullptr;
Value* offset = nullptr;
// [修改] 扩展基地址的判断,使其可以识别 AllocaInst 或 GlobalValue
// 扩展基地址的判断,使其可以识别 AllocaInst 或 GlobalValue
if (dynamic_cast<AllocaInst*>(lhs) || dynamic_cast<GlobalValue*>(lhs)) {
base = lhs;
offset = rhs;
@ -421,7 +399,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(li));
}
// 2. [修改] 根据基地址的类型,生成不同的指令来获取基地址
// 2. 根据基地址的类型,生成不同的指令来获取基地址
auto base_addr_vreg = getNewVReg(Type::getIntType()); // 创建一个新的临时vreg来存放基地址
// 情况一:基地址是局部栈变量
@ -452,7 +430,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
}
}
// [V2优点] 在BINARY节点内部按需加载常量操作数。
// 在BINARY节点内部按需加载常量操作数。
auto load_val_if_const = [&](Value* val) {
if (auto c = dynamic_cast<ConstantValue*>(val)) {
if (DEBUG) {
@ -483,7 +461,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
auto dest_vreg = getVReg(bin);
auto lhs_vreg = getVReg(lhs);
// [V2优点] 融合 ADDIW 优化。
// 融合 ADDIW 优化。
if (rhs_is_imm_opt) {
auto rhs_const = dynamic_cast<ConstantValue*>(rhs);
auto instr = std::make_unique<MachineInstr>(RVOpcodes::ADDIW);
@ -539,6 +517,15 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kSra: {
auto rhs_const = dynamic_cast<ConstantInteger*>(rhs);
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SRAIW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<ImmOperand>(rhs_const->getInt()));
CurMBB->addInstruction(std::move(instr));
break;
}
case BinaryInst::kICmpEQ: { // 等于 (a == b) -> (subw; seqz)
auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
sub->addOperand(std::make_unique<RegOperand>(dest_vreg));
@ -758,11 +745,83 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFtoI: { // 浮点 to 整数
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FCVT_W_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是整数vreg
instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是浮点vreg
CurMBB->addInstruction(std::move(instr));
case Instruction::kFtoI: { // 浮点 to 整数 (带向下取整)
// 目标:实现 floor(x) 的效果, C/C++中浮点转整数是截断(truncate)
// 对于正数floor(x) == truncate(x)
// RISC-V的 fcvt.w.s 默认是“四舍五入到偶数”
// 我们需要手动实现截断逻辑
// 逻辑:
// temp_i = fcvt.w.s(x) // 四舍五入
// temp_f = fcvt.s.w(temp_i) // 转回浮点
// if (x < temp_f) { // 如果原数更小,说明被“五入”了
// result = temp_i - 1
// } else {
// result = temp_i
// }
auto temp_i_vreg = getNewVReg(Type::getIntType());
auto temp_f_vreg = getNewVReg(Type::getFloatType());
auto cmp_vreg = getNewVReg(Type::getIntType());
// 1. fcvt.w.s temp_i_vreg, src_vreg
auto fcvt_w = std::make_unique<MachineInstr>(RVOpcodes::FCVT_W_S);
fcvt_w->addOperand(std::make_unique<RegOperand>(temp_i_vreg));
fcvt_w->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(fcvt_w));
// 2. fcvt.s.w temp_f_vreg, temp_i_vreg
auto fcvt_s = std::make_unique<MachineInstr>(RVOpcodes::FCVT_S_W);
fcvt_s->addOperand(std::make_unique<RegOperand>(temp_f_vreg));
fcvt_s->addOperand(std::make_unique<RegOperand>(temp_i_vreg));
CurMBB->addInstruction(std::move(fcvt_s));
// 3. flt.s cmp_vreg, src_vreg, temp_f_vreg
auto flt = std::make_unique<MachineInstr>(RVOpcodes::FLT_S);
flt->addOperand(std::make_unique<RegOperand>(cmp_vreg));
flt->addOperand(std::make_unique<RegOperand>(src_vreg));
flt->addOperand(std::make_unique<RegOperand>(temp_f_vreg));
CurMBB->addInstruction(std::move(flt));
// 创建标签
int unique_id = this->local_label_counter++;
std::string rounded_up_label = MFunc->getName() + "_ftoi_rounded_up_" + std::to_string(unique_id);
std::string done_label = MFunc->getName() + "_ftoi_done_" + std::to_string(unique_id);
// 4. bne cmp_vreg, x0, rounded_up_label
auto bne = std::make_unique<MachineInstr>(RVOpcodes::BNE);
bne->addOperand(std::make_unique<RegOperand>(cmp_vreg));
bne->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
bne->addOperand(std::make_unique<LabelOperand>(rounded_up_label));
CurMBB->addInstruction(std::move(bne));
// 5. else 分支: mv dest_vreg, temp_i_vreg
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(dest_vreg));
mv->addOperand(std::make_unique<RegOperand>(temp_i_vreg));
CurMBB->addInstruction(std::move(mv));
// 6. j done_label
auto j = std::make_unique<MachineInstr>(RVOpcodes::J);
j->addOperand(std::make_unique<LabelOperand>(done_label));
CurMBB->addInstruction(std::move(j));
// 7. rounded_up_label:
auto label_up = std::make_unique<MachineInstr>(RVOpcodes::LABEL);
label_up->addOperand(std::make_unique<LabelOperand>(rounded_up_label));
CurMBB->addInstruction(std::move(label_up));
// 8. addiw dest_vreg, temp_i_vreg, -1
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDIW);
addi->addOperand(std::make_unique<RegOperand>(dest_vreg));
addi->addOperand(std::make_unique<RegOperand>(temp_i_vreg));
addi->addOperand(std::make_unique<ImmOperand>(-1));
CurMBB->addInstruction(std::move(addi));
// 9. done_label:
auto label_done = std::make_unique<MachineInstr>(RVOpcodes::LABEL);
label_done->addOperand(std::make_unique<LabelOperand>(done_label));
CurMBB->addInstruction(std::move(label_done));
break;
}
case Instruction::kFNeg: { // 浮点取负
@ -943,7 +1002,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
// --- 步骤 3: 生成CALL指令 ---
auto call_instr = std::make_unique<MachineInstr>(RVOpcodes::CALL);
// [协议] 如果函数有返回值,将它的目标虚拟寄存器作为第一个操作数
// 如果函数有返回值,将它的目标虚拟寄存器作为第一个操作数
if (!call->getType()->isVoid()) {
unsigned dest_vreg = getVReg(call);
call_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
@ -1020,7 +1079,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
} else {
// --- 处理整数/指针返回值 ---
// 返回值需要被放入 a0
// [V2优点] 在RETURN节点内加载常量返回值
// 在RETURN节点内加载常量返回值
if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) {
auto li_instr = std::make_unique<MachineInstr>(RVOpcodes::LI);
li_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
@ -1034,7 +1093,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
}
}
}
// [V1设计保留] 函数尾声epilogue不由RETURN节点生成
// 函数尾声epilogue不由RETURN节点生成
// 而是由后续的AsmPrinter或其它Pass统一处理这是一种常见且有效的模块化设计。
auto ret_mi = std::make_unique<MachineInstr>(RVOpcodes::RET);
CurMBB->addInstruction(std::move(ret_mi));
@ -1048,7 +1107,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
auto then_bb_name = cond_br->getThenBlock()->getName();
auto else_bb_name = cond_br->getElseBlock()->getName();
// [优化] 检查分支条件是否为编译期常量
// 检查分支条件是否为编译期常量
if (auto const_cond = dynamic_cast<ConstantValue*>(condition)) {
// 如果条件是常量直接生成一个无条件跳转J而不是BNE
if (const_cond->getInt() != 0) { // 条件为 true
@ -1063,7 +1122,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
}
// 如果条件不是常量,则执行标准流程
else {
// [修复] 为条件变量生成加载指令(如果它是常量的话,尽管上面已经处理了)
// 为条件变量生成加载指令(如果它是常量的话,尽管上面已经处理了)
// 这一步是为了逻辑完整,以防有其他类型的常量没有被捕获
if (auto const_val = dynamic_cast<ConstantValue*>(condition)) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
@ -1097,7 +1156,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
}
case DAGNode::MEMSET: {
// [V1设计保留] Memset的核心展开逻辑在虚拟寄存器层面是正确的无需修改。
// Memset的核心展开逻辑在虚拟寄存器层面是正确的无需修改。
// 之前的bug是由于其输入地址、值、大小的虚拟寄存器未被正确初始化。
// 在修复了CONSTANT/ALLOCA_ADDR的加载问题后此处的逻辑现在可以正常工作。
@ -1280,14 +1339,19 @@ void RISCv64ISel::selectNode(DAGNode* node) {
if (stride != 0) {
// --- 为当前索引和步长生成偏移计算指令 ---
auto offset_vreg = getNewVReg();
auto index_vreg = getVReg(indexValue);
// 如果索引是常量,先用 LI 指令加载到虚拟寄存器
// 处理索引 - 区分常量与动态值
unsigned index_vreg;
if (auto const_index = dynamic_cast<ConstantValue*>(indexValue)) {
// 对于常量索引,直接创建新的虚拟寄存器
index_vreg = getNewVReg();
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(index_vreg));
li->addOperand(std::make_unique<ImmOperand>(const_index->getInt()));
CurMBB->addInstruction(std::move(li));
} else {
// 对于动态索引,使用已存在的虚拟寄存器
index_vreg = getVReg(indexValue);
}
// 优化如果步长是1可以直接移动(MV)作为偏移量,无需乘法
@ -1445,7 +1509,7 @@ std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicB
// 依次添加所有索引作为后续的操作数
for (auto index : gep->getIndices()) {
// [修复] 从 Use 对象中获取真正的 Value*
// 从 Use 对象中获取真正的 Value*
gep_node->operands.push_back(get_operand_node(index->getValue(), value_to_node, nodes_storage));
}
} else if (auto load = dynamic_cast<LoadInst*>(inst)) {
@ -1473,7 +1537,7 @@ std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicB
}
}
}
if (bin->getKind() >= Instruction::kFAdd) { // 假设浮点指令枚举值更大
if (bin->isFPBinary()) { // 假设浮点指令枚举值更大
auto fbin_node = create_node(DAGNode::FBINARY, bin, value_to_node, nodes_storage);
fbin_node->operands.push_back(get_operand_node(bin->getLhs(), value_to_node, nodes_storage));
fbin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
@ -1549,7 +1613,7 @@ unsigned RISCv64ISel::getTypeSizeInBytes(Type* type) {
}
}
// [新] 打印DAG图以供调试的辅助函数
// 打印DAG图以供调试的辅助函数
void RISCv64ISel::print_dag(const std::vector<std::unique_ptr<DAGNode>>& dag, const std::string& bb_name) {
// 检查是否有DEBUG宏或者全局变量避免在非调试模式下打印
// if (!DEBUG) return;
@ -1645,4 +1709,8 @@ void RISCv64ISel::print_dag(const std::vector<std::unique_ptr<DAGNode>>& dag, co
std::cerr << "======================================\n\n";
}
unsigned int RISCv64ISel::getVRegCounter() const {
return vreg_counter;
}
} // namespace sysy

View File

@ -44,7 +44,7 @@ std::string regToString(PhysicalReg reg) {
}
}
// [新增] 打印栈帧信息的完整实现
// 打印栈帧信息的完整实现
void MachineFunction::dumpStackFrameInfo(std::ostream& os) const {
const StackFrameInfo& info = frame_info;

View File

@ -55,12 +55,41 @@ void RISCv64RegAlloc::run() {
if (DEBUG) std::cerr << "===== Running Graph Coloring Register Allocation for function: " << MFunc->getName() << " =====\n";
while (true) {
const int MAX_ITERATIONS = 50;
int iteration = 0;
while (iteration++ < MAX_ITERATIONS) {
if (doAllocation()) {
break;
} else {
rewriteProgram();
if (DEBUG) std::cerr << "--- Spilling detected, re-running allocation ---\n";
if (DEBUG) std::cerr << "--- Spilling detected, re-running allocation (iteration " << iteration << ") ---\n";
if (iteration >= MAX_ITERATIONS) {
std::cerr << "ERROR: Register allocation failed to converge after " << MAX_ITERATIONS << " iterations\n";
std::cerr << " Spill worklist size: " << spillWorklist.size() << "\n";
std::cerr << " Total nodes: " << (initial.size() + coloredNodes.size()) << "\n";
// Emergency spill remaining nodes to break the loop
std::cerr << " Emergency spilling remaining spill worklist nodes...\n";
for (unsigned node : spillWorklist) {
spilledNodes.insert(node);
}
// Also spill any nodes that didn't get colors
std::set<unsigned> uncolored;
for (unsigned node : initial) {
if (color_map.find(node) == color_map.end()) {
uncolored.insert(node);
}
}
for (unsigned node : uncolored) {
spilledNodes.insert(node);
}
// Force completion
break;
}
}
}
@ -93,7 +122,7 @@ bool RISCv64RegAlloc::doAllocation() {
}
void RISCv64RegAlloc::precolorByCallingConvention() {
// [新增] 在处理前,先清空颜色相关的状态,确保重试时不会出错
// 在处理前,先清空颜色相关的状态,确保重试时不会出错
color_map.clear();
coloredNodes.clear();
@ -122,30 +151,6 @@ void RISCv64RegAlloc::precolorByCallingConvention() {
}
}
// // --- 部分2为CALL指令的返回值预着色 ---
// for (auto& mbb : MFunc->getBlocks()) {
// for (auto& instr : mbb->getInstructions()) {
// if (instr->getOpcode() == 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()) {
// unsigned ret_vreg = reg_op->getVRegNum();
// assert(vreg_to_value_map.count(ret_vreg) && "Return vreg not found!");
// Value* ret_val = vreg_to_value_map.at(ret_vreg);
// if (ret_val->getType()->isFloat()) {
// color_map[ret_vreg] = PhysicalReg::F10; // fa0
// } else {
// color_map[ret_vreg] = PhysicalReg::A0; // a0
// }
// }
// }
// }
// }
// }
// 将所有预着色的vreg视为已着色节点
for(const auto& pair : color_map) {
coloredNodes.insert(pair.first);
@ -168,7 +173,7 @@ void RISCv64RegAlloc::initialize() {
spillWorklist.clear();
spilledNodes.clear();
coalescedNodes.clear();
coloredNodes.clear(); // [修正] 恢复对这两个集合的清除
coloredNodes.clear();
selectStack.clear();
coalescedMoves.clear();
@ -181,7 +186,7 @@ void RISCv64RegAlloc::initialize() {
degree.clear();
moveList.clear();
alias.clear();
color_map.clear(); // [修正] 恢复对 color_map 的清除
color_map.clear();
}
// 活跃性分析(此部分为标准数据流分析,与现有版本类似但更精细)
@ -197,7 +202,6 @@ void RISCv64RegAlloc::analyzeLiveness() {
VRegSet uses, defs;
for (const auto& instr_ptr : mbb->getInstructions()) {
VRegSet instr_use, instr_def;
// 使用新的、能看到物理寄存器的版本
getInstrUseDef_Liveness(instr_ptr.get(), instr_use, instr_def);
for (unsigned u : instr_use) {
if (defs.find(u) == defs.end()) uses.insert(u);
@ -238,7 +242,7 @@ void RISCv64RegAlloc::analyzeLiveness() {
const MachineInstr* instr = instr_it->get();
live_out_map[instr] = current_live;
VRegSet use, def;
// 使用新的、能看到物理寄存器的版本
getInstrUseDef_Liveness(instr, use, def);
for(auto d : def) current_live.erase(d);
for(auto u : use) current_live.insert(u);
@ -247,7 +251,6 @@ void RISCv64RegAlloc::analyzeLiveness() {
}
}
// [最终修正] 包含了所有正确逻辑和您已有调试代码的完整版本
void RISCv64RegAlloc::build() {
initial.clear();
RISCv64AsmPrinter printer_inside_build(MFunc);
@ -403,15 +406,33 @@ void RISCv64RegAlloc::build() {
}
// --- 规则 3: Live_Out 集合内部的【虚拟寄存器】形成完全图 ---
// [优化与修正] 使用更高效的遍历,避免重复调用 addEdge(A,B) 和 addEdge(B,A)
for (auto it1 = live_out.begin(); it1 != live_out.end(); ++it1) {
unsigned l1 = *it1;
// [关键修正] 只为虚拟寄存器 l1 添加边
if (precolored.count(l1)) continue;
// 使用更高效的遍历,避免重复调用 addEdge(A,B) 和 addEdge(B,A)
// 添加限制以防止过度密集的图
const size_t MAX_LIVE_OUT_SIZE = 32; // 限制最大活跃变量数
if (live_out.size() > MAX_LIVE_OUT_SIZE) {
// 对于大量活跃变量,使用更保守的边添加策略
// 只添加必要的边,而不是完全图
for (auto it1 = live_out.begin(); it1 != live_out.end(); ++it1) {
unsigned l1 = *it1;
if (precolored.count(l1)) continue;
// 只添加与定义变量相关的边
for (unsigned d : def) {
if (d != l1 && !precolored.count(d)) {
addEdge(l1, d);
}
}
}
} else {
// 对于较小的集合,使用原来的完全图方法
for (auto it1 = live_out.begin(); it1 != live_out.end(); ++it1) {
unsigned l1 = *it1;
if (precolored.count(l1)) continue;
for (auto it2 = std::next(it1); it2 != live_out.end(); ++it2) {
unsigned l2 = *it2;
addEdge(l1, l2);
for (auto it2 = std::next(it1); it2 != live_out.end(); ++it2) {
unsigned l2 = *it2;
addEdge(l1, l2);
}
}
}
}
@ -463,6 +484,17 @@ void RISCv64RegAlloc::coalesce() {
unsigned y = getAlias(*use.begin());
unsigned u, v;
if (precolored.count(y)) { u = y; v = x; } else { u = x; v = y; }
// 防御性检查,处理物理寄存器之间的传送指令
if (precolored.count(u) && precolored.count(v)) {
// 如果 u 和 v 都是物理寄存器,我们不能合并它们。
// 这通常是一条寄存器拷贝指令,例如 `mv a2, a1`。
// 把它加入 constrainedMoves 列表,然后直接返回,不再处理。
constrainedMoves.insert(move);
// addWorklist(u) 和 addWorklist(v) 在这里也不需要调用,
// 因为它们只对虚拟寄存器有意义。
return;
}
if (DEEPERDEBUG) std::cerr << "[Coalesce] Processing move between " << regIdToString(x)
<< " and " << regIdToString(y) << " (aliases " << regIdToString(u)
@ -484,8 +516,6 @@ void RISCv64RegAlloc::coalesce() {
addWorklist(v);
return; // 立即返回,不再进行后续检查
}
// --- 新的、拆分后的启发式检查逻辑 ---
bool pre_interfere = adjList.at(v).count(u);
@ -504,8 +534,6 @@ void RISCv64RegAlloc::coalesce() {
// --- 场景1u是物理寄存器使用 George 启发式 ---
if (DEEPERDEBUG) std::cerr << " -> Trying George Heuristic (u is precolored)...\n";
// ==================== [展开的 std::all_of 逻辑] ====================
// 步骤 1: 独立调用 adjacent(v) 获取邻居集合
VRegSet neighbors_of_v = adjacent(v);
if (DEEPERDEBUG) {
@ -537,7 +565,6 @@ void RISCv64RegAlloc::coalesce() {
if (DEEPERDEBUG) {
std::cerr << " -> George Heuristic final result: " << (george_ok ? "OK" : "FAIL") << "\n";
}
// =================================================================
if (george_ok) {
can_coalesce = true;
@ -622,11 +649,11 @@ void RISCv64RegAlloc::assignColors() {
}
}
// 步骤 2: [最终修正] 完整、正确地处理 coalescedNodes
// 步骤 2: 处理 coalescedNodes
for (unsigned n : coalescedNodes) {
unsigned root_alias = getAlias(n);
// --- 新的、健壮的逻辑,处理所有三种可能性 ---
// --- 处理所有三种可能性 ---
// 情况 1: 别名本身就是物理寄存器 (修复当前bug)
if (precolored.count(root_alias)) {
@ -649,9 +676,13 @@ void RISCv64RegAlloc::assignColors() {
// 重写程序,插入溢出代码
void RISCv64RegAlloc::rewriteProgram() {
// 1. 为溢出的旧vreg在栈上分配空间
StackFrameInfo& frame_info = MFunc->getFrameInfo();
int spill_base_offset = frame_info.locals_size + frame_info.callee_saved_size;
// 使用 EFI Pass 确定的 locals_end_offset 作为溢出分配的基准。
// locals_end_offset 本身是负数,代表局部变量区域的下边界地址。
int spill_current_offset = frame_info.locals_end_offset - frame_info.spill_size;
// 保存溢出区域的起始点,用于最后计算总的 spill_size
const int spill_start_offset = frame_info.locals_end_offset;
for (unsigned vreg : spilledNodes) {
if (frame_info.spill_offsets.count(vreg)) continue;
@ -663,11 +694,19 @@ void RISCv64RegAlloc::rewriteProgram() {
size = 8; // pointer
}
spill_base_offset += size;
spill_base_offset = (spill_base_offset + 7) & ~7;
frame_info.spill_offsets[vreg] = -spill_base_offset; // [修正] 溢出槽也使用负偏移量
// 在当前偏移基础上继续向下(地址变得更负)分配空间
spill_current_offset -= size;
// 对齐新的、更小的地址RISC-V 要求8字节对齐
spill_current_offset = spill_current_offset & ~7;
// 将计算出的、不会冲突的正确偏移量存入 spill_offsets
frame_info.spill_offsets[vreg] = spill_current_offset;
}
frame_info.spill_size = spill_base_offset - (frame_info.locals_size + frame_info.callee_saved_size);
// 更新总的溢出区域大小。
// spill_size = -(结束偏移 - 开始偏移)
frame_info.spill_size = -(spill_current_offset - spill_start_offset);
// 2. 遍历所有指令,重写代码
for (auto& mbb : MFunc->getBlocks()) {
@ -711,7 +750,7 @@ void RISCv64RegAlloc::rewriteProgram() {
}
}
// c. [核心修正] 创建一条全新的指令用新vreg替换旧vreg
// c. 创建一条全新的指令用新vreg替换旧vreg
auto new_instr = std::make_unique<MachineInstr>(instr_ptr->getOpcode());
for (const auto& op : instr_ptr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) {
@ -771,6 +810,11 @@ void RISCv64RegAlloc::rewriteProgram() {
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(old_vreg))
));
new_instructions.push_back(std::move(store));
if (DEEPERDEBUG) {
std::cerr << "[Spill] Inserted spill store for %vreg" << old_vreg
<< " at offset " << frame_info.spill_offsets.at(old_vreg)
<< " with new temp vreg " << regIdToString(new_temp_vreg) << ".\n";
}
}
}
mbb->getInstructions() = std::move(new_instructions);
@ -781,7 +825,7 @@ void RISCv64RegAlloc::rewriteProgram() {
}
/**
* @brief [最终修正] 获取一条指令完整的【虚拟】使用/定义寄存器集合
* @brief 获取一条指令完整的【虚拟】使用/定义寄存器集合
* 这个函数将服务于图的构建收集initial节点等
*/
void RISCv64RegAlloc::getInstrUseDef(const MachineInstr* instr, VRegSet& use, VRegSet& def) {
@ -832,10 +876,8 @@ void RISCv64RegAlloc::getInstrUseDef(const MachineInstr* instr, VRegSet& use, VR
}
}
// in file: RISCv64RegAlloc.cpp
/**
* @brief [最终修复版] 获取一条指令完整的、包含物理寄存器的Use/Def集合
* @brief 获取一条指令完整的、包含物理寄存器的Use/Def集合
* 这个函数专门服务于活跃性分析,现已补全所有指令(包括伪指令)的逻辑。
*/
void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet& use, VRegSet& def) {
@ -943,7 +985,6 @@ void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet
else if (opcode == RVOpcodes::JALR) {
// JALR rd, rs1, imm. Def: rd, Use: rs1.
// 同时也隐式定义了ra(x1)但通常rd就是ra。为精确我们只处理显式操作数。
// 旧版本逻辑def.insert(ra); first_reg_is_def = false; -> 这是不精确的
def.insert(get_any_reg_id(operands[0].get()));
use.insert(get_any_reg_id(operands[1].get()));
}
@ -952,7 +993,7 @@ void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet
use.insert(offset + static_cast<unsigned>(PhysicalReg::A0));
use.insert(offset + static_cast<unsigned>(PhysicalReg::F10)); // F10 is fa0
}
// [关键Bug修复] 添加对 PSEUDO_KEEPALIVE 的处理
// 添加对 PSEUDO_KEEPALIVE 的处理
else if (opcode == RVOpcodes::PSEUDO_KEEPALIVE) {
// keepalive的所有操作数都是use以确保它们的生命周期延续到该点
for (const auto& op : operands) {
@ -1212,7 +1253,7 @@ bool RISCv64RegAlloc::briggsHeuristic(unsigned u, unsigned v) {
// George启发式
bool RISCv64RegAlloc::georgeHeuristic(unsigned t, unsigned u) {
// 关键修正:如果 t 不是一个待分配的虚拟寄存器(即它是物理寄存器),
// 如果 t 不是一个待分配的虚拟寄存器(即它是物理寄存器),
// 那么它已经被预着色,总是满足 George 启发式条件。
// 我们通过检查 degree.count(t) 来判断 t 是否在我们的虚拟寄存器工作集中。
if (degree.count(t) == 0) {
@ -1224,44 +1265,6 @@ bool RISCv64RegAlloc::georgeHeuristic(unsigned t, unsigned u) {
return degree.at(t) < K || precolored.count(u) || adjList.at(t).count(u);
}
// void RISCv64RegAlloc::combine(unsigned u, unsigned v) {
// // 1. 从相应的工作列表中移除即将被合并的节点 v
// if (freezeWorklist.count(v)) {
// freezeWorklist.erase(v);
// } else {
// spillWorklist.erase(v);
// }
// // 2. 将 v 加入 coalescedNodes 集合,并设置其别名
// coalescedNodes.insert(v);
// alias[v] = u;
// // 3. 将 v 的传送指令列表合并到 u
// if (moveList.count(u) && moveList.count(v)) {
// moveList.at(u).insert(moveList.at(v).begin(), moveList.at(v).end());
// } else if (moveList.count(v)) {
// moveList[u] = moveList.at(v);
// }
// // [Bug修复] 移除了论文伪代码中不存在的 enableMoves({v}) 调用。
// // 4. [核心Bug修复] 遍历 v 的“当前有效”邻居 t (使用 adjacent(v) 而非 adjList.at(v))
// // 将它们与 u 连接,并更新它们的度数。
// for (unsigned t : adjacent(v)) {
// addEdge(t, u);
// decrementDegree(t);
// }
// // 5. 检查合并后的节点 u 的状态,如果其度数变高,可能需要将其移到 spillWorklist
// if (!precolored.count(u)) {
// int K = isFPVReg(u) ? K_fp : K_int;
// if (degree.at(u) >= K && freezeWorklist.count(u)) {
// freezeWorklist.erase(u);
// spillWorklist.insert(u);
// }
// }
// }
void RISCv64RegAlloc::combine(unsigned u, unsigned v) {
freezeWorklist.erase(v);
spillWorklist.erase(v);
@ -1377,9 +1380,9 @@ void RISCv64RegAlloc::applyColoring() {
// 使用 setPReg 将虚拟寄存器转换为物理寄存器
reg_op->setPReg(color_map.at(vreg));
} else {
// 如果一个vreg在成功分配后仍然没有颜色这是一个错误
std::cerr << "FATAL: Virtual register %vreg" << vreg << " has no color after allocation!\n";
assert(false && "Virtual register has no color after allocation!");
// 如果一个vreg在成功分配后仍然没有颜色可能是紧急溢出
// std::cerr << "WARNING: Virtual register %vreg" << vreg << " has no color after allocation, treating as spilled\n";
// 在紧急溢出情况下,使用临时寄存器
reg_op->setPReg(PhysicalReg::T6);
}
}
@ -1391,7 +1394,7 @@ void RISCv64RegAlloc::applyColoring() {
if (color_map.count(vreg)) {
reg_op->setPReg(color_map.at(vreg));
} else {
assert(false && "Virtual register in memory operand has no color!");
// std::cerr << "WARNING: Virtual register in memory operand has no color, using T6\n";
reg_op->setPReg(PhysicalReg::T6);
}
}
@ -1483,7 +1486,6 @@ std::string RISCv64RegAlloc::regToString(PhysicalReg reg) {
std::string RISCv64RegAlloc::regIdToString(unsigned id) {
const unsigned offset = static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID);
// 使用更健壮的检查方式
if (id >= offset && precolored.count(id)) {
// 先减去偏移量,得到原始的、小的枚举值
PhysicalReg reg = static_cast<PhysicalReg>(id - offset);

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

@ -20,6 +20,8 @@ public:
void setStream(std::ostream& os) { OS = &os; }
// 辅助函数
std::string regToString(PhysicalReg reg);
std::string formatInstr(const MachineInstr *instr);
private:
// 打印各个部分
void printBasicBlock(MachineBasicBlock* mbb, bool debug = false);

View File

@ -24,7 +24,7 @@ private:
// 私有辅助函数,用于根据类型计算其占用的字节数。
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,7 +23,8 @@ public:
// 公开接口以便后续模块如RegAlloc可以查询或创建vreg
unsigned getVReg(Value* val);
unsigned getNewVReg() { return vreg_counter++; }
unsigned getNewVReg(Type* type);
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; }

View File

@ -39,14 +39,14 @@ enum class PhysicalReg {
// 用于内部表示物理寄存器在干扰图中的节点ID一个简单的特殊ID确保不与vreg_counter冲突
// 假设 vreg_counter 不会达到这么大的值
PHYS_REG_START_ID = 100000,
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,
// 移位指令
@ -280,14 +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; // [新增] 已排序的、需要存取的被调用者保存寄存器
std::map<unsigned, PhysicalReg> vreg_to_preg_map; // RegAlloc最终的分配结果
std::vector<PhysicalReg> callee_saved_regs_to_store; // 已排序的、需要存取的被调用者保存寄存器
};
// 机器函数

View File

@ -10,6 +10,8 @@
#include "PrologueEpilogueInsertion.h"
#include "EliminateFrameIndices.h"
#include "Pass.h"
#include "DivStrengthReduction.h"
namespace sysy {

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,6 +380,9 @@ 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 {
@ -394,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 {
@ -420,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 {
@ -446,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 {
@ -460,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());
@ -477,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 ---
@ -617,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
@ -633,21 +672,6 @@ class User : public Value {
explicit User(Type *type, const std::string &name = "") : Value(type, name) {}
public:
// ~User() override {
// // 当 User 对象被销毁时例如LoadInst 或 StoreInst 被删除时),
// // 它必须通知它所使用的所有 Value将对应的 Use 关系从它们的 uses 列表中移除。
// // 这样可以防止 Value 的 uses 列表中出现悬空的 Use 对象。
// for (const auto &use_ptr : operands) {
// // 确保 use_ptr 非空,并且其内部指向的 Value* 也非空
// // (虽然通常情况下不会为空,但为了健壮性考虑)
// if (use_ptr && use_ptr->getValue()) {
// use_ptr->getValue()->removeUse(use_ptr);
// }
// }
// // operands 向量本身是 std::vector<std::shared_ptr<Use>>
// // 在此析构函数结束后operands 向量会被销毁,其内部的 shared_ptr 也会被释放,
// // 如果 shared_ptr 引用计数降为0Use 对象本身也会被销毁。
// }
unsigned getNumOperands() const { return operands.size(); } ///< 获取操作数数量
auto operand_begin() const { return operands.begin(); } ///< 返回操作数列表的开头迭代器
auto operand_end() const { return operands.end(); } ///< 返回操作数列表的结尾迭代器
@ -657,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) {
@ -670,6 +690,9 @@ class User : public Value {
} ///< 增加多个操作数
void replaceOperand(unsigned index, Value *value); ///< 替换操作数
void setOperand(unsigned index, Value *value); ///< 设置操作数
/// 清理用户的所有操作数使用关系
void cleanup();
};
/*!
@ -704,6 +727,7 @@ class Instruction : public User {
kFCmpGE = 0x1UL << 20,
kAnd = 0x1UL << 21,
kOr = 0x1UL << 22,
// kXor = 0x1UL << 46,
// Unary
kNeg = 0x1UL << 23,
kNot = 0x1UL << 24,
@ -728,6 +752,10 @@ class Instruction : public User {
kPhi = 0x1UL << 39,
kBitItoF = 0x1UL << 40,
kBitFtoI = 0x1UL << 41,
kSrl = 0x1UL << 42, // 逻辑右移
kSll = 0x1UL << 43, // 逻辑左移
kSra = 0x1UL << 44, // 算术右移
kMulh = 0x1UL << 45
};
protected:
@ -745,57 +773,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:
@ -803,27 +831,41 @@ 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 kSrl:
return "lshr";
case kSll:
return "shl";
case kSra:
return "ashr";
case kMulh:
return "mulh";
default:
return "Unknown";
}
@ -835,11 +877,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 | kSrl | kSll | 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 =
@ -886,6 +932,10 @@ public:
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;
@ -907,58 +957,62 @@ 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));}
//增加llvm同名方法实现获取value和block
Value* getIncomingValue(unsigned k) const {return getOperand(2 * k);} ///< 获取位置为k的值
BasicBlock* getIncomingBlock(unsigned k) const {return dynamic_cast<BasicBlock*>(getOperand(2 * k + 1));}
Value* getIncomingValue(BasicBlock* blk) const {
return getvalfromBlk(blk);
} ///< 获取指定基本块的传入值
BasicBlock* getIncomingBlock(Value* val) const {
return getBlkfromVal(val);
} ///< 获取指定值的传入基本块
void replaceIncoming(BasicBlock *oldBlock, BasicBlock *newBlock, Value *newValue){
delBlk(oldBlock);
addIncoming(newValue, newBlock);
}
auto& getincomings() const {return blk2val;} ///< 获取所有的基本块和对应的值
Value* getvalfromBlk(BasicBlock* blk) const ;
BasicBlock* getBlkfromVal(Value* val) const ;
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);
auto getIncomingValues() const {
std::vector<std::pair<BasicBlock*, Value*>> result;
for (const auto& [block, value] : blk2val) {
result.emplace_back(block, value);
}
return result;
}
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 removeIncoming(BasicBlock *block){
delBlk(block);
}
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;
};
@ -967,16 +1021,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.
@ -994,7 +1046,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.
@ -1073,6 +1125,7 @@ public:
// 后端处理数组访存操作时需要创建计算地址的指令,需要在外部构造 BinaryInst 对象
return new BinaryInst(kind, type, lhs, rhs, parent, name);
}
void print(std::ostream& os) const override;
}; // class BinaryInst
//! The return statement
@ -1093,6 +1146,7 @@ class ReturnInst : public Instruction {
Value* getReturnValue() const {
return hasReturnValue() ? getOperand(0) : nullptr;
}
void print(std::ostream& os) const override;
};
//! Unconditional branch
@ -1122,7 +1176,7 @@ public:
}
return succs;
}
void print(std::ostream& os) const override;
}; // class UncondBrInst
//! Conditional branch
@ -1162,7 +1216,7 @@ public:
}
return succs;
}
void print(std::ostream& os) const override;
}; // class CondBrInst
class UnreachableInst : public Instruction {
@ -1170,7 +1224,7 @@ 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
@ -1188,7 +1242,7 @@ public:
Type* getAllocatedType() const {
return getType()->as<PointerType>()->getBaseType();
} ///< 获取分配的类型
void print(std::ostream& os) const override;
}; // class AllocaInst
@ -1226,6 +1280,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
@ -1243,7 +1298,7 @@ protected:
public:
Value* getPointer() const { return getOperand(0); }
void print(std::ostream& os) const override;
}; // class LoadInst
//! Store a value to memory address specified by a pointer value
@ -1262,7 +1317,7 @@ protected:
public:
Value* getValue() const { return getOperand(0); }
Value* getPointer() const { return getOperand(1); }
void print(std::ostream& os) const override;
}; // class StoreInst
//! Memset instruction
@ -1292,7 +1347,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;
@ -1310,6 +1365,11 @@ public:
public:
Function* getParent() const { return func; }
int getIndex() const { return index; }
/// 清理参数的使用关系
void cleanup();
void print(std::ostream& os) const;
};
@ -1375,8 +1435,19 @@ protected:
auto is_same_ptr = [blockToRemove](const std::unique_ptr<BasicBlock> &ptr) { return ptr.get() == blockToRemove; };
blocks.remove_if(is_same_ptr);
}
BasicBlock* addBasicBlock(const std::string &name, BasicBlock *before) {
// 在指定的基本块之前添加一个新的基本块
auto it = std::find_if(blocks.begin(), blocks.end(),
[before](const std::unique_ptr<BasicBlock> &ptr) { return ptr.get() == before; });
if (it != blocks.end()) {
auto newblk = blocks.emplace(it, std::make_unique<BasicBlock>(this, name));
return newblk->get(); // 返回新添加的基本块指针
}
assert(false && "BasicBlock to insert before not found!");
return nullptr; // 如果没有找到指定的基本块则返回nullptr
} ///< 添加一个新的基本块到某个基本块之前
BasicBlock* addBasicBlock(const std::string &name = "") {
blocks.emplace_back(new BasicBlock(this, name));
blocks.emplace_back(std::make_unique<BasicBlock>(this, name));
return blocks.back().get();
}
BasicBlock* addBasicBlock(BasicBlock *block) {
@ -1387,6 +1458,11 @@ protected:
blocks.emplace_front(block);
return block;
}
/// 清理函数中的所有使用关系
void cleanup();
void print(std::ostream& os) const;
};
//! Global value declared at file scope
@ -1452,6 +1528,7 @@ public:
return getByIndex(index);
} ///< 通过多维索引indices获取初始值
const ValueCounter& getInitValues() const { return initValues; }
void print(std::ostream& os) const;
}; // class GlobalValue
@ -1509,6 +1586,8 @@ class ConstantVariable : public Value {
return getByIndex(index);
} ///< 通过多维索引indices获取初始值
const ValueCounter& getInitValues() const { return initValues; } ///< 获取初始值
void print(std::ostream& os) const;
void print_init(std::ostream& os) const;
};
using SymbolTableNode = struct SymbolTableNode {
@ -1531,6 +1610,8 @@ 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; ///< 获取全局常量列表
void enterNewScope(); ///< 进入新的作用域
@ -1538,6 +1619,9 @@ class SymbolTable {
bool isInGlobalScope() const; ///< 是否位于全局作用域
void enterGlobalScope(); ///< 进入全局作用域
bool isCurNodeNull() { return curNode == nullptr; }
/// 清理符号表中的所有内容
void cleanup();
};
//! IR unit for representing a SysY compile unit
@ -1590,6 +1674,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和当前作用域获取变量
@ -1602,7 +1692,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();
@ -1622,6 +1712,11 @@ class Module {
void leaveScope() { variableTable.leaveScope(); } ///< 离开作用域
bool isInGlobalArea() const { return variableTable.isInGlobalScope(); } ///< 是否位于全局作用域
/// 清理模块中的所有对象,包括函数、基本块、指令等
void cleanup();
void print(std::ostream& os) const;
};
/*!

View File

@ -217,6 +217,18 @@ class IRBuilder {
BinaryInst * createOrInst(Value *lhs, Value *rhs, const std::string &name = "") {
return createBinaryInst(Instruction::kOr, Type::getIntType(), lhs, rhs, name);
} ///< 创建按位或指令
BinaryInst * createSllInst(Value *lhs, Value *rhs, const std::string &name = "") {
return createBinaryInst(Instruction::kSll, Type::getIntType(), lhs, rhs, name);
} ///< 创建逻辑左移指令
BinaryInst * createSrlInst(Value *lhs, Value *rhs, const std::string &name = "") {
return createBinaryInst(Instruction::kSrl, 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()) {
@ -344,38 +356,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,246 @@
#pragma once
#include "IR.h"
#include "Pass.h"
#include <map>
#include <set>
#include <vector>
#include <memory>
namespace sysy {
// 前向声明
class MemoryLocation;
class AliasAnalysisResult;
/**
* @brief 别名关系类型
* 按风险等级递增排序
*/
enum class AliasType {
NO_ALIAS = 0, // 确定无别名 (不同的局部数组)
SELF_ALIAS = 1, // 自别名 (同一数组的不同索引)
POSSIBLE_ALIAS = 2, // 可能有别名 (函数参数数组)
UNKNOWN_ALIAS = 3 // 未知 (保守估计)
};
/**
* @brief 内存位置信息
* 描述一个内存访问的基础信息
*/
struct MemoryLocation {
Value* basePointer; // 基指针 (剥离GEP后的真实基址)
Value* accessPointer; // 访问指针 (包含索引信息)
// 分类信息
bool isLocalArray; // 是否为局部数组
bool isFunctionParameter; // 是否为函数参数
bool isGlobalArray; // 是否为全局数组
// 索引信息
std::vector<Value*> indices; // GEP索引列表
bool hasConstantIndices; // 是否为常量索引
bool hasLoopVariableIndex; // 是否包含循环变量
int constantOffset; // 常量偏移量 (仅当全部为常量时有效)
// 访问模式
bool hasReads; // 是否有读操作
bool hasWrites; // 是否有写操作
std::vector<Instruction*> accessInsts; // 所有访问指令
MemoryLocation(Value* base, Value* access)
: basePointer(base), accessPointer(access),
isLocalArray(false), isFunctionParameter(false), isGlobalArray(false),
hasConstantIndices(false), hasLoopVariableIndex(false), constantOffset(0),
hasReads(false), hasWrites(false) {}
};
/**
* @brief 别名分析结果
* 存储一个函数的完整别名分析信息
*/
class AliasAnalysisResult : public AnalysisResultBase {
public:
AliasAnalysisResult(Function *F) : AssociatedFunction(F) {}
~AliasAnalysisResult() override = default;
// ========== 基础查询接口 ==========
/**
* 查询两个指针之间的别名关系
*/
AliasType queryAlias(Value* ptr1, Value* ptr2) const;
/**
* 查询指针的内存位置信息
*/
const MemoryLocation* getMemoryLocation(Value* ptr) const;
/**
* 获取所有内存位置
*/
const std::map<Value*, std::unique_ptr<MemoryLocation>>& getAllMemoryLocations() const {
return LocationMap;
}
// ========== 高级查询接口 ==========
/**
* 检查指针是否为局部数组
*/
bool isLocalArray(Value* ptr) const;
/**
* 检查指针是否为函数参数数组
*/
bool isFunctionParameter(Value* ptr) const;
/**
* 检查指针是否为全局数组
*/
bool isGlobalArray(Value* ptr) const;
/**
* 检查指针是否使用常量索引
*/
bool hasConstantAccess(Value* ptr) const;
// ========== 统计接口 ==========
/**
* 获取各类别名类型的统计信息
*/
struct Statistics {
int totalQueries;
int noAlias;
int selfAlias;
int possibleAlias;
int unknownAlias;
int localArrays;
int functionParameters;
int globalArrays;
int constantAccesses;
};
Statistics getStatistics() const;
/**
* 打印别名分析结果 (调试用)
*/
void print() const;
void printStatics() const;
// ========== 内部方法 ==========
void addMemoryLocation(std::unique_ptr<MemoryLocation> location);
void addAliasRelation(Value* ptr1, Value* ptr2, AliasType type);
// ========== 公开数据成员 (供Pass使用) ==========
std::map<Value*, std::unique_ptr<MemoryLocation>> LocationMap; // 内存位置映射
std::map<std::pair<Value*, Value*>, AliasType> AliasMap; // 别名关系缓存
private:
Function *AssociatedFunction; // 关联的函数
// 分类存储
std::vector<Argument*> ArrayParameters; // 数组参数
std::vector<AllocaInst*> LocalArrays; // 局部数组
std::set<GlobalValue*> AccessedGlobals; // 访问的全局变量
};
/**
* @brief SysY语言特化的别名分析Pass
* 针对SysY语言特性优化的别名分析实现
*/
class SysYAliasAnalysisPass : public AnalysisPass {
public:
// 唯一的 Pass ID
static void *ID;
// 在这里开启激进分析策略
SysYAliasAnalysisPass() : AnalysisPass("SysYAliasAnalysis", Pass::Granularity::Function),
aggressiveParameterMode(false), parameterOptimizationEnabled(false) {}
// 实现 getPassID
void *getPassID() const override { return &ID; }
// 核心运行方法
bool runOnFunction(Function *F, AnalysisManager &AM) override;
// 获取分析结果
std::unique_ptr<AnalysisResultBase> getResult() override { return std::move(CurrentResult); }
// ========== 配置接口 ==========
/**
* 启用针对SysY评测的激进优化模式
* 在这种模式下,假设不同参数不会传入相同数组
*/
void enableSysYTestingMode() {
aggressiveParameterMode = true;
parameterOptimizationEnabled = true;
}
/**
* 使用保守的默认模式(适合通用场景)
*/
void useConservativeMode() {
aggressiveParameterMode = false;
parameterOptimizationEnabled = false;
}
private:
std::unique_ptr<AliasAnalysisResult> CurrentResult; // 当前函数的分析结果
// ========== 主要分析流程 ==========
void collectMemoryAccesses(Function* F); // 收集内存访问
void buildAliasRelations(Function* F); // 构建别名关系
void optimizeForSysY(Function* F); // SysY特化优化
// ========== 内存位置分析 ==========
std::unique_ptr<MemoryLocation> createMemoryLocation(Value* ptr);
Value* getBasePointer(Value* ptr); // 获取基指针
void analyzeMemoryType(MemoryLocation* location); // 分析内存类型
void analyzeIndexPattern(MemoryLocation* location); // 分析索引模式
// ========== 别名关系推断 ==========
AliasType analyzeAliasBetween(MemoryLocation* loc1, MemoryLocation* loc2);
AliasType compareIndices(MemoryLocation* loc1, MemoryLocation* loc2);
AliasType compareLocalArrays(MemoryLocation* loc1, MemoryLocation* loc2);
AliasType compareParameters(MemoryLocation* loc1, MemoryLocation* loc2);
AliasType compareWithGlobal(MemoryLocation* loc1, MemoryLocation* loc2);
AliasType compareMixedTypes(MemoryLocation* loc1, MemoryLocation* loc2);
// ========== SysY特化优化 ==========
void applySysYConstraints(Function* F); // 应用SysY语言约束
void optimizeParameterAnalysis(Function* F); // 优化参数分析
void optimizeArrayAccessAnalysis(Function* F); // 优化数组访问分析
// ========== 配置和策略控制 ==========
bool useAggressiveParameterAnalysis() const { return aggressiveParameterMode; }
bool enableParameterOptimization() const { return parameterOptimizationEnabled; }
void setAggressiveParameterMode(bool enable) { aggressiveParameterMode = enable; }
void setParameterOptimizationEnabled(bool enable) { parameterOptimizationEnabled = enable; }
// ========== 辅助优化方法 ==========
void optimizeConstantIndexAccesses(); // 优化常量索引访问
void optimizeSequentialAccesses(); // 优化顺序访问
// ========== 辅助方法 ==========
bool isConstantValue(Value* val); // 是否为常量
bool hasLoopVariableInIndices(const std::vector<Value*>& indices, Function* F);
int calculateConstantOffset(const std::vector<Value*>& indices);
void printStatistics() const; // 打印统计信息
private:
// ========== 配置选项 ==========
bool aggressiveParameterMode = false; // 激进的参数别名分析模式
bool parameterOptimizationEnabled = false; // 启用参数优化
};
} // namespace sysy

View File

@ -0,0 +1,242 @@
#pragma once
#include "IR.h"
#include "Pass.h"
#include <map>
#include <set>
#include <vector>
#include <memory>
#include <algorithm>
#include <unordered_set>
namespace sysy {
// 前向声明
class CallGraphAnalysisResult;
/**
* @brief 调用图节点信息
* 存储单个函数在调用图中的信息
*/
struct CallGraphNode {
Function* function; // 关联的函数
std::set<Function*> callers; // 调用此函数的函数集合
std::set<Function*> callees; // 此函数调用的函数集合
// 递归信息
bool isRecursive; // 是否参与递归调用
bool isSelfRecursive; // 是否自递归
int recursiveDepth; // 递归深度(-1表示无限递归)
// 调用统计
size_t totalCallers; // 调用者总数
size_t totalCallees; // 被调用函数总数
size_t callSiteCount; // 调用点总数
CallGraphNode(Function* f) : function(f), isRecursive(false),
isSelfRecursive(false), recursiveDepth(0), totalCallers(0),
totalCallees(0), callSiteCount(0) {}
};
/**
* @brief 调用图分析结果类
* 包含整个模块的调用图信息和查询接口
*/
class CallGraphAnalysisResult : public AnalysisResultBase {
public:
CallGraphAnalysisResult(Module* M) : AssociatedModule(M) {}
~CallGraphAnalysisResult() override = default;
// ========== 基础查询接口 ==========
/**
* 获取函数的调用图节点
*/
const CallGraphNode* getNode(Function* F) const {
auto it = nodes.find(F);
return (it != nodes.end()) ? it->second.get() : nullptr;
}
/**
* 获取函数的调用图节点非const版本
*/
CallGraphNode* getMutableNode(Function* F) {
auto it = nodes.find(F);
return (it != nodes.end()) ? it->second.get() : nullptr;
}
/**
* 获取所有函数节点
*/
const std::map<Function*, std::unique_ptr<CallGraphNode>>& getAllNodes() const {
return nodes;
}
/**
* 检查函数是否存在于调用图中
*/
bool hasFunction(Function* F) const {
return nodes.find(F) != nodes.end();
}
// ========== 调用关系查询 ==========
/**
* 检查是否存在从caller到callee的调用
*/
bool hasCallEdge(Function* caller, Function* callee) const {
auto node = getNode(caller);
return node && node->callees.count(callee) > 0;
}
/**
* 获取函数的所有调用者
*/
std::vector<Function*> getCallers(Function* F) const {
auto node = getNode(F);
if (!node) return {};
return std::vector<Function*>(node->callers.begin(), node->callers.end());
}
/**
* 获取函数的所有被调用函数
*/
std::vector<Function*> getCallees(Function* F) const {
auto node = getNode(F);
if (!node) return {};
return std::vector<Function*>(node->callees.begin(), node->callees.end());
}
// ========== 递归分析查询 ==========
/**
* 检查函数是否参与递归调用
*/
bool isRecursive(Function* F) const {
auto node = getNode(F);
return node && node->isRecursive;
}
/**
* 检查函数是否自递归
*/
bool isSelfRecursive(Function* F) const {
auto node = getNode(F);
return node && node->isSelfRecursive;
}
/**
* 获取递归深度
*/
int getRecursiveDepth(Function* F) const {
auto node = getNode(F);
return node ? node->recursiveDepth : 0;
}
// ========== 拓扑排序和SCC ==========
/**
* 获取函数的拓扑排序结果
* 保证被调用函数在调用函数之前
*/
const std::vector<Function*>& getTopologicalOrder() const {
return topologicalOrder;
}
/**
* 获取强连通分量列表
* 每个SCC表示一个递归函数群
*/
const std::vector<std::vector<Function*>>& getStronglyConnectedComponents() const {
return sccs;
}
/**
* 获取函数所在的SCC索引
*/
int getSCCIndex(Function* F) const {
auto it = functionToSCC.find(F);
return (it != functionToSCC.end()) ? it->second : -1;
}
// ========== 统计信息 ==========
struct Statistics {
size_t totalFunctions;
size_t totalCallEdges;
size_t recursiveFunctions;
size_t selfRecursiveFunctions;
size_t stronglyConnectedComponents;
size_t maxSCCSize;
double avgCallersPerFunction;
double avgCalleesPerFunction;
};
Statistics getStatistics() const;
/**
* 打印调用图分析结果
*/
void print() const;
// ========== 内部构建接口 ==========
void addNode(Function* F);
void addCallEdge(Function* caller, Function* callee);
void computeTopologicalOrder();
void computeStronglyConnectedComponents();
void analyzeRecursion();
private:
Module* AssociatedModule; // 关联的模块
std::map<Function*, std::unique_ptr<CallGraphNode>> nodes; // 调用图节点
std::vector<Function*> topologicalOrder; // 拓扑排序结果
std::vector<std::vector<Function*>> sccs; // 强连通分量
std::map<Function*, int> functionToSCC; // 函数到SCC的映射
// 内部辅助方法
void dfsTopological(Function* F, std::unordered_set<Function*>& visited,
std::vector<Function*>& result);
void tarjanSCC();
void tarjanDFS(Function* F, int& index, std::vector<int>& indices,
std::vector<int>& lowlinks, std::vector<Function*>& stack,
std::unordered_set<Function*>& onStack);
};
/**
* @brief SysY调用图分析Pass
* Module级别的分析Pass构建整个模块的函数调用图
*/
class CallGraphAnalysisPass : public AnalysisPass {
public:
// 唯一的 Pass ID
static void* ID;
CallGraphAnalysisPass() : AnalysisPass("CallGraphAnalysis", Pass::Granularity::Module) {}
// 实现 getPassID
void* getPassID() const override { return &ID; }
// 核心运行方法
bool runOnModule(Module* M, AnalysisManager& AM) override;
// 获取分析结果
std::unique_ptr<AnalysisResultBase> getResult() override { return std::move(CurrentResult); }
private:
std::unique_ptr<CallGraphAnalysisResult> CurrentResult; // 当前模块的分析结果
// ========== 主要分析流程 ==========
void buildCallGraph(Module* M); // 构建调用图
void scanFunctionCalls(Function* F); // 扫描函数的调用
void processCallInstruction(CallInst* call, Function* caller); // 处理调用指令
// ========== 辅助方法 ==========
bool isLibraryFunction(Function* F) const; // 判断是否为标准库函数
bool isIntrinsicFunction(Function* F) const; // 判断是否为内置函数
void printStatistics() const; // 打印统计信息
};
} // namespace sysy

View File

@ -6,30 +6,82 @@
#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;
BasicBlock* getImmediateDominator(BasicBlock* BB) const;
const std::set<BasicBlock*>* getDominanceFrontier(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);
void computeIDoms(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;
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);
};

View File

@ -0,0 +1,618 @@
#pragma once
#include "Dom.h"
#include "IR.h"
#include "Pass.h"
#include <algorithm>
#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <queue>
#include <set>
#include <vector>
namespace sysy {
// 前向声明
class LoopAnalysisResult;
class AliasAnalysisResult;
class SideEffectAnalysisResult;
/**
* @brief 表示一个识别出的循环。
*/
class Loop {
private:
static int NextLoopID; // 静态变量用于分配唯一ID
int LoopID;
public:
// 构造函数:指定循环头
Loop(BasicBlock *header) : Header(header), LoopID(NextLoopID++) {}
// 获取循环头
BasicBlock *getHeader() const { return Header; }
// 获取循环的名称 基于ID
std::string getName() const { return "loop_" + std::to_string(LoopID); }
// 获取循环体包含的所有基本块
const std::set<BasicBlock *> &getBlocks() const { return LoopBlocks; }
// 获取循环的出口基本块(即从循环内部跳转到循环外部的基本块)
const std::set<BasicBlock *> &getExitBlocks() const { return ExitBlocks; }
// 获取循环前置块(如果存在),可以为 nullptr
BasicBlock *getPreHeader() const { return PreHeader; }
// 获取直接包含此循环的父循环(如果存在),可以为 nullptr
Loop *getParentLoop() const { return ParentLoop; }
// 获取直接嵌套在此循环内的子循环
const std::vector<Loop *> &getNestedLoops() const { return NestedLoops; }
// 获取循环的层级 (0 表示最外层循环1 表示嵌套一层,以此类推)
int getLoopLevel() const { return Level; }
// 检查一个基本块是否属于当前循环
bool contains(BasicBlock *BB) const { return LoopBlocks.count(BB); }
// 判断当前循环是否是最内层循环 (没有嵌套子循环)
bool isInnermost() const { return NestedLoops.empty(); }
// 获取循环的深度(从最外层开始计算)
int getLoopDepth() const { return Level + 1; }
// 获取循环体的大小(基本块数量)
size_t getLoopSize() const { return LoopBlocks.size(); }
// 检查循环是否有唯一的外部前驱(即是否有前置块)
bool hasUniquePreHeader() const { return PreHeader != nullptr; }
// 检查循环是否是最外层循环(没有父循环)
bool isOutermost() const { return getParentLoop() == nullptr; }
// 获取循环的所有出口(从循环内到循环外的基本块)
std::vector<BasicBlock*> getExitingBlocks() const {
std::vector<BasicBlock*> exitingBlocks;
for (BasicBlock* bb : LoopBlocks) {
for (BasicBlock* succ : bb->getSuccessors()) {
if (!contains(succ)) {
exitingBlocks.push_back(bb);
break; // 每个基本块只添加一次
}
}
}
return exitingBlocks;
}
// 判断循环是否是简单循环(只有一个回边)
bool isSimpleLoop() const {
int backEdgeCount = 0;
for (BasicBlock* pred : Header->getPredecessors()) {
if (contains(pred)) {
backEdgeCount++;
}
}
return backEdgeCount == 1;
}
/**
* 获取所有出口目标块 (循环外接收循环出口边的块)
* 使用场景: 循环后置处理、phi节点分析
*/
std::vector<BasicBlock*> getExitTargetBlocks() const {
std::set<BasicBlock*> exitTargetSet;
for (BasicBlock* bb : LoopBlocks) {
for (BasicBlock* succ : bb->getSuccessors()) {
if (!contains(succ)) {
exitTargetSet.insert(succ);
}
}
}
return std::vector<BasicBlock*>(exitTargetSet.begin(), exitTargetSet.end());
}
/**
* 计算循环的"深度"相对于指定的祖先循环
* 使用场景: 相对深度计算、嵌套分析
*/
int getRelativeDepth(Loop* ancestor) const {
if (this == ancestor) return 0;
int depth = 0;
Loop* current = this->ParentLoop;
while (current && current != ancestor) {
depth++;
current = current->ParentLoop;
}
return current == ancestor ? depth : -1; // -1表示不是祖先关系
}
/**
* 检查循环是否包含函数调用
* 使用场景: 内联决策、副作用分析
*/
bool containsFunctionCalls() const {
for (BasicBlock* bb : LoopBlocks) {
for (auto& inst : bb->getInstructions()) {
if (dynamic_cast<CallInst*>(inst.get())) {
return true;
}
}
}
return false;
}
/**
* 检查循环是否可能有副作用(基于副作用分析结果)
* 使用场景: 循环优化决策、并行化分析
*/
bool mayHaveSideEffects(SideEffectAnalysisResult* sideEffectAnalysis) const;
/**
* 检查循环是否访问全局内存(基于别名分析结果)
* 使用场景: 并行化分析、缓存优化
*/
bool accessesGlobalMemory(AliasAnalysisResult* aliasAnalysis) const;
/**
* 检查循环是否有可能的内存别名冲突
* 使用场景: 向量化分析、并行化决策
*/
bool hasMemoryAliasConflicts(AliasAnalysisResult* aliasAnalysis) const;
/**
* 估算循环的"热度" (基于嵌套深度和大小)
* 使用场景: 优化优先级、资源分配
*/
double getLoopHotness() const {
// 简单的热度估算: 深度权重 + 大小惩罚
double hotness = std::pow(2.0, Level); // 深度越深越热
hotness /= std::sqrt(LoopBlocks.size()); // 大小越大相对热度降低
return hotness;
}
// --- 供 LoopAnalysisPass 内部调用的方法,用于构建 Loop 对象 ---
void addBlock(BasicBlock *BB) { LoopBlocks.insert(BB); }
void addExitBlock(BasicBlock *BB) { ExitBlocks.insert(BB); }
void setPreHeader(BasicBlock *BB) { PreHeader = BB; }
void setParentLoop(Loop *loop) { ParentLoop = loop; }
void addNestedLoop(Loop *loop) { NestedLoops.push_back(loop); }
void setLoopLevel(int level) { Level = level; }
void clearNestedLoops() { NestedLoops.clear(); }
private:
BasicBlock *Header; // 循环头基本块
std::set<BasicBlock *> LoopBlocks; // 循环体包含的基本块集合
std::set<BasicBlock *> ExitBlocks; // 循环出口基本块集合
BasicBlock *PreHeader = nullptr; // 循环前置块 (Optional)
Loop *ParentLoop = nullptr; // 父循环 (用于嵌套)
std::vector<Loop *> NestedLoops; // 嵌套的子循环
int Level = -1; // 循环的层级,-1表示未计算
};
/**
* @brief 循环分析结果类。
* 包含一个函数中所有识别出的循环,并提供高效的查询缓存机制。
*/
class LoopAnalysisResult : public AnalysisResultBase {
public:
LoopAnalysisResult(Function *F) : AssociatedFunction(F) {}
~LoopAnalysisResult() override = default;
// ========== 缓存统计结构 ==========
struct CacheStats {
size_t innermostLoopsCached;
size_t outermostLoopsCached;
size_t loopsByDepthCached;
size_t containingLoopsCached;
size_t allNestedLoopsCached;
size_t totalCachedQueries;
};
private:
// ========== 高频查询缓存 ==========
mutable std::optional<std::vector<Loop*>> cachedInnermostLoops;
mutable std::optional<std::vector<Loop*>> cachedOutermostLoops;
mutable std::optional<int> cachedMaxDepth;
mutable std::optional<size_t> cachedLoopCount;
mutable std::map<int, std::vector<Loop*>> cachedLoopsByDepth;
// ========== 中频查询缓存 ==========
mutable std::map<BasicBlock*, Loop*> cachedInnermostContainingLoop;
mutable std::map<Loop*, std::set<Loop*>> cachedAllNestedLoops; // 递归嵌套
mutable std::map<BasicBlock*, std::vector<Loop*>> cachedAllContainingLoops;
// ========== 缓存状态管理 ==========
mutable bool cacheValid = true;
// 内部辅助方法
void invalidateCache() const {
cachedInnermostLoops.reset();
cachedOutermostLoops.reset();
cachedMaxDepth.reset();
cachedLoopCount.reset();
cachedLoopsByDepth.clear();
cachedInnermostContainingLoop.clear();
cachedAllNestedLoops.clear();
cachedAllContainingLoops.clear();
cacheValid = false;
}
void ensureCacheValid() const {
if (!cacheValid) {
// 重新计算基础缓存
computeBasicCache();
cacheValid = true;
}
}
void computeBasicCache() const {
// 计算最内层循环
if (!cachedInnermostLoops) {
cachedInnermostLoops = std::vector<Loop*>();
for (const auto& loop : AllLoops) {
if (loop->isInnermost()) {
cachedInnermostLoops->push_back(loop.get());
}
}
}
// 计算最外层循环
if (!cachedOutermostLoops) {
cachedOutermostLoops = std::vector<Loop*>();
for (const auto& loop : AllLoops) {
if (loop->isOutermost()) {
cachedOutermostLoops->push_back(loop.get());
}
}
}
// 计算最大深度
if (!cachedMaxDepth) {
int maxDepth = 0;
for (const auto& loop : AllLoops) {
maxDepth = std::max(maxDepth, loop->getLoopDepth());
}
cachedMaxDepth = maxDepth;
}
// 计算循环总数
if (!cachedLoopCount) {
cachedLoopCount = AllLoops.size();
}
}
public:
// ========== 基础接口 ==========
// 添加一个识别出的循环到结果中
void addLoop(std::unique_ptr<Loop> loop) {
invalidateCache(); // 添加新循环时失效缓存
AllLoops.push_back(std::move(loop));
LoopMap[AllLoops.back()->getHeader()] = AllLoops.back().get();
}
// 获取所有识别出的循环unique_ptr 管理内存)
const std::vector<std::unique_ptr<Loop>> &getAllLoops() const { return AllLoops; }
// ========== 高频查询接口 ==========
/**
* 获取所有最内层循环 - 循环优化的主要目标
* 使用场景: 循环展开、向量化、循环不变量外提
*/
const std::vector<Loop*>& getInnermostLoops() const {
ensureCacheValid();
if (!cachedInnermostLoops) {
cachedInnermostLoops = std::vector<Loop*>();
for (const auto& loop : AllLoops) {
if (loop->isInnermost()) {
cachedInnermostLoops->push_back(loop.get());
}
}
}
return *cachedInnermostLoops;
}
/**
* 获取所有最外层循环
* 使用场景: 循环树遍历、整体优化策略
*/
const std::vector<Loop*>& getOutermostLoops() const {
ensureCacheValid();
if (!cachedOutermostLoops) {
cachedOutermostLoops = std::vector<Loop*>();
for (const auto& loop : AllLoops) {
if (loop->isOutermost()) {
cachedOutermostLoops->push_back(loop.get());
}
}
}
return *cachedOutermostLoops;
}
/**
* 获取指定深度的所有循环
* 使用场景: 分层优化、循环展开决策、并行化分析
*/
const std::vector<Loop*>& getLoopsAtDepth(int depth) const {
ensureCacheValid();
if (cachedLoopsByDepth.find(depth) == cachedLoopsByDepth.end()) {
std::vector<Loop*> result;
for (const auto& loop : AllLoops) {
if (loop->getLoopDepth() == depth) {
result.push_back(loop.get());
}
}
cachedLoopsByDepth[depth] = std::move(result);
}
return cachedLoopsByDepth[depth];
}
/**
* 获取最大循环嵌套深度
* 使用场景: 优化预算分配、编译时间控制
*/
int getMaxLoopDepth() const {
ensureCacheValid();
if (!cachedMaxDepth) {
int maxDepth = 0;
for (const auto& loop : AllLoops) {
maxDepth = std::max(maxDepth, loop->getLoopDepth());
}
cachedMaxDepth = maxDepth;
}
return *cachedMaxDepth;
}
/**
* 获取循环总数
* 使用场景: 统计信息、优化决策
*/
size_t getLoopCount() const {
ensureCacheValid();
if (!cachedLoopCount) {
cachedLoopCount = AllLoops.size();
}
return *cachedLoopCount;
}
// 获取指定深度的循环数量
size_t getLoopCountAtDepth(int depth) const {
return getLoopsAtDepth(depth).size();
}
// 检查函数是否包含循环
bool hasLoops() const { return !AllLoops.empty(); }
// ========== 中频查询接口 ==========
/**
* 获取包含指定基本块的最内层循环
* 使用场景: 活跃性分析、寄存器分配、指令调度
*/
Loop* getInnermostContainingLoop(BasicBlock* BB) const {
ensureCacheValid();
if (cachedInnermostContainingLoop.find(BB) == cachedInnermostContainingLoop.end()) {
Loop* result = nullptr;
int maxDepth = -1;
for (const auto& loop : AllLoops) {
if (loop->contains(BB) && loop->getLoopDepth() > maxDepth) {
result = loop.get();
maxDepth = loop->getLoopDepth();
}
}
cachedInnermostContainingLoop[BB] = result;
}
return cachedInnermostContainingLoop[BB];
}
/**
* 获取包含指定基本块的所有循环 (从外到内排序)
* 使用场景: 循环间优化、依赖分析
*/
const std::vector<Loop*>& getAllContainingLoops(BasicBlock* BB) const {
ensureCacheValid();
if (cachedAllContainingLoops.find(BB) == cachedAllContainingLoops.end()) {
std::vector<Loop*> result;
for (const auto& loop : AllLoops) {
if (loop->contains(BB)) {
result.push_back(loop.get());
}
}
// 按深度排序 (外层到内层)
std::sort(result.begin(), result.end(),
[](Loop* a, Loop* b) { return a->getLoopDepth() < b->getLoopDepth(); });
cachedAllContainingLoops[BB] = std::move(result);
}
return cachedAllContainingLoops[BB];
}
/**
* 获取指定循环的所有嵌套子循环 (递归)
* 使用场景: 循环树分析、嵌套优化
*/
const std::set<Loop*>& getAllNestedLoops(Loop* loop) const {
ensureCacheValid();
if (cachedAllNestedLoops.find(loop) == cachedAllNestedLoops.end()) {
std::set<Loop*> result;
std::function<void(Loop*)> collectNested = [&](Loop* current) {
for (Loop* nested : current->getNestedLoops()) {
result.insert(nested);
collectNested(nested); // 递归收集
}
};
collectNested(loop);
cachedAllNestedLoops[loop] = std::move(result);
}
return cachedAllNestedLoops[loop];
}
// ========== 利用别名和副作用分析的查询接口 ==========
/**
* 获取所有纯循环(无副作用的循环)
* 并行化、循环优化
*/
std::vector<Loop*> getPureLoops(SideEffectAnalysisResult* sideEffectAnalysis) const {
std::vector<Loop*> result;
if (!sideEffectAnalysis) return result;
for (const auto& loop : AllLoops) {
if (!loop->mayHaveSideEffects(sideEffectAnalysis)) {
result.push_back(loop.get());
}
}
return result;
}
/**
* 获取所有只访问局部内存的循环
* 缓存优化、局部性分析
*/
std::vector<Loop*> getLocalMemoryLoops(AliasAnalysisResult* aliasAnalysis) const {
std::vector<Loop*> result;
if (!aliasAnalysis) return result;
for (const auto& loop : AllLoops) {
if (!loop->accessesGlobalMemory(aliasAnalysis)) {
result.push_back(loop.get());
}
}
return result;
}
/**
* 获取所有无内存别名冲突的循环
* 向量化、并行化
*/
std::vector<Loop*> getNoAliasConflictLoops(AliasAnalysisResult* aliasAnalysis) const {
std::vector<Loop*> result;
if (!aliasAnalysis) return result;
for (const auto& loop : AllLoops) {
if (!loop->hasMemoryAliasConflicts(aliasAnalysis)) {
result.push_back(loop.get());
}
}
return result;
}
// ========== 低频查询接口(不缓存) ==========
/**
* 检查两个循环是否有嵌套关系
* 循环间依赖分析
*/
bool isNestedLoop(Loop* inner, Loop* outer) const {
if (inner == outer) return false;
Loop* current = inner->getParentLoop();
while (current) {
if (current == outer) return true;
current = current->getParentLoop();
}
return false;
}
/**
* 获取两个循环的最近公共祖先循环
* 循环融合分析、优化范围确定
*/
Loop* getLowestCommonAncestor(Loop* loop1, Loop* loop2) const {
if (!loop1 || !loop2) return nullptr;
if (loop1 == loop2) return loop1;
// 收集loop1的所有祖先
std::set<Loop*> ancestors1;
Loop* current = loop1;
while (current) {
ancestors1.insert(current);
current = current->getParentLoop();
}
// 查找loop2祖先链中第一个在ancestors1中的循环
current = loop2;
while (current) {
if (ancestors1.count(current)) {
return current;
}
current = current->getParentLoop();
}
return nullptr; // 没有公共祖先
}
// 通过循环头获取 Loop 对象
Loop *getLoopForHeader(BasicBlock *header) const {
auto it = LoopMap.find(header);
return (it != LoopMap.end()) ? it->second : nullptr;
}
// 通过某个基本块获取包含它的最内层循环 (向后兼容接口)
Loop *getLoopContainingBlock(BasicBlock *BB) const {
return getInnermostContainingLoop(BB);
}
// ========== 缓存管理接口 ==========
/**
* 手动失效缓存 (可删除)
*/
void invalidateQueryCache() const {
invalidateCache();
}
/**
* 获取缓存统计信息
*/
CacheStats getCacheStats() const {
CacheStats stats = {};
stats.innermostLoopsCached = cachedInnermostLoops.has_value() ? 1 : 0;
stats.outermostLoopsCached = cachedOutermostLoops.has_value() ? 1 : 0;
stats.loopsByDepthCached = cachedLoopsByDepth.size();
stats.containingLoopsCached = cachedInnermostContainingLoop.size();
stats.allNestedLoopsCached = cachedAllNestedLoops.size();
stats.totalCachedQueries = stats.innermostLoopsCached + stats.outermostLoopsCached +
stats.loopsByDepthCached + stats.containingLoopsCached +
stats.allNestedLoopsCached;
return stats;
}
// 打印分析结果
void print() const;
void printBBSet(const std::string &prefix, const std::set<BasicBlock *> &s) const;
void printLoopVector(const std::string &prefix, const std::vector<Loop *> &loops) const;
private:
Function *AssociatedFunction; // 结果关联的函数
std::vector<std::unique_ptr<Loop>> AllLoops; // 所有识别出的循环
std::map<BasicBlock *, Loop *> LoopMap; // 循环头到 Loop* 的映射,方便查找
};
/**
* @brief 循环分析遍。
* 识别函数中的所有循环,并生成 LoopAnalysisResult。
*/
class LoopAnalysisPass : public AnalysisPass {
public:
// 唯一的 Pass ID需要在 .cpp 文件中定义
static void *ID;
LoopAnalysisPass() : AnalysisPass("LoopAnalysis", Pass::Granularity::Function) {}
// 实现 getPassID
void *getPassID() const override { return &ID; }
// 核心运行方法:在每个函数上执行循环分析
bool runOnFunction(Function *F, AnalysisManager &AM) override;
// 获取分析结果
std::unique_ptr<AnalysisResultBase> getResult() override { return std::move(CurrentResult); }
private:
std::unique_ptr<LoopAnalysisResult> CurrentResult; // 当前函数的分析结果
};
} // namespace sysy

View File

@ -0,0 +1,360 @@
#pragma once
#include "Dom.h" // 支配树分析依赖
#include "Loop.h" // 循环分析依赖
#include "Liveness.h" // 活跃性分析依赖
#include "AliasAnalysis.h" // 别名分析依赖
#include "SideEffectAnalysis.h" // 副作用分析依赖
#include "CallGraphAnalysis.h" // 调用图分析依赖
#include "IR.h" // IR定义
#include "Pass.h" // Pass框架
#include <algorithm>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <vector>
namespace sysy {
// 前向声明
class LoopCharacteristicsResult;
enum IVKind {
kBasic, // 基本归纳变量
kLinear, // 线性归纳变量
kCmplx // 复杂派生归纳变量
} ; // 归纳变量类型
struct InductionVarInfo {
Value* div; // 派生归纳变量的指令
Value* base = nullptr; // 其根phi或BIV或DIV
std::pair<Value*, Value*> Multibase = {nullptr, nullptr}; // 多个BIV
Instruction::Kind Instkind; // 操作类型
int factor = 1; // 系数如i*2+3的2
int offset = 0; // 常量偏移
bool valid; // 是否线性可归约
IVKind ivkind; // 归纳变量类型
static std::unique_ptr<InductionVarInfo> createBasicBIV(Value* v, Instruction::Kind kind, Value* base = nullptr, int factor = 1, int offset = 0) {
return std::make_unique<InductionVarInfo>(
InductionVarInfo{v, base, {nullptr, nullptr}, kind, factor, offset, true, IVKind::kBasic}
);
}
static std::unique_ptr<InductionVarInfo> createSingleDIV(Value* v, Instruction::Kind kind, Value* base = nullptr, int factor = 1, int offset = 0) {
return std::make_unique<InductionVarInfo>(
InductionVarInfo{v, base, {nullptr, nullptr}, kind, factor, offset, true, IVKind::kLinear}
);
}
static std::unique_ptr<InductionVarInfo> createDoubleDIV(Value* v, Instruction::Kind kind, Value* base1 = nullptr, Value* base2 = nullptr, int factor = 1, int offset = 0) {
return std::make_unique<InductionVarInfo>(
InductionVarInfo{v, nullptr, {base1, base2}, kind, factor, offset, false, IVKind::kCmplx}
);
}
};
/**
* @brief 循环特征信息结构 - 基础循环分析阶段
* 存储循环的基本特征信息,为后续精确分析提供基础
*/
struct LoopCharacteristics {
Loop* loop; // 关联的循环对象
// ========== 基础循环形式分析 ==========
bool isCountingLoop; // 是否为计数循环 (for i=0; i<n; i++)
bool isSimpleForLoop; // 是否为简单for循环
bool hasComplexControlFlow; // 是否有复杂控制流 (break, continue)
bool isInnermost; // 是否为最内层循环
// ========== 归纳变量分析 ==========
// ========== 基础循环不变量分析 ==========
std::unordered_set<Value*> loopInvariants; // 循环不变量
std::unordered_set<Instruction*> invariantInsts; // 可提升的不变指令
std::vector<std::unique_ptr<InductionVarInfo>> InductionVars; // 归纳变量
// ========== 基础边界分析 ==========
std::optional<int> staticTripCount; // 静态循环次数(如果可确定)
bool hasKnownBounds; // 是否有已知边界
// ========== 基础纯度和副作用分析 ==========
bool isPure; // 是否为纯循环(无副作用)
bool accessesOnlyLocalMemory; // 是否只访问局部内存
bool hasNoMemoryAliasConflicts; // 是否无内存别名冲突
// ========== 基础内存访问模式分析 ==========
struct MemoryAccessPattern {
std::vector<Instruction*> loadInsts; // load指令列表
std::vector<Instruction*> storeInsts; // store指令列表
bool isArrayParameter; // 是否为数组参数访问
bool isGlobalArray; // 是否为全局数组访问
bool hasConstantIndices; // 是否使用常量索引
};
std::map<Value*, MemoryAccessPattern> memoryPatterns; // 内存访问模式
// ========== 基础性能特征 ==========
size_t instructionCount; // 循环体指令数
size_t memoryOperationCount; // 内存操作数
size_t arithmeticOperationCount; // 算术操作数
double computeToMemoryRatio; // 计算与内存操作比率
// ========== 基础优化提示 ==========
bool benefitsFromUnrolling; // 是否适合循环展开
int suggestedUnrollFactor; // 建议的展开因子
// 构造函数 - 简化的基础分析初始化
LoopCharacteristics(Loop* l) : loop(l),
isCountingLoop(false), isSimpleForLoop(false), hasComplexControlFlow(false),
isInnermost(false), hasKnownBounds(false), isPure(false),
accessesOnlyLocalMemory(false), hasNoMemoryAliasConflicts(false),
benefitsFromUnrolling(false), suggestedUnrollFactor(1),
instructionCount(0), memoryOperationCount(0),
arithmeticOperationCount(0), computeToMemoryRatio(0.0) {}
};
/**
* @brief 循环特征分析结果类
* 包含函数中所有循环的特征信息,并提供查询接口
*/
class LoopCharacteristicsResult : public AnalysisResultBase {
public:
LoopCharacteristicsResult(Function *F) : AssociatedFunction(F) {}
~LoopCharacteristicsResult() override = default;
// ========== 基础接口 ==========
/**
* 添加循环特征信息
*/
void addLoopCharacteristics(std::unique_ptr<LoopCharacteristics> characteristics) {
auto* loop = characteristics->loop;
CharacteristicsMap[loop] = std::move(characteristics);
}
/**
* 获取指定循环的特征信息
*/
const LoopCharacteristics* getCharacteristics(Loop* loop) const {
auto it = CharacteristicsMap.find(loop);
return (it != CharacteristicsMap.end()) ? it->second.get() : nullptr;
}
/**
* 获取所有循环特征信息
*/
const std::map<Loop*, std::unique_ptr<LoopCharacteristics>>& getAllCharacteristics() const {
return CharacteristicsMap;
}
// ========== 核心查询接口 ==========
/**
* 获取所有计数循环
*/
std::vector<Loop*> getCountingLoops() const {
std::vector<Loop*> result;
for (const auto& [loop, chars] : CharacteristicsMap) {
if (chars->isCountingLoop) {
result.push_back(loop);
}
}
return result;
}
/**
* 获取所有纯循环(无副作用)
*/
std::vector<Loop*> getPureLoops() const {
std::vector<Loop*> result;
for (const auto& [loop, chars] : CharacteristicsMap) {
if (chars->isPure) {
result.push_back(loop);
}
}
return result;
}
/**
* 获取所有只访问局部内存的循环
*/
std::vector<Loop*> getLocalMemoryOnlyLoops() const {
std::vector<Loop*> result;
for (const auto& [loop, chars] : CharacteristicsMap) {
if (chars->accessesOnlyLocalMemory) {
result.push_back(loop);
}
}
return result;
}
/**
* 获取所有无内存别名冲突的循环
*/
std::vector<Loop*> getNoAliasConflictLoops() const {
std::vector<Loop*> result;
for (const auto& [loop, chars] : CharacteristicsMap) {
if (chars->hasNoMemoryAliasConflicts) {
result.push_back(loop);
}
}
return result;
}
/**
* 获取所有适合展开的循环
*/
std::vector<Loop*> getUnrollingCandidates() const {
std::vector<Loop*> result;
for (const auto& [loop, chars] : CharacteristicsMap) {
if (chars->benefitsFromUnrolling) {
result.push_back(loop);
}
}
return result;
}
/**
* 根据热度排序循环 (用于优化优先级)
*/
std::vector<Loop*> getLoopsByHotness() const {
std::vector<Loop*> result;
for (const auto& [loop, chars] : CharacteristicsMap) {
result.push_back(loop);
}
// 按循环热度排序 (嵌套深度 + 循环次数 + 指令数)
std::sort(result.begin(), result.end(), [](Loop* a, Loop* b) {
double hotnessA = a->getLoopHotness();
double hotnessB = b->getLoopHotness();
return hotnessA > hotnessB; // 降序排列
});
return result;
}
// ========== 基础统计接口 ==========
/**
* 获取基础优化统计信息
*/
struct BasicOptimizationStats {
size_t totalLoops;
size_t countingLoops;
size_t unrollingCandidates;
size_t pureLoops;
size_t localMemoryOnlyLoops;
size_t noAliasConflictLoops;
double avgInstructionCount;
double avgComputeMemoryRatio;
};
BasicOptimizationStats getOptimizationStats() const {
BasicOptimizationStats stats = {};
stats.totalLoops = CharacteristicsMap.size();
size_t totalInstructions = 0;
double totalComputeMemoryRatio = 0.0;
for (const auto& [loop, chars] : CharacteristicsMap) {
if (chars->isCountingLoop) stats.countingLoops++;
if (chars->benefitsFromUnrolling) stats.unrollingCandidates++;
if (chars->isPure) stats.pureLoops++;
if (chars->accessesOnlyLocalMemory) stats.localMemoryOnlyLoops++;
if (chars->hasNoMemoryAliasConflicts) stats.noAliasConflictLoops++;
totalInstructions += chars->instructionCount;
totalComputeMemoryRatio += chars->computeToMemoryRatio;
}
if (stats.totalLoops > 0) {
stats.avgInstructionCount = static_cast<double>(totalInstructions) / stats.totalLoops;
stats.avgComputeMemoryRatio = totalComputeMemoryRatio / stats.totalLoops;
}
return stats;
}
// 打印分析结果
void print() const;
private:
Function *AssociatedFunction; // 关联的函数
std::map<Loop*, std::unique_ptr<LoopCharacteristics>> CharacteristicsMap; // 循环特征映射
};
/**
* @brief 基础循环特征分析遍
* 在循环规范化前执行,进行基础的循环特征分析,为后续精确分析提供基础
*/
class LoopCharacteristicsPass : public AnalysisPass {
public:
// 唯一的 Pass ID
static void *ID;
LoopCharacteristicsPass() : AnalysisPass("LoopCharacteristics", Pass::Granularity::Function) {}
// 实现 getPassID
void *getPassID() const override { return &ID; }
// 核心运行方法
bool runOnFunction(Function *F, AnalysisManager &AM) override;
// 获取分析结果
std::unique_ptr<AnalysisResultBase> getResult() override { return std::move(CurrentResult); }
private:
std::unique_ptr<LoopCharacteristicsResult> CurrentResult;
// ========== 缓存的分析结果 ==========
LoopAnalysisResult* loopAnalysis; // 循环结构分析结果
AliasAnalysisResult* aliasAnalysis; // 别名分析结果
SideEffectAnalysisResult* sideEffectAnalysis; // 副作用分析结果
// ========== 核心分析方法 ==========
void analyzeLoop(Loop* loop, LoopCharacteristics* characteristics);
// 基础循环形式分析
void analyzeLoopForm(Loop* loop, LoopCharacteristics* characteristics);
// 基础性能指标计算
void computePerformanceMetrics(Loop* loop, LoopCharacteristics* characteristics);
// 基础纯度和副作用分析
void analyzePurityAndSideEffects(Loop* loop, LoopCharacteristics* characteristics);
// 基础归纳变量识别
void identifyBasicInductionVariables(Loop* loop, LoopCharacteristics* characteristics);
// 循环不变量识别
void identifyBasicLoopInvariants(Loop* loop, LoopCharacteristics* characteristics);
// 基础边界分析
void analyzeBasicLoopBounds(Loop* loop, LoopCharacteristics* characteristics);
// 基础内存访问模式分析
void analyzeBasicMemoryAccessPatterns(Loop* loop, LoopCharacteristics* characteristics);
// 基础优化评估
void evaluateBasicOptimizationOpportunities(Loop* loop, LoopCharacteristics* characteristics);
// ========== 辅助方法 ==========
bool isClassicLoopInvariant(Value* val, Loop* loop, const std::unordered_set<Value*>& invariants);
void findDerivedInductionVars(Value* root,
Value* base, // 只传单一BIV base
Loop* loop,
std::vector<std::unique_ptr<InductionVarInfo>>& ivs,
std::set<Value*>& visited
);
bool isBasicInductionVariable(Value* val, Loop* loop);
// ========== 循环不变量分析辅助方法 ==========
bool isInvariantOperands(Instruction* inst, Loop* loop, const std::unordered_set<Value*>& invariants);
bool isMemoryLocationModifiedInLoop(Value* ptr, Loop* loop);
bool isMemoryLocationLoadedInLoop(Value* ptr, Loop* loop, Instruction* excludeInst = nullptr);
bool isPureFunction(Function* calledFunc);
};
} // namespace sysy

View File

@ -0,0 +1,250 @@
#pragma once
#include "Pass.h"
#include "Loop.h"
#include "LoopCharacteristics.h"
#include "AliasAnalysis.h"
#include "SideEffectAnalysis.h"
#include <vector>
#include <map>
#include <memory>
#include <set>
#include <string>
namespace sysy {
/**
* @brief 依赖类型枚举 - 只考虑真正影响并行性的依赖
*
* 依赖类型分析说明:
* - TRUE_DEPENDENCE (RAW): 真依赖,必须保持原始执行顺序,是最关键的依赖
* - ANTI_DEPENDENCE (WAR): 反依赖,影响指令重排序,可通过寄存器重命名等技术缓解
* - OUTPUT_DEPENDENCE (WAW): 输出依赖,相对较少但需要考虑,可通过变量私有化解决
*
*/
enum class DependenceType {
TRUE_DEPENDENCE, // 真依赖 (RAW) - 读后写流依赖,最重要的依赖类型
ANTI_DEPENDENCE, // 反依赖 (WAR) - 写后读反向依赖,影响指令重排序
OUTPUT_DEPENDENCE // 输出依赖 (WAW) - 写后写,相对较少但需要考虑
};
/**
* @brief 依赖向量 - 表示两个内存访问之间的迭代距离
* 例如a[i] 和 a[i+1] 之间的依赖向量是 [1]
* a[i][j] 和 a[i+1][j-2] 之间的依赖向量是 [1,-2]
*/
struct DependenceVector {
std::vector<int> distances; // 每个循环层次的依赖距离
bool isConstant; // 是否为常量距离
bool isKnown; // 是否已知距离
DependenceVector(size_t loopDepth) : distances(loopDepth, 0), isConstant(false), isKnown(false) {}
// 检查是否为循环无关依赖
bool isLoopIndependent() const {
for (int dist : distances) {
if (dist != 0) return false;
}
return true;
}
// 获取词典序方向向量
std::vector<int> getDirectionVector() const;
// 检查是否可以通过向量化处理
bool isVectorizationSafe() const;
};
/**
* @brief 精确依赖关系 - 包含依赖向量的详细依赖信息
*/
struct PreciseDependence {
Instruction* source;
Instruction* sink;
DependenceType type;
DependenceVector dependenceVector;
Value* memoryLocation;
// 并行化相关
bool allowsParallelization; // 是否允许并行化
bool requiresSynchronization; // 是否需要同步
bool isReductionDependence; // 是否为归约依赖
PreciseDependence(size_t loopDepth) : dependenceVector(loopDepth),
allowsParallelization(true), requiresSynchronization(false), isReductionDependence(false) {}
};
/**
* @brief 向量化分析信息 - 暂时搁置,保留接口
*/
struct VectorizationAnalysis {
bool isVectorizable; // 固定为false暂不支持
int suggestedVectorWidth; // 固定为1
std::vector<std::string> preventingFactors; // 阻止向量化的因素
VectorizationAnalysis() : isVectorizable(false), suggestedVectorWidth(1) {
preventingFactors.push_back("Vectorization temporarily disabled");
}
};
/**
* @brief 并行化分析信息
*/
struct ParallelizationAnalysis {
bool isParallelizable; // 是否可并行化
int suggestedThreadCount; // 建议的线程数
std::vector<std::string> preventingFactors; // 阻止并行化的因素
// 并行化模式
enum ParallelizationType {
NONE, // 不可并行化
EMBARRASSINGLY_PARALLEL, // 完全并行
REDUCTION_PARALLEL, // 归约并行
PIPELINE_PARALLEL, // 流水线并行
CONDITIONAL_PARALLEL // 条件并行
} parallelType;
// 负载均衡
bool hasLoadBalance; // 是否有良好的负载均衡
bool isDynamicLoadBalanced; // 是否需要动态负载均衡
double workComplexity; // 工作复杂度估计
// 同步需求
bool requiresReduction; // 是否需要归约操作
bool requiresBarrier; // 是否需要屏障同步
std::set<Value*> sharedVariables; // 共享变量
std::set<Value*> reductionVariables; // 归约变量
std::set<Value*> privatizableVariables; // 可私有化变量
// 内存访问模式
bool hasMemoryConflicts; // 是否有内存冲突
bool hasReadOnlyAccess; // 是否只有只读访问
bool hasIndependentAccess; // 是否有独立的内存访问
// 并行化收益评估
double parallelizationBenefit; // 并行化收益估计 (0-1)
size_t communicationCost; // 通信开销估计
size_t synchronizationCost; // 同步开销估计
ParallelizationAnalysis() : isParallelizable(false), suggestedThreadCount(1), parallelType(NONE),
hasLoadBalance(true), isDynamicLoadBalanced(false), workComplexity(0.0), requiresReduction(false),
requiresBarrier(false), hasMemoryConflicts(false), hasReadOnlyAccess(false), hasIndependentAccess(false),
parallelizationBenefit(0.0), communicationCost(0), synchronizationCost(0) {}
};
/**
* @brief 循环向量化/并行化分析结果
*/
class LoopVectorizationResult : public AnalysisResultBase {
private:
Function* AssociatedFunction;
std::map<Loop*, VectorizationAnalysis> VectorizationMap;
std::map<Loop*, ParallelizationAnalysis> ParallelizationMap;
std::map<Loop*, std::vector<PreciseDependence>> DependenceMap;
public:
LoopVectorizationResult(Function* F) : AssociatedFunction(F) {}
~LoopVectorizationResult() override = default;
// 基础接口
void addVectorizationAnalysis(Loop* loop, VectorizationAnalysis analysis) {
VectorizationMap[loop] = std::move(analysis);
}
void addParallelizationAnalysis(Loop* loop, ParallelizationAnalysis analysis) {
ParallelizationMap[loop] = std::move(analysis);
}
void addDependenceAnalysis(Loop* loop, std::vector<PreciseDependence> dependences) {
DependenceMap[loop] = std::move(dependences);
}
// 查询接口
const VectorizationAnalysis* getVectorizationAnalysis(Loop* loop) const {
auto it = VectorizationMap.find(loop);
return it != VectorizationMap.end() ? &it->second : nullptr;
}
const ParallelizationAnalysis* getParallelizationAnalysis(Loop* loop) const {
auto it = ParallelizationMap.find(loop);
return it != ParallelizationMap.end() ? &it->second : nullptr;
}
const std::vector<PreciseDependence>* getPreciseDependences(Loop* loop) const {
auto it = DependenceMap.find(loop);
return it != DependenceMap.end() ? &it->second : nullptr;
}
// 统计接口
size_t getVectorizableLoopCount() const;
size_t getParallelizableLoopCount() const;
// 优化建议
std::vector<Loop*> getVectorizationCandidates() const;
std::vector<Loop*> getParallelizationCandidates() const;
// 打印分析结果
void print() const;
};
/**
* @brief 循环向量化/并行化分析遍
* 在循环规范化后执行,进行精确的依赖向量分析和向量化/并行化可行性评估
* 专注于并行化分析,向量化功能暂时搁置
*/
class LoopVectorizationPass : public AnalysisPass {
public:
// 唯一的 Pass ID
static void *ID;
LoopVectorizationPass() : AnalysisPass("LoopVectorization", Pass::Granularity::Function) {}
// 实现 getPassID
void *getPassID() const override { return &ID; }
// 核心运行方法
bool runOnFunction(Function *F, AnalysisManager &AM) override;
// 获取分析结果
std::unique_ptr<AnalysisResultBase> getResult() override { return std::move(CurrentResult); }
private:
std::unique_ptr<LoopVectorizationResult> CurrentResult;
// ========== 主要分析方法 ==========
void analyzeLoop(Loop* loop, LoopCharacteristics* characteristics,
AliasAnalysisResult* aliasAnalysis, SideEffectAnalysisResult* sideEffectAnalysis);
// ========== 依赖向量分析 ==========
std::vector<PreciseDependence> computeDependenceVectors(Loop* loop, AliasAnalysisResult* aliasAnalysis);
DependenceVector computeAccessDependence(Instruction* inst1, Instruction* inst2, Loop* loop);
bool areAccessesAffinelyRelated(Value* ptr1, Value* ptr2, Loop* loop);
// ========== 向量化分析 (暂时搁置) ==========
VectorizationAnalysis analyzeVectorizability(Loop* loop, const std::vector<PreciseDependence>& dependences,
LoopCharacteristics* characteristics);
// ========== 并行化分析 ==========
ParallelizationAnalysis analyzeParallelizability(Loop* loop, const std::vector<PreciseDependence>& dependences,
LoopCharacteristics* characteristics);
bool checkParallelizationLegality(Loop* loop, const std::vector<PreciseDependence>& dependences);
int estimateOptimalThreadCount(Loop* loop, LoopCharacteristics* characteristics);
ParallelizationAnalysis::ParallelizationType determineParallelizationType(Loop* loop,
const std::vector<PreciseDependence>& dependences);
// ========== 并行化专用分析方法 ==========
void analyzeReductionPatterns(Loop* loop, ParallelizationAnalysis* analysis);
void analyzeMemoryAccessPatterns(Loop* loop, ParallelizationAnalysis* analysis, AliasAnalysisResult* aliasAnalysis);
void estimateParallelizationBenefit(Loop* loop, ParallelizationAnalysis* analysis, LoopCharacteristics* characteristics);
void identifyPrivatizableVariables(Loop* loop, ParallelizationAnalysis* analysis);
void analyzeSynchronizationNeeds(Loop* loop, ParallelizationAnalysis* analysis, const std::vector<PreciseDependence>& dependences);
// ========== 辅助方法 ==========
std::vector<int> extractInductionCoefficients(Value* ptr, Loop* loop);
bool isConstantStride(Value* ptr, Loop* loop, int& stride);
bool isIndependentMemoryAccess(Value* ptr1, Value* ptr2, Loop* loop);
double estimateWorkComplexity(Loop* loop);
bool hasReductionPattern(Value* var, Loop* loop);
};
} // namespace sysy

View File

@ -0,0 +1,137 @@
#pragma once
#include "Pass.h"
#include "IR.h"
#include "AliasAnalysis.h"
#include "CallGraphAnalysis.h"
#include <unordered_set>
#include <unordered_map>
namespace sysy {
// 副作用类型枚举
enum class SideEffectType {
NO_SIDE_EFFECT, // 无副作用
MEMORY_WRITE, // 内存写入store、memset
FUNCTION_CALL, // 函数调用(可能有任意副作用)
IO_OPERATION, // I/O操作printf、scanf等
UNKNOWN // 未知副作用
};
// 副作用信息结构
struct SideEffectInfo {
SideEffectType type = SideEffectType::NO_SIDE_EFFECT;
bool mayModifyGlobal = false; // 可能修改全局变量
bool mayModifyMemory = false; // 可能修改内存
bool mayCallFunction = false; // 可能调用函数
bool isPure = true; // 是否为纯函数(无副作用且结果只依赖参数)
// 合并两个副作用信息
SideEffectInfo merge(const SideEffectInfo& other) const {
SideEffectInfo result;
result.type = (type == SideEffectType::NO_SIDE_EFFECT) ? other.type : type;
result.mayModifyGlobal = mayModifyGlobal || other.mayModifyGlobal;
result.mayModifyMemory = mayModifyMemory || other.mayModifyMemory;
result.mayCallFunction = mayCallFunction || other.mayCallFunction;
result.isPure = isPure && other.isPure;
return result;
}
};
// 副作用分析结果类
class SideEffectAnalysisResult : public AnalysisResultBase {
private:
// 指令级别的副作用信息
std::unordered_map<Instruction*, SideEffectInfo> instructionSideEffects;
// 函数级别的副作用信息
std::unordered_map<Function*, SideEffectInfo> functionSideEffects;
// 已知的SysY标准库函数副作用信息
std::unordered_map<std::string, SideEffectInfo> knownFunctions;
public:
SideEffectAnalysisResult();
virtual ~SideEffectAnalysisResult() noexcept override = default;
// 获取指令的副作用信息
const SideEffectInfo& getInstructionSideEffect(Instruction* inst) const;
// 获取函数的副作用信息
const SideEffectInfo& getFunctionSideEffect(Function* func) const;
// 设置指令的副作用信息
void setInstructionSideEffect(Instruction* inst, const SideEffectInfo& info);
// 设置函数的副作用信息
void setFunctionSideEffect(Function* func, const SideEffectInfo& info);
// 检查指令是否有副作用
bool hasSideEffect(Instruction* inst) const;
// 检查指令是否可能修改内存
bool mayModifyMemory(Instruction* inst) const;
// 检查指令是否可能修改全局状态
bool mayModifyGlobal(Instruction* inst) const;
// 检查函数是否为纯函数
bool isPureFunction(Function* func) const;
// 获取已知函数的副作用信息
const SideEffectInfo* getKnownFunctionSideEffect(const std::string& funcName) const;
// 初始化已知函数的副作用信息
void initializeKnownFunctions();
private:
};
// 副作用分析遍类 - Module级别分析
class SysYSideEffectAnalysisPass : public AnalysisPass {
public:
// 静态成员作为该遍的唯一ID
static void* ID;
SysYSideEffectAnalysisPass() : AnalysisPass("SysYSideEffectAnalysis", Granularity::Module) {}
// 在模块上运行分析
bool runOnModule(Module* M, AnalysisManager& AM) override;
// 获取分析结果
std::unique_ptr<AnalysisResultBase> getResult() override;
// Pass 基类中的纯虚函数,必须实现
void* getPassID() const override { return &ID; }
private:
// 分析结果
std::unique_ptr<SideEffectAnalysisResult> result;
// 调用图分析结果
CallGraphAnalysisResult* callGraphAnalysis = nullptr;
// 分析单个函数的副作用Module级别的内部方法
SideEffectInfo analyzeFunction(Function* func, AnalysisManager& AM);
// 分析单个指令的副作用
SideEffectInfo analyzeInstruction(Instruction* inst, Function* currentFunc, AnalysisManager& AM);
// 分析函数调用指令的副作用(利用调用图)
SideEffectInfo analyzeCallInstruction(CallInst* call, Function* currentFunc, AnalysisManager& AM);
// 分析存储指令的副作用
SideEffectInfo analyzeStoreInstruction(StoreInst* store, Function* currentFunc, AnalysisManager& AM);
// 分析内存设置指令的副作用
SideEffectInfo analyzeMemsetInstruction(MemsetInst* memset, Function* currentFunc, AnalysisManager& AM);
// 使用不动点算法分析递归函数群
void analyzeStronglyConnectedComponent(const std::vector<Function*>& scc, AnalysisManager& AM);
// 检查函数间副作用传播的收敛性
bool hasConverged(const std::unordered_map<Function*, SideEffectInfo>& oldEffects,
const std::unordered_map<Function*, SideEffectInfo>& newEffects) const;
};
} // 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

@ -4,6 +4,8 @@
#include "IR.h"
#include "SysYIROptUtils.h"
#include "Dom.h"
#include "AliasAnalysis.h"
#include "SideEffectAnalysis.h"
#include <unordered_set>
#include <queue>
@ -25,8 +27,12 @@ public:
private:
// 存储活跃指令的集合
std::unordered_set<Instruction*> alive_insts;
// 别名分析结果
AliasAnalysisResult* aliasAnalysis = nullptr;
// 副作用分析结果
SideEffectAnalysisResult* sideEffectAnalysis = nullptr;
// 判断指令是否是天然活跃的(即总是保留的)
// 判断指令是否是"天然活跃"的(即总是保留的)
// inst: 要检查的指令
// 返回值: 如果指令是天然活跃的则为true否则为false
bool isAlive(Instruction* inst);
@ -34,6 +40,9 @@ private:
// 递归地将活跃指令及其依赖加入到 alive_insts 集合中
// inst: 要标记为活跃的指令
void addAlive(Instruction* inst);
// 检查Store指令是否可能有副作用通过别名分析
bool mayHaveSideEffect(StoreInst* store);
};
// DCE 优化遍类,继承自 OptimizationPass

View File

@ -0,0 +1,87 @@
#pragma once
#include "Pass.h"
#include "IR.h"
#include "Dom.h"
#include "SideEffectAnalysis.h"
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <string>
#include <sstream>
namespace sysy {
// GVN优化遍的核心逻辑封装类
class GVNContext {
public:
// 运行GVN优化的主要方法
void run(Function* func, AnalysisManager* AM, bool& changed);
private:
// 新的值编号系统
std::unordered_map<Value*, unsigned> valueToNumber; // Value -> 值编号
std::unordered_map<unsigned, Value*> numberToValue; // 值编号 -> 代表值
std::unordered_map<std::string, unsigned> expressionToNumber; // 表达式 -> 值编号
unsigned nextValueNumber = 1;
// 已访问的基本块集合
std::unordered_set<BasicBlock*> visited;
// 逆后序遍历的基本块列表
std::vector<BasicBlock*> rpoBlocks;
// 需要删除的指令集合
std::unordered_set<Instruction*> needRemove;
// 分析结果
DominatorTree* domTree = nullptr;
SideEffectAnalysisResult* sideEffectAnalysis = nullptr;
// 计算逆后序遍历
void computeRPO(Function* func);
void dfs(BasicBlock* bb);
// 新的值编号方法
unsigned getValueNumber(Value* value);
unsigned assignValueNumber(Value* value);
// 基本块处理
void processBasicBlock(BasicBlock* bb, bool& changed);
// 指令处理
bool processInstruction(Instruction* inst);
// 表达式构建和查找
std::string buildExpressionKey(Instruction* inst);
Value* findExistingValue(const std::string& exprKey, Instruction* inst);
// 支配关系和安全性检查
bool dominates(Instruction* a, Instruction* b);
bool isMemorySafe(LoadInst* earlierLoad, LoadInst* laterLoad);
// 清理方法
void eliminateRedundantInstructions(bool& changed);
void invalidateMemoryValues(StoreInst* store);
};
// GVN优化遍类
class GVN : public OptimizationPass {
public:
// 静态成员作为该遍的唯一ID
static void* ID;
GVN() : OptimizationPass("GVN", Granularity::Function) {}
// 在函数上运行优化
bool runOnFunction(Function* func, AnalysisManager& AM) override;
// 返回该遍的唯一ID
void* getPassID() const override { return ID; }
// 声明分析依赖
void getAnalysisUsage(std::set<void*>& analysisDependencies,
std::set<void*>& analysisInvalidations) const override;
};
} // namespace sysy

View File

@ -0,0 +1,107 @@
#pragma once
#include "Pass.h"
#include "IR.h"
#include "SideEffectAnalysis.h"
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <cstdint>
namespace sysy {
// 魔数乘法结构,用于除法优化
struct MagicNumber {
uint32_t multiplier;
int shift;
bool needAdd;
MagicNumber(uint32_t m, int s, bool add = false)
: multiplier(m), shift(s), needAdd(add) {}
};
// 全局强度削弱优化遍的核心逻辑封装类
class GlobalStrengthReductionContext {
public:
// 构造函数接受IRBuilder参数
explicit GlobalStrengthReductionContext(IRBuilder* builder) : builder(builder) {}
// 运行优化的主要方法
void run(Function* func, AnalysisManager* AM, bool& changed);
private:
IRBuilder* builder; // IR构建器
// 分析结果
SideEffectAnalysisResult* sideEffectAnalysis = nullptr;
// 优化计数
int algebraicOptCount = 0;
int strengthReductionCount = 0;
int divisionOptCount = 0;
// 主要优化方法
bool processBasicBlock(BasicBlock* bb);
bool processInstruction(Instruction* inst);
// 代数优化方法
bool tryAlgebraicOptimization(Instruction* inst);
bool optimizeAddition(BinaryInst* inst);
bool optimizeSubtraction(BinaryInst* inst);
bool optimizeMultiplication(BinaryInst* inst);
bool optimizeDivision(BinaryInst* inst);
bool optimizeComparison(BinaryInst* inst);
bool optimizeLogical(BinaryInst* inst);
// 强度削弱方法
bool tryStrengthReduction(Instruction* inst);
bool reduceMultiplication(BinaryInst* inst);
bool reduceDivision(BinaryInst* inst);
bool reducePower(CallInst* inst);
// 复杂乘法强度削弱方法
bool tryComplexMultiplication(BinaryInst* inst, Value* variable, int constant);
bool findOptimalShiftDecomposition(int constant, std::vector<int>& shifts);
Value* createShiftDecomposition(BinaryInst* inst, Value* variable, const std::vector<int>& shifts);
// 魔数乘法相关方法
MagicNumber computeMagicNumber(uint32_t divisor);
std::pair<int, int> computeMulhMagicNumbers(int divisor);
Value* createMagicDivision(BinaryInst* divInst, uint32_t divisor, const MagicNumber& magic);
Value* createMagicDivisionLibdivide(BinaryInst* divInst, int divisor);
bool isPowerOfTwo(uint32_t n);
int log2OfPowerOfTwo(uint32_t n);
// 辅助方法
bool isConstantInt(Value* val, int& constVal);
bool isConstantInt(Value* val, uint32_t& constVal);
ConstantInteger* getConstantInt(int val);
bool hasOnlyLocalUses(Instruction* inst);
void replaceWithOptimized(Instruction* original, Value* replacement);
};
// 全局强度削弱优化遍类
class GlobalStrengthReduction : public OptimizationPass {
private:
IRBuilder* builder; // IR构建器用于创建新指令
public:
// 静态成员作为该遍的唯一ID
static void* ID;
// 构造函数接受IRBuilder参数
explicit GlobalStrengthReduction(IRBuilder* builder)
: OptimizationPass("GlobalStrengthReduction", Granularity::Function), builder(builder) {}
// 在函数上运行优化
bool runOnFunction(Function* func, AnalysisManager& AM) override;
// 返回该遍的唯一ID
void* getPassID() const override { return ID; }
// 声明分析依赖
void getAnalysisUsage(std::set<void*>& analysisDependencies,
std::set<void*>& analysisInvalidations) const override;
};
} // namespace sysy

View File

@ -0,0 +1,252 @@
#pragma once
#include "Pass.h"
#include "IR.h"
#include "LoopCharacteristics.h"
#include "Loop.h"
#include "Dom.h"
#include "SideEffectAnalysis.h"
#include "AliasAnalysis.h"
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <memory>
namespace sysy {
// 前向声明
class LoopCharacteristicsResult;
class LoopAnalysisResult;
/**
* @brief 死归纳变量信息
* 记录一个可以被消除的归纳变量
*/
struct DeadInductionVariable {
PhiInst* phiInst; // phi 指令
std::vector<Instruction*> relatedInsts; // 相关的递增/递减指令
Loop* containingLoop; // 所在循环
bool canEliminate; // 是否可以安全消除
DeadInductionVariable(PhiInst* phi, Loop* loop)
: phiInst(phi), containingLoop(loop), canEliminate(false) {}
};
/**
* @brief 归纳变量消除上下文类
* 封装归纳变量消除优化的核心逻辑和状态
*/
class InductionVariableEliminationContext {
public:
InductionVariableEliminationContext() {}
/**
* 运行归纳变量消除优化
* @param F 目标函数
* @param AM 分析管理器
* @return 是否修改了IR
*/
bool run(Function* F, AnalysisManager& AM);
private:
// 分析结果缓存
LoopAnalysisResult* loopAnalysis = nullptr;
LoopCharacteristicsResult* loopCharacteristics = nullptr;
DominatorTree* dominatorTree = nullptr;
SideEffectAnalysisResult* sideEffectAnalysis = nullptr;
AliasAnalysisResult* aliasAnalysis = nullptr;
// 死归纳变量存储
std::vector<std::unique_ptr<DeadInductionVariable>> deadIVs;
std::unordered_map<Loop*, std::vector<DeadInductionVariable*>> loopToDeadIVs;
// ========== 核心分析和优化阶段 ==========
/**
* 阶段1识别死归纳变量
* 找出没有被有效使用的归纳变量
*/
void identifyDeadInductionVariables(Function* F);
/**
* 阶段2分析消除的安全性
* 确保消除操作不会破坏程序语义
*/
void analyzeSafetyForElimination();
/**
* 阶段3执行归纳变量消除
* 删除死归纳变量及其相关指令
*/
bool performInductionVariableElimination();
// ========== 辅助方法 ==========
/**
* 检查归纳变量是否为死归纳变量
* @param iv 归纳变量信息
* @param loop 所在循环
* @return 如果是死归纳变量返回相关信息否则返回nullptr
*/
std::unique_ptr<DeadInductionVariable>
isDeadInductionVariable(const InductionVarInfo* iv, Loop* loop);
/**
* 递归分析phi指令及其使用链是否都是死代码
* @param phiInst phi指令
* @param loop 所在循环
* @return phi指令是否可以安全删除
*/
bool isPhiInstructionDeadRecursively(PhiInst* phiInst, Loop* loop);
/**
* 递归分析指令的使用链是否都是死代码
* @param inst 要分析的指令
* @param loop 所在循环
* @param visited 已访问的指令集合(避免无限递归)
* @param currentPath 当前递归路径(检测循环依赖)
* @return 指令的使用链是否都是死代码
*/
bool isInstructionUseChainDeadRecursively(Instruction* inst, Loop* loop,
std::set<Instruction*>& visited,
std::set<Instruction*>& currentPath);
/**
* 检查循环是否有副作用
* @param loop 要检查的循环
* @return 循环是否有副作用
*/
bool loopHasSideEffects(Loop* loop);
/**
* 检查指令是否被用于循环退出条件
* @param inst 要检查的指令
* @param loop 所在循环
* @return 是否被用于循环退出条件
*/
bool isUsedInLoopExitCondition(Instruction* inst, Loop* loop);
/**
* 检查指令的结果是否未被有效使用
* @param inst 要检查的指令
* @param loop 所在循环
* @return 指令结果是否未被有效使用
*/
bool isInstructionResultUnused(Instruction* inst, Loop* loop);
/**
* 检查store指令是否存储到死地址利用别名分析
* @param store store指令
* @param loop 所在循环
* @return 是否存储到死地址
*/
bool isStoreToDeadLocation(StoreInst* store, Loop* loop);
/**
* 检查指令是否为死代码或只在循环内部使用
* @param inst 要检查的指令
* @param loop 所在循环
* @return 是否为死代码或只在循环内部使用
*/
bool isInstructionDeadOrInternalOnly(Instruction* inst, Loop* loop);
/**
* 检查指令是否有效地为死代码(带递归深度限制)
* @param inst 要检查的指令
* @param loop 所在循环
* @param maxDepth 最大递归深度
* @return 指令是否有效地为死代码
*/
bool isInstructionEffectivelyDead(Instruction* inst, Loop* loop, int maxDepth);
/**
* 检查store指令是否有后续的load操作
* @param store store指令
* @param loop 所在循环
* @return 是否有后续的load操作
*/
bool hasSubsequentLoad(StoreInst* store, Loop* loop);
/**
* 检查指令是否在循环外有使用
* @param inst 要检查的指令
* @param loop 所在循环
* @return 是否在循环外有使用
*/
bool hasUsageOutsideLoop(Instruction* inst, Loop* loop);
/**
* 检查store指令是否在循环外有后续的load操作
* @param store store指令
* @param loop 所在循环
* @return 是否在循环外有后续的load操作
*/
bool hasSubsequentLoadOutsideLoop(StoreInst* store, Loop* loop);
/**
* 递归检查基本块子树中是否有对指定位置的load操作
* @param bb 基本块
* @param ptr 指针
* @param visited 已访问的基本块集合
* @return 是否有load操作
*/
bool hasLoadInSubtree(BasicBlock* bb, Value* ptr, std::set<BasicBlock*>& visited);
/**
* 收集与归纳变量相关的所有指令
* @param phiInst phi指令
* @param loop 所在循环
* @return 相关指令列表
*/
std::vector<Instruction*> collectRelatedInstructions(PhiInst* phiInst, Loop* loop);
/**
* 检查消除归纳变量的安全性
* @param deadIV 死归纳变量
* @return 是否可以安全消除
*/
bool isSafeToEliminate(const DeadInductionVariable* deadIV);
/**
* 消除单个死归纳变量
* @param deadIV 死归纳变量
* @return 是否成功消除
*/
bool eliminateDeadInductionVariable(DeadInductionVariable* deadIV);
/**
* 打印调试信息
*/
void printDebugInfo();
};
/**
* @brief 归纳变量消除优化遍
* 消除循环中无用的归纳变量,减少寄存器压力
*/
class InductionVariableElimination : public OptimizationPass {
public:
// 唯一的 Pass ID
static void *ID;
InductionVariableElimination()
: OptimizationPass("InductionVariableElimination", Granularity::Function) {}
/**
* 在函数上运行归纳变量消除优化
* @param F 目标函数
* @param AM 分析管理器
* @return 是否修改了IR
*/
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,40 @@
#pragma once
#include "Pass.h"
#include "Loop.h"
#include "LoopCharacteristics.h"
#include "Dom.h"
#include <unordered_set>
#include <vector>
namespace sysy{
class LICMContext {
public:
LICMContext(Function* func, Loop* loop, IRBuilder* builder, const LoopCharacteristics* chars)
: func(func), loop(loop), builder(builder), chars(chars) {}
// 运行LICM主流程返回IR是否被修改
bool run();
private:
Function* func;
Loop* loop;
IRBuilder* builder;
const LoopCharacteristics* chars; // 特征分析结果
// 外提所有可提升指令
bool hoistInstructions();
};
class LICM : public OptimizationPass{
private:
IRBuilder *builder; ///< IR构建器用于插入指令
public:
static void *ID;
LICM(IRBuilder *builder = nullptr) : OptimizationPass("LICM", Granularity::Function) , builder(builder) {}
bool runOnFunction(Function *F, AnalysisManager &AM) override;
void getAnalysisUsage(std::set<void *> &, std::set<void *> &) 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,155 @@
#pragma once
#include "Loop.h" // 循环分析依赖
#include "Dom.h" // 支配树分析依赖
#include "IR.h" // IR定义
#include "IRBuilder.h" // IR构建器
#include "Pass.h" // Pass框架
#include <memory>
#include <set>
#include <vector>
namespace sysy {
/**
* @brief 循环规范化转换Pass
*
* 该Pass在循环不变量提升等优化前运行主要负责
* 1. 为没有前置块(preheader)的循环创建前置块
* 2. 确保循环结构符合后续优化的要求
* 3. 规范化循环的控制流结构
*
* 前置块的作用:
* - 为循环不变量提升提供插入位置
* - 简化循环分析和优化
* - 确保循环有唯一的入口点
*/
class LoopNormalizationPass : public OptimizationPass {
public:
// 唯一的 Pass ID
static void *ID;
LoopNormalizationPass(IRBuilder* builder) : OptimizationPass("LoopNormalization", Pass::Granularity::Function), builder(builder) {}
// 实现 getPassID
void *getPassID() const override { return &ID; }
// 核心运行方法
bool runOnFunction(Function *F, AnalysisManager &AM) override;
// 声明分析依赖和失效信息
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
private:
// ========== IR构建器 ==========
IRBuilder* builder; // IR构建器
// ========== 缓存的分析结果 ==========
LoopAnalysisResult* loopAnalysis; // 循环结构分析结果
DominatorTree* domTree; // 支配树分析结果
// ========== 规范化统计 ==========
struct NormalizationStats {
size_t totalLoops; // 总循环数
size_t loopsNeedingPreheader; // 需要前置块的循环数
size_t preheadersCreated; // 创建的前置块数
size_t loopsNormalized; // 规范化的循环数
size_t redundantPhisRemoved; // 删除的冗余PHI节点数
NormalizationStats() : totalLoops(0), loopsNeedingPreheader(0),
preheadersCreated(0), loopsNormalized(0),
redundantPhisRemoved(0) {}
} stats;
// ========== 核心规范化方法 ==========
/**
* 规范化单个循环
* @param loop 要规范化的循环
* @return 是否进行了修改
*/
bool normalizeLoop(Loop* loop);
/**
* 为循环创建前置块
* @param loop 需要前置块的循环
* @return 创建的前置块如果失败则返回nullptr
*/
BasicBlock* createPreheaderForLoop(Loop* loop);
/**
* 检查循环是否需要前置块(基于结构性需求)
* @param loop 要检查的循环
* @return true如果需要前置块
*/
bool needsPreheader(Loop* loop);
/**
* 检查循环是否已有合适的前置块
* @param loop 要检查的循环
* @return 现有的前置块如果没有则返回nullptr
*/
BasicBlock* getExistingPreheader(Loop* loop);
/**
* 更新支配树关系(在创建新块后)
* @param newBlock 新创建的基本块
* @param loop 相关的循环
*/
void updateDominatorRelations(BasicBlock* newBlock, Loop* loop);
/**
* 重定向循环外的前驱块到新的前置块
* @param loop 目标循环
* @param preheader 新创建的前置块
* @param header 循环头部
*/
void redirectExternalPredecessors(Loop* loop, BasicBlock* preheader, BasicBlock* header, const std::vector<BasicBlock*>& externalPreds);
/**
* 为前置块生成合适的名称
* @param loop 相关的循环
* @return 生成的前置块名称
*/
std::string generatePreheaderName(Loop* loop);
/**
* 验证规范化结果的正确性
* @param loop 规范化后的循环
* @return true如果规范化正确
*/
bool validateNormalization(Loop* loop);
// ========== 辅助方法 ==========
/**
* 获取循环的外部前驱块(不在循环内的前驱)
* @param loop 目标循环
* @return 外部前驱块列表
*/
std::vector<BasicBlock*> getExternalPredecessors(Loop* loop);
/**
* 检查基本块是否适合作为前置块
* @param block 候选基本块
* @param loop 目标循环
* @return true如果适合作为前置块
*/
bool isSuitableAsPreheader(BasicBlock* block, Loop* loop);
/**
* 更新PHI节点以适应新的前置块
* @param header 循环头部
* @param preheader 新的前置块
* @param oldPreds 原来的外部前驱
*/
void updatePhiNodesForPreheader(BasicBlock* header, BasicBlock* preheader,
const std::vector<BasicBlock*>& oldPreds);
/**
* 打印规范化统计信息
*/
void printStats(Function* F);
};
} // namespace sysy

View File

@ -0,0 +1,233 @@
#pragma once
#include "Pass.h"
#include "IR.h"
#include "LoopCharacteristics.h"
#include "Loop.h"
#include "Dom.h"
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <memory>
namespace sysy {
// 前向声明
class LoopCharacteristicsResult;
class LoopAnalysisResult;
/**
* @brief 强度削弱候选项信息
* 记录一个可以进行强度削弱的表达式信息
*/
struct StrengthReductionCandidate {
enum OpType {
MULTIPLY, // 乘法: iv * const
DIVIDE, // 除法: iv / 2^n (转换为右移)
DIVIDE_CONST, // 除法: iv / const (使用mulh指令优化)
REMAINDER // 取模: iv % 2^n (转换为位与)
};
enum DivisionStrategy {
SIMPLE_SHIFT, // 简单右移(仅适用于无符号或非负数)
SIGNED_CORRECTION, // 有符号除法修正: (x + (x >> 31) & mask) >> k
MULH_OPTIMIZATION // 使用mulh指令优化任意常数除法
};
Instruction* originalInst; // 原始指令 (如 i*4, i/8, i%16)
Value* inductionVar; // 归纳变量 (如 i)
OpType operationType; // 操作类型
DivisionStrategy divStrategy; // 除法策略(仅用于除法)
int multiplier; // 乘数/除数/模数 (如 4, 8, 16)
int shiftAmount; // 位移量 (对于2的幂)
int offset; // 偏移量 (如常数项)
BasicBlock* containingBlock; // 所在基本块
Loop* containingLoop; // 所在循环
bool hasNegativeValues; // 归纳变量是否可能为负数
// 强度削弱后的新变量
PhiInst* newPhi = nullptr; // 新的 phi 指令
Value* newInductionVar = nullptr; // 新的归纳变量
StrengthReductionCandidate(Instruction* inst, Value* iv, OpType opType, int value, int off,
BasicBlock* bb, Loop* loop)
: originalInst(inst), inductionVar(iv), operationType(opType),
divStrategy(SIMPLE_SHIFT), multiplier(value), offset(off),
containingBlock(bb), containingLoop(loop), hasNegativeValues(false) {
// 计算位移量(用于除法和取模的强度削弱)
if (opType == DIVIDE || opType == REMAINDER) {
shiftAmount = 0;
int temp = value;
while (temp > 1) {
temp >>= 1;
shiftAmount++;
}
} else {
shiftAmount = 0;
}
}
};
/**
* @brief 强度削弱上下文类
* 封装强度削弱优化的核心逻辑和状态
*/
class StrengthReductionContext {
public:
StrengthReductionContext(IRBuilder* builder) : builder(builder) {}
/**
* 运行强度削弱优化
* @param F 目标函数
* @param AM 分析管理器
* @return 是否修改了IR
*/
bool run(Function* F, AnalysisManager& AM);
private:
IRBuilder* builder;
// 分析结果缓存
LoopAnalysisResult* loopAnalysis = nullptr;
LoopCharacteristicsResult* loopCharacteristics = nullptr;
DominatorTree* dominatorTree = nullptr;
// 候选项存储
std::vector<std::unique_ptr<StrengthReductionCandidate>> candidates;
std::unordered_map<Loop*, std::vector<StrengthReductionCandidate*>> loopToCandidates;
// ========== 核心分析和优化阶段 ==========
/**
* 阶段1识别强度削弱候选项
* 扫描所有循环中的乘法指令,找出可以优化的模式
*/
void identifyStrengthReductionCandidates(Function* F);
/**
* 阶段2分析候选项的优化潜力
* 评估每个候选项的收益,过滤掉不值得优化的情况
*/
void analyzeOptimizationPotential();
/**
* 阶段3执行强度削弱变换
* 对选中的候选项执行实际的强度削弱优化
*/
bool performStrengthReduction();
// ========== 辅助分析函数 ==========
/**
* 分析归纳变量是否可能取负值
* @param ivInfo 归纳变量信息
* @param loop 所属循环
* @return 如果可能为负数返回true
*/
bool analyzeInductionVariableRange(const InductionVarInfo* ivInfo, Loop* loop) const;
/**
* 生成除法替换代码
* @param candidate 优化候选项
* @param builder IR构建器
* @return 替换值
*/
Value* generateDivisionReplacement(StrengthReductionCandidate* candidate, IRBuilder* builder) const;
/**
* 生成任意常数除法替换代码
* @param candidate 优化候选项
* @param builder IR构建器
* @return 替换值
*/
Value* generateConstantDivisionReplacement(StrengthReductionCandidate* candidate, IRBuilder* builder) const;
/**
* 检查指令是否为强度削弱候选项
* @param inst 要检查的指令
* @param loop 所在循环
* @return 如果是候选项返回候选项信息否则返回nullptr
*/
std::unique_ptr<StrengthReductionCandidate>
isStrengthReductionCandidate(Instruction* inst, Loop* loop);
/**
* 检查值是否为循环的归纳变量
* @param val 要检查的值
* @param loop 循环
* @param characteristics 循环特征信息
* @return 如果是归纳变量返回归纳变量信息否则返回nullptr
*/
const InductionVarInfo*
getInductionVarInfo(Value* val, Loop* loop, const LoopCharacteristics* characteristics);
/**
* 为候选项创建新的归纳变量
* @param candidate 候选项
* @return 是否成功创建
*/
bool createNewInductionVariable(StrengthReductionCandidate* candidate);
/**
* 替换原始指令的所有使用
* @param candidate 候选项
* @return 是否成功替换
*/
bool replaceOriginalInstruction(StrengthReductionCandidate* candidate);
/**
* 估算优化收益
* 计算强度削弱后的性能提升
* @param candidate 候选项
* @return 估算的收益分数
*/
double estimateOptimizationBenefit(const StrengthReductionCandidate* candidate);
/**
* 检查优化的合法性
* @param candidate 候选项
* @return 是否可以安全地进行优化
*/
bool isOptimizationLegal(const StrengthReductionCandidate* candidate);
/**
* 打印调试信息
*/
void printDebugInfo();
};
/**
* @brief 循环强度削弱优化遍
* 将循环中的乘法运算转换为更高效的加法运算
*/
class LoopStrengthReduction : public OptimizationPass {
public:
// 唯一的 Pass ID
static void *ID;
LoopStrengthReduction(IRBuilder* builder)
: OptimizationPass("LoopStrengthReduction", Granularity::Function),
builder(builder) {}
/**
* 在函数上运行强度削弱优化
* @param F 目标函数
* @param AM 分析管理器
* @return 是否修改了IR
*/
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; }
private:
IRBuilder* builder;
};
} // namespace sysy

View File

@ -3,6 +3,8 @@
#include "IR.h"
#include "Pass.h"
#include "SysYIROptUtils.h"
#include "AliasAnalysis.h"
#include "SideEffectAnalysis.h"
#include <cassert>
#include <iostream>
#include <map>
@ -63,6 +65,8 @@ struct SSAPValue {
class SCCPContext {
private:
IRBuilder *builder; // IR 构建器,用于插入指令和创建常量
AliasAnalysisResult *aliasAnalysis; // 别名分析结果
SideEffectAnalysisResult *sideEffectAnalysis; // 副作用分析结果
// 工作列表
// 存储需要重新评估的指令
@ -92,6 +96,14 @@ private:
SSAPValue ComputeConstant(BinaryInst *binaryinst, SSAPValue lhsVal, SSAPValue rhsVal);
// 辅助函数:对一元操作进行常量折叠
SSAPValue ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVal);
// 辅助函数:检查是否为已知的纯函数
bool isKnownPureFunction(const std::string &funcName) const;
// 辅助函数:计算纯函数的常量结果
SSAPValue computePureFunctionResult(CallInst *call, const std::vector<SSAPValue> &argValues);
// 辅助函数:查找存储到指定位置的常量值
SSAPValue findStoredConstantValue(Value *ptr, BasicBlock *currentBB);
// 辅助函数动态检查数组访问是否为常量索引考虑SCCP状态
bool hasRuntimeConstantAccess(Value *ptr);
// 主要优化阶段
// 阶段1: 常量传播与折叠
@ -117,7 +129,13 @@ private:
void RemovePhiIncoming(BasicBlock *phiParentBB, BasicBlock *removedPred);
public:
SCCPContext(IRBuilder *builder) : builder(builder) {}
SCCPContext(IRBuilder *builder) : builder(builder), aliasAnalysis(nullptr), sideEffectAnalysis(nullptr) {}
// 设置别名分析结果
void setAliasAnalysis(AliasAnalysisResult *aa) { aliasAnalysis = aa; }
// 设置副作用分析结果
void setSideEffectAnalysis(SideEffectAnalysisResult *sea) { sideEffectAnalysis = sea; }
// 运行 SCCP 优化
void run(Function *func, AnalysisManager &AM);

View File

@ -48,13 +48,6 @@ public:
}
}
}
// 清空 User 的 operands 向量。这会递减 User 持有的 shared_ptr<Use> 的引用计数。
// 当引用计数降为 0 时Use 对象本身将被销毁。
// User::operands.clear(); // 这个步骤会在 Instruction 的析构函数中自动完成,因为它是 vector 成员
// 或者我们可以在 User::removeOperand 方法中确保 Use 对象从 operands 中移除。
// 实际上,只要 Value::removeUse(use_ptr) 被调用了,
// 当 Instruction 所在的 unique_ptr 销毁时,它的 operands vector 也会被销毁。
// 所以这里不需要显式 clear()
}
static void usedelete(Instruction *inst) {
assert(inst && "Instruction to delete cannot be null.");
@ -75,7 +68,7 @@ public:
// 步骤3: 物理删除指令
// 这会导致 Instruction 对象的 unique_ptr 销毁,从而调用其析构函数链。
parentBlock->removeInst(inst);
}
}
static BasicBlock::iterator usedelete(BasicBlock::iterator inst_it) {
Instruction *inst_to_delete = inst_it->get();
@ -92,7 +85,7 @@ public:
// 步骤3: 物理删除指令并返回下一个迭代器
return parentBlock->removeInst(inst_it);
}
}
// 判断是否是全局变量
static bool isGlobal(Value *val) {
@ -114,6 +107,190 @@ public:
// 所以当AllocaInst的basetype是PointerType时一维数组或者是指向ArrayType的PointerType多位数组返回true
return aval && (baseType->isPointer() || baseType->as<PointerType>()->getBaseType()->isArray());
}
//该实现参考了libdivide的算法
static std::pair<int, int> computeMulhMagicNumbers(int divisor) {
if (DEBUG) {
std::cout << "\n[SR] ===== Computing magic numbers for divisor " << divisor << " (libdivide algorithm) =====" << std::endl;
}
if (divisor == 0) {
if (DEBUG) std::cout << "[SR] Error: divisor must be != 0" << std::endl;
return {-1, -1};
}
// libdivide 常数
const uint8_t LIBDIVIDE_ADD_MARKER = 0x40;
const uint8_t LIBDIVIDE_NEGATIVE_DIVISOR = 0x80;
// 辅助函数:计算前导零个数
auto count_leading_zeros32 = [](uint32_t val) -> uint32_t {
if (val == 0) return 32;
return __builtin_clz(val);
};
// 辅助函数64位除法返回32位商和余数
auto div_64_32 = [](uint32_t high, uint32_t low, uint32_t divisor, uint32_t* rem) -> uint32_t {
uint64_t dividend = ((uint64_t)high << 32) | low;
uint32_t quotient = dividend / divisor;
*rem = dividend % divisor;
return quotient;
};
if (DEBUG) {
std::cout << "[SR] Input divisor: " << divisor << std::endl;
}
// libdivide_internal_s32_gen 算法实现
int32_t d = divisor;
uint32_t ud = (uint32_t)d;
uint32_t absD = (d < 0) ? -ud : ud;
if (DEBUG) {
std::cout << "[SR] absD = " << absD << std::endl;
}
uint32_t floor_log_2_d = 31 - count_leading_zeros32(absD);
if (DEBUG) {
std::cout << "[SR] floor_log_2_d = " << floor_log_2_d << std::endl;
}
// 检查 absD 是否为2的幂
if ((absD & (absD - 1)) == 0) {
if (DEBUG) {
std::cout << "[SR] " << absD << " 是2的幂使用移位方法" << std::endl;
}
// 对于2的幂我们只使用移位不需要魔数
int shift = floor_log_2_d;
if (d < 0) shift |= 0x80; // 标记负数
if (DEBUG) {
std::cout << "[SR] Power of 2 result: magic=0, shift=" << shift << std::endl;
std::cout << "[SR] ===== End magic computation =====" << std::endl;
}
// 对于我们的目的我们将在IR生成中以不同方式处理2的幂
// 返回特殊标记
return {0, shift};
}
if (DEBUG) {
std::cout << "[SR] " << absD << " is not a power of 2, computing magic number" << std::endl;
}
// 非2的幂除数的魔数计算
uint8_t more;
uint32_t rem, proposed_m;
// 计算 proposed_m = floor(2^(floor_log_2_d + 31) / absD)
proposed_m = div_64_32((uint32_t)1 << (floor_log_2_d - 1), 0, absD, &rem);
const uint32_t e = absD - rem;
if (DEBUG) {
std::cout << "[SR] proposed_m = " << proposed_m << ", rem = " << rem << ", e = " << e << std::endl;
}
// 确定是否需要"加法"版本
const bool branchfree = false; // 使用分支版本
if (!branchfree && e < ((uint32_t)1 << floor_log_2_d)) {
// 这个幂次有效
more = (uint8_t)(floor_log_2_d - 1);
if (DEBUG) {
std::cout << "[SR] Using basic algorithm, shift = " << (int)more << std::endl;
}
} else {
// 我们需要上升一个等级
proposed_m += proposed_m;
const uint32_t twice_rem = rem + rem;
if (twice_rem >= absD || twice_rem < rem) {
proposed_m += 1;
}
more = (uint8_t)(floor_log_2_d | LIBDIVIDE_ADD_MARKER);
if (DEBUG) {
std::cout << "[SR] Using add algorithm, proposed_m = " << proposed_m << ", more = " << (int)more << std::endl;
}
}
proposed_m += 1;
int32_t magic = (int32_t)proposed_m;
// 处理负除数
if (d < 0) {
more |= LIBDIVIDE_NEGATIVE_DIVISOR;
if (!branchfree) {
magic = -magic;
}
if (DEBUG) {
std::cout << "[SR] Negative divisor, magic = " << magic << ", more = " << (int)more << std::endl;
}
}
// 为我们的IR生成提取移位量和标志
int shift = more & 0x3F; // 移除标志保留移位量位0-5
bool need_add = (more & LIBDIVIDE_ADD_MARKER) != 0;
bool is_negative = (more & LIBDIVIDE_NEGATIVE_DIVISOR) != 0;
if (DEBUG) {
std::cout << "[SR] Final result: magic = " << magic << ", more = " << (int)more
<< " (0x" << std::hex << (int)more << std::dec << ")" << std::endl;
std::cout << "[SR] Shift = " << shift << ", need_add = " << need_add
<< ", is_negative = " << is_negative << std::endl;
// Test the magic number using the correct libdivide algorithm
std::cout << "[SR] Testing magic number (libdivide algorithm):" << std::endl;
int test_values[] = {1, 7, 37, 100, 999, -1, -7, -37, -100};
for (int test_val : test_values) {
int64_t quotient;
// 实现正确的libdivide算法
int64_t product = (int64_t)test_val * magic;
int64_t high_bits = product >> 32;
if (need_add) {
// ADD_MARKER情况移位前加上被除数
// 这是libdivide的关键洞察
high_bits += test_val;
quotient = high_bits >> shift;
} else {
// 正常情况:只是移位
quotient = high_bits >> shift;
}
// 符号修正这是libdivide有符号除法的关键部分
// 如果被除数为负商需要加1来匹配C语言的截断除法语义
if (test_val < 0) {
quotient += 1;
}
int expected = test_val / divisor;
bool correct = (quotient == expected);
std::cout << "[SR] " << test_val << " / " << divisor << " = " << quotient
<< " (expected " << expected << ") " << (correct ? "" : "") << std::endl;
}
std::cout << "[SR] ===== End magic computation =====" << std::endl;
}
// 返回魔数、移位量并在移位中编码ADD_MARKER标志
// 我们将使用移位的第6位表示ADD_MARKER第7位表示负数如果需要
int encoded_shift = shift;
if (need_add) {
encoded_shift |= 0x40; // 设置第6位表示ADD_MARKER
if (DEBUG) {
std::cout << "[SR] Encoding ADD_MARKER in shift: " << encoded_shift << std::endl;
}
}
return {magic, encoded_shift};
}
};
}// namespace sysy

View File

@ -0,0 +1,39 @@
#pragma once
#include "Pass.h"
#include "Dom.h"
#include "Loop.h"
namespace sysy {
/**
* @class TailCallOpt
* @brief 优化尾调用的中端优化通道。
*
* 该类实现了一个针对函数级别的尾调用优化的优化通道OptimizationPass
* 通过分析和转换 IR中间表示将可优化的尾调用转换为更高效的形式
* 以减少函数调用的开销,提升程序性能。
*
* @note 需要传入 IRBuilder 指针用于 IR 构建和修改。
*
* @method runOnFunction
* 对指定函数进行尾调用优化。
*
* @method getPassID
* 获取当前优化通道的唯一标识符。
*
* @method getAnalysisUsage
* 指定该优化通道所依赖和失效的分析集合。
*/
class TailCallOpt : public OptimizationPass {
private:
IRBuilder* builder;
public:
TailCallOpt(IRBuilder* builder) : OptimizationPass("TailCallOpt", Granularity::Function), builder(builder) {}
static void *ID;
bool runOnFunction(Function *F, AnalysisManager &AM) override;
void *getPassID() const override { return &ID; }
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
};
} // namespace sysy

View File

@ -151,17 +151,21 @@ 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: {
// 检查是否已存在有效结果
auto it = moduleCachedResults.find(analysisID);
if (it != moduleCachedResults.end()) {
if(DEBUG) {
std::cout << "Using cached result for Analysis Pass: " << analysisPass->getName() << "\n";
}
return static_cast<T *>(it->second.get()); // 返回缓存结果
}
// 只有在实际运行时才打印调试信息
if(DEBUG){
std::cout << "Running Analysis Pass: " << analysisPass->getName() << "\n";
}
// 运行模块级分析遍
if (!pModuleRef) {
std::cerr << "Error: Module reference not set for AnalysisManager to run Module Pass.\n";
@ -183,8 +187,16 @@ public:
// 检查是否已存在有效结果
auto it = functionCachedResults.find({F, analysisID});
if (it != functionCachedResults.end()) {
if(DEBUG) {
std::cout << "Using cached result for Analysis Pass: " << analysisPass->getName() << " (Function: " << F->getName() << ")\n";
}
return static_cast<T *>(it->second.get()); // 返回缓存结果
}
// 只有在实际运行时才打印调试信息
if(DEBUG){
std::cout << "Running Analysis Pass: " << analysisPass->getName() << "\n";
std::cout << "Function: " << F->getName() << "\n";
}
// 运行函数级分析遍
analysisPass->runOnFunction(F, *this);
// 获取结果并缓存
@ -202,8 +214,16 @@ public:
// 检查是否已存在有效结果
auto it = basicBlockCachedResults.find({BB, analysisID});
if (it != basicBlockCachedResults.end()) {
if(DEBUG) {
std::cout << "Using cached result for Analysis Pass: " << analysisPass->getName() << " (BasicBlock: " << BB->getName() << ")\n";
}
return static_cast<T *>(it->second.get()); // 返回缓存结果
}
// 只有在实际运行时才打印调试信息
if(DEBUG){
std::cout << "Running Analysis Pass: " << analysisPass->getName() << "\n";
std::cout << "BasicBlock: " << BB->getName() << "\n";
}
// 运行基本块级分析遍
analysisPass->runOnBasicBlock(BB, *this);
// 获取结果并缓存
@ -279,7 +299,7 @@ private:
IRBuilder *pBuilder;
public:
PassManager() = default;
PassManager() = delete;
~PassManager() = default;
PassManager(Module *module, IRBuilder *builder) : pmodule(module) ,pBuilder(builder), analysisManager(module) {}

View File

@ -86,7 +86,60 @@ private:
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;
@ -167,6 +220,15 @@ public:
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);

View File

@ -6,11 +6,26 @@ add_library(midend_lib STATIC
Pass/Pass.cpp
Pass/Analysis/Dom.cpp
Pass/Analysis/Liveness.cpp
Pass/Analysis/Loop.cpp
Pass/Analysis/LoopCharacteristics.cpp
Pass/Analysis/LoopVectorization.cpp
Pass/Analysis/AliasAnalysis.cpp
Pass/Analysis/SideEffectAnalysis.cpp
Pass/Analysis/CallGraphAnalysis.cpp
Pass/Optimize/DCE.cpp
Pass/Optimize/Mem2Reg.cpp
Pass/Optimize/Reg2Mem.cpp
Pass/Optimize/GVN.cpp
Pass/Optimize/SysYIRCFGOpt.cpp
Pass/Optimize/SCCP.cpp
Pass/Optimize/LoopNormalization.cpp
Pass/Optimize/LICM.cpp
Pass/Optimize/LoopStrengthReduction.cpp
Pass/Optimize/InductionVariableElimination.cpp
Pass/Optimize/GlobalStrengthReduction.cpp
Pass/Optimize/BuildCFG.cpp
Pass/Optimize/LargeArrayToGlobal.cpp
Pass/Optimize/TailCallOpt.cpp
)
# 包含中端模块所需的头文件路径

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,559 @@
#include "AliasAnalysis.h"
#include "SysYIRPrinter.h"
#include <iostream>
extern int DEBUG;
namespace sysy {
// 静态成员初始化
void *SysYAliasAnalysisPass::ID = (void *)&SysYAliasAnalysisPass::ID;
// ========== AliasAnalysisResult 实现 ==========
void AliasAnalysisResult::print() const {
std::cout << "---- Alias Analysis Results for Function: " << AssociatedFunction->getName() << " ----\n";
// 打印内存位置信息
std::cout << " Memory Locations (" << LocationMap.size() << "):\n";
for (const auto& pair : LocationMap) {
const auto& loc = pair.second;
std::cout << " - Base: " << loc->basePointer->getName();
std::cout << " (Type: ";
if (loc->isLocalArray) std::cout << "Local";
else if (loc->isFunctionParameter) std::cout << "Parameter";
else if (loc->isGlobalArray) std::cout << "Global";
else std::cout << "Unknown";
std::cout << ")\n";
}
// 打印别名关系
std::cout << " Alias Relations (" << AliasMap.size() << "):\n";
for (const auto& pair : AliasMap) {
std::cout << " - (" << pair.first.first->getName() << ", " << pair.first.second->getName() << "): ";
switch (pair.second) {
case AliasType::NO_ALIAS: std::cout << "No Alias"; break;
case AliasType::SELF_ALIAS: std::cout << "Self Alias"; break;
case AliasType::POSSIBLE_ALIAS: std::cout << "Possible Alias"; break;
case AliasType::UNKNOWN_ALIAS: std::cout << "Unknown Alias"; break;
}
std::cout << "\n";
}
std::cout << "-----------------------------------------------------------\n";
}
AliasType AliasAnalysisResult::queryAlias(Value* ptr1, Value* ptr2) const {
auto key = std::make_pair(ptr1, ptr2);
auto it = AliasMap.find(key);
if (it != AliasMap.end()) {
return it->second;
}
// 尝试反向查找
key = std::make_pair(ptr2, ptr1);
it = AliasMap.find(key);
if (it != AliasMap.end()) {
return it->second;
}
return AliasType::UNKNOWN_ALIAS; // 保守估计
}
const MemoryLocation* AliasAnalysisResult::getMemoryLocation(Value* ptr) const {
auto it = LocationMap.find(ptr);
return (it != LocationMap.end()) ? it->second.get() : nullptr;
}
bool AliasAnalysisResult::isLocalArray(Value* ptr) const {
const MemoryLocation* loc = getMemoryLocation(ptr);
return loc && loc->isLocalArray;
}
bool AliasAnalysisResult::isFunctionParameter(Value* ptr) const {
const MemoryLocation* loc = getMemoryLocation(ptr);
return loc && loc->isFunctionParameter;
}
bool AliasAnalysisResult::isGlobalArray(Value* ptr) const {
const MemoryLocation* loc = getMemoryLocation(ptr);
return loc && loc->isGlobalArray;
}
bool AliasAnalysisResult::hasConstantAccess(Value* ptr) const {
const MemoryLocation* loc = getMemoryLocation(ptr);
return loc && loc->hasConstantIndices;
}
AliasAnalysisResult::Statistics AliasAnalysisResult::getStatistics() const {
Statistics stats = {0};
stats.totalQueries = AliasMap.size();
for (auto& pair : AliasMap) {
switch (pair.second) {
case AliasType::NO_ALIAS: stats.noAlias++; break;
case AliasType::SELF_ALIAS: stats.selfAlias++; break;
case AliasType::POSSIBLE_ALIAS: stats.possibleAlias++; break;
case AliasType::UNKNOWN_ALIAS: stats.unknownAlias++; break;
}
}
for (auto& loc : LocationMap) {
if (loc.second->isLocalArray) stats.localArrays++;
if (loc.second->isFunctionParameter) stats.functionParameters++;
if (loc.second->isGlobalArray) stats.globalArrays++;
if (loc.second->hasConstantIndices) stats.constantAccesses++;
}
return stats;
}
void AliasAnalysisResult::printStatics() const {
std::cout << "=== Alias Analysis Results ===" << std::endl;
auto stats = getStatistics();
std::cout << "Total queries: " << stats.totalQueries << std::endl;
std::cout << "No alias: " << stats.noAlias << std::endl;
std::cout << "Self alias: " << stats.selfAlias << std::endl;
std::cout << "Possible alias: " << stats.possibleAlias << std::endl;
std::cout << "Unknown alias: " << stats.unknownAlias << std::endl;
std::cout << "Local arrays: " << stats.localArrays << std::endl;
std::cout << "Function parameters: " << stats.functionParameters << std::endl;
std::cout << "Global arrays: " << stats.globalArrays << std::endl;
std::cout << "Constant accesses: " << stats.constantAccesses << std::endl;
}
void AliasAnalysisResult::addMemoryLocation(std::unique_ptr<MemoryLocation> location) {
Value* ptr = location->accessPointer;
LocationMap[ptr] = std::move(location);
}
void AliasAnalysisResult::addAliasRelation(Value* ptr1, Value* ptr2, AliasType type) {
auto key = std::make_pair(ptr1, ptr2);
AliasMap[key] = type;
}
// ========== SysYAliasAnalysisPass 实现 ==========
bool SysYAliasAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
if (DEBUG) {
std::cout << "Running SysY Alias Analysis on function: " << F->getName() << std::endl;
}
// 创建分析结果
CurrentResult = std::make_unique<AliasAnalysisResult>(F);
// 执行主要分析步骤
collectMemoryAccesses(F);
buildAliasRelations(F);
optimizeForSysY(F);
if (DEBUG) {
CurrentResult->print();
CurrentResult->printStatics();
}
return false; // 分析遍不修改IR
}
void SysYAliasAnalysisPass::collectMemoryAccesses(Function* F) {
// 收集函数中所有内存访问指令
for (auto& bb : F->getBasicBlocks()) {
for (auto& inst : bb->getInstructions()) {
Value* ptr = nullptr;
if (auto* loadInst = dynamic_cast<LoadInst*>(inst.get())) {
ptr = loadInst->getPointer();
} else if (auto* storeInst = dynamic_cast<StoreInst*>(inst.get())) {
ptr = storeInst->getPointer();
}
if (ptr) {
// 创建内存位置信息
auto location = createMemoryLocation(ptr);
location->accessInsts.push_back(inst.get());
// 更新读写标记
if (dynamic_cast<LoadInst*>(inst.get())) {
location->hasReads = true;
} else {
location->hasWrites = true;
}
CurrentResult->addMemoryLocation(std::move(location));
}
}
}
}
void SysYAliasAnalysisPass::buildAliasRelations(Function *F) {
// 构建所有内存访问之间的别名关系
auto& locationMap = CurrentResult->LocationMap;
std::vector<Value*> allPointers;
for (auto& pair : locationMap) {
allPointers.push_back(pair.first);
}
// 两两比较所有指针
for (size_t i = 0; i < allPointers.size(); ++i) {
for (size_t j = i + 1; j < allPointers.size(); ++j) {
Value* ptr1 = allPointers[i];
Value* ptr2 = allPointers[j];
MemoryLocation* loc1 = locationMap[ptr1].get();
MemoryLocation* loc2 = locationMap[ptr2].get();
AliasType aliasType = analyzeAliasBetween(loc1, loc2);
CurrentResult->addAliasRelation(ptr1, ptr2, aliasType);
}
}
}
void SysYAliasAnalysisPass::optimizeForSysY(Function* F) {
// SysY特化优化
applySysYConstraints(F);
optimizeParameterAnalysis(F);
optimizeArrayAccessAnalysis(F);
}
std::unique_ptr<MemoryLocation> SysYAliasAnalysisPass::createMemoryLocation(Value* ptr) {
Value* basePtr = getBasePointer(ptr);
auto location = std::make_unique<MemoryLocation>(basePtr, ptr);
// 分析内存类型和索引模式
analyzeMemoryType(location.get());
analyzeIndexPattern(location.get());
return location;
}
Value* SysYAliasAnalysisPass::getBasePointer(Value* ptr) {
// 递归剥离GEP指令找到真正的基指针
if (auto* gepInst = dynamic_cast<GetElementPtrInst*>(ptr)) {
return getBasePointer(gepInst->getBasePointer());
}
return ptr;
}
void SysYAliasAnalysisPass::analyzeMemoryType(MemoryLocation* location) {
Value* base = location->basePointer;
// 检查内存类型
if (dynamic_cast<AllocaInst*>(base)) {
location->isLocalArray = true;
} else if (dynamic_cast<Argument*>(base)) {
location->isFunctionParameter = true;
} else if (dynamic_cast<GlobalValue*>(base)) {
location->isGlobalArray = true;
}
}
void SysYAliasAnalysisPass::analyzeIndexPattern(MemoryLocation* location) {
// 分析GEP指令的索引模式
if (auto* gepInst = dynamic_cast<GetElementPtrInst*>(location->accessPointer)) {
// 初始化为true如果发现非常量索引则设为false
location->hasConstantIndices = true;
// 收集所有索引
for (unsigned i = 0; i < gepInst->getNumIndices(); ++i) {
Value* index = gepInst->getIndex(i);
location->indices.push_back(index);
// 检查是否为常量索引
if (!isConstantValue(index)) {
location->hasConstantIndices = false;
}
}
// 检查是否包含循环变量
Function* containingFunc = nullptr;
if (auto* inst = dynamic_cast<Instruction*>(location->basePointer)) {
containingFunc = inst->getParent()->getParent();
} else if (auto* arg = dynamic_cast<Argument*>(location->basePointer)) {
containingFunc = arg->getParent();
}
if (containingFunc) {
location->hasLoopVariableIndex = hasLoopVariableInIndices(location->indices, containingFunc);
}
// 计算常量偏移
if (location->hasConstantIndices) {
location->constantOffset = calculateConstantOffset(location->indices);
}
}
}
AliasType SysYAliasAnalysisPass::analyzeAliasBetween(MemoryLocation* loc1, MemoryLocation* loc2) {
// 分析两个内存位置之间的别名关系
// 1. 相同基指针的情况需要进一步分析索引
if (loc1->basePointer == loc2->basePointer) {
// 如果是同一个访问指针,那就是完全相同的内存位置
if (loc1->accessPointer == loc2->accessPointer) {
return AliasType::SELF_ALIAS;
}
// 相同基指针但不同访问指针,需要比较索引
return compareIndices(loc1, loc2);
}
// 2. 不同类型的内存位置
if ((loc1->isLocalArray && loc2->isLocalArray)) {
return compareLocalArrays(loc1, loc2);
}
if ((loc1->isFunctionParameter && loc2->isFunctionParameter)) {
return compareParameters(loc1, loc2);
}
if ((loc1->isGlobalArray || loc2->isGlobalArray)) {
return compareWithGlobal(loc1, loc2);
}
return compareMixedTypes(loc1, loc2);
}
AliasType SysYAliasAnalysisPass::compareIndices(MemoryLocation* loc1, MemoryLocation* loc2) {
// 比较相同基指针下的不同索引访问
// 如果都有常量索引,可以精确比较
if (loc1->hasConstantIndices && loc2->hasConstantIndices) {
// 比较索引数量
if (loc1->indices.size() != loc2->indices.size()) {
return AliasType::NO_ALIAS;
}
// 逐个比较索引值
for (size_t i = 0; i < loc1->indices.size(); ++i) {
Value* idx1 = loc1->indices[i];
Value* idx2 = loc2->indices[i];
// 都是常量,比较值
auto* const1 = dynamic_cast<ConstantInteger*>(idx1);
auto* const2 = dynamic_cast<ConstantInteger*>(idx2);
if (const1 && const2) {
int val1 = std::get<int>(const1->getVal());
int val2 = std::get<int>(const2->getVal());
if (val1 != val2) {
return AliasType::NO_ALIAS; // 不同常量索引,确定无别名
}
} else {
// 不是常量,无法确定
return AliasType::POSSIBLE_ALIAS;
}
}
// 所有索引都相同
return AliasType::SELF_ALIAS;
}
// 如果有非常量索引,保守估计
return AliasType::POSSIBLE_ALIAS;
}
AliasType SysYAliasAnalysisPass::compareLocalArrays(MemoryLocation* loc1, MemoryLocation* loc2) {
// 不同局部数组不别名
return AliasType::NO_ALIAS;
}
AliasType SysYAliasAnalysisPass::compareParameters(MemoryLocation* loc1, MemoryLocation* loc2) {
// SysY特化可配置的数组参数别名策略
//
// SysY中数组参数的语法形式
// void func(int a[], int b[]) - 一维数组参数
// void func(int a[][10], int b[]) - 多维数组参数
//
// 默认保守策略:不同数组参数可能别名(因为可能传入相同数组)
// func(arr, arr); // 传入同一个数组给两个参数
//
// 激进策略:假设不同数组参数不会传入相同数组(适用于评测环境)
// 在SysY评测中这种情况很少出现
if (useAggressiveParameterAnalysis()) {
// 激进策略:不同数组参数假设不别名
return AliasType::NO_ALIAS;
} else {
// 保守策略:不同数组参数可能别名
return AliasType::POSSIBLE_ALIAS;
}
}
AliasType SysYAliasAnalysisPass::compareWithGlobal(MemoryLocation* loc1, MemoryLocation* loc2) {
// 涉及全局数组的访问分析
// 这里处理所有涉及全局数组的情况
// SysY特化局部数组与全局数组不别名
if ((loc1->isLocalArray && loc2->isGlobalArray) ||
(loc1->isGlobalArray && loc2->isLocalArray)) {
// 局部数组在栈上,全局数组在全局区,确定不别名
return AliasType::NO_ALIAS;
}
// SysY特化数组参数与全局数组可能别名保守处理
if ((loc1->isFunctionParameter && loc2->isGlobalArray) ||
(loc1->isGlobalArray && loc2->isFunctionParameter)) {
// 数组参数可能指向全局数组,需要保守处理
return AliasType::POSSIBLE_ALIAS;
}
// 其他涉及全局数组的情况,采用保守策略
return AliasType::POSSIBLE_ALIAS;
}
AliasType SysYAliasAnalysisPass::compareMixedTypes(MemoryLocation* loc1, MemoryLocation* loc2) {
// 混合类型访问的别名分析
// 处理不同内存类型之间的别名关系
// SysY特化局部数组与数组参数通常不别名
// 典型场景:
// void func(int p[]) { // p 是数组参数
// int local[10]; // local 是局部数组
// p[0] = local[0]; // 混合类型访问
// }
// 或多维数组:
// void func(int p[][10]) { // p 是多维数组参数
// int local[10]; // local 是局部数组
// p[i][0] = local[0]; // 混合类型访问
// }
// 局部数组与数组参数在SysY中通常不别名
if ((loc1->isLocalArray && loc2->isFunctionParameter) ||
(loc1->isFunctionParameter && loc2->isLocalArray)) {
// 因为局部数组是栈上分配,而数组参数是传入的外部数组
return AliasType::NO_ALIAS;
}
// 对于其他混合情况,保守估计
return AliasType::UNKNOWN_ALIAS;
}
void SysYAliasAnalysisPass::applySysYConstraints(Function* F) {
// SysY语言特定的约束和优化
// 1. SysY没有指针运算简化了别名分析
// 2. 数组传参时保持数组语义
// 3. 没有动态内存分配,所有数组要么是局部的要么是参数/全局
}
void SysYAliasAnalysisPass::optimizeParameterAnalysis(Function* F) {
// 数组参数别名分析优化
// 为SysY评测环境提供可配置的优化策略
if (!enableParameterOptimization()) {
return; // 保持默认的保守策略
}
// 可选的参数优化:假设不同数组参数不会传入相同数组
// 典型的SysY函数调用
// int arr1[10], arr2[20];
// func(arr1, arr2); // 传入不同数组
// 而不是:
// func(arr1, arr1); // 传入相同数组给两个参数
// 这在SysY评测中通常是安全的假设
auto& locationMap = CurrentResult->LocationMap;
for (auto it1 = locationMap.begin(); it1 != locationMap.end(); ++it1) {
for (auto it2 = std::next(it1); it2 != locationMap.end(); ++it2) {
MemoryLocation* loc1 = it1->second.get();
MemoryLocation* loc2 = it2->second.get();
// 如果两个都是数组参数且基指针不同设为NO_ALIAS
if (loc1->isFunctionParameter && loc2->isFunctionParameter &&
loc1->basePointer != loc2->basePointer) {
CurrentResult->addAliasRelation(it1->first, it2->first, AliasType::NO_ALIAS);
}
}
}
}
void SysYAliasAnalysisPass::optimizeArrayAccessAnalysis(Function* F) {
// 数组访问别名分析优化
// 基于SysY语言的特点进行简单优化
// 优化1同一数组的不同常量索引访问确定无别名
optimizeConstantIndexAccesses();
// 优化2识别简单的顺序访问模式
optimizeSequentialAccesses();
}
bool SysYAliasAnalysisPass::isConstantValue(Value* val) {
return dynamic_cast<ConstantInteger*>(val) != nullptr; // 简化,只检查整数常量
}
bool SysYAliasAnalysisPass::hasLoopVariableInIndices(const std::vector<Value*>& indices, Function* F) {
// 保守策略:所有非常量索引都视为可能的循环变量
// 这样可以避免复杂的循环分析依赖,保持分析的独立性
for (Value* index : indices) {
if (!isConstantValue(index)) {
return true; // 保守估计,确保正确性
}
}
return false;
}
int SysYAliasAnalysisPass::calculateConstantOffset(const std::vector<Value*>& indices) {
int offset = 0;
for (Value* index : indices) {
if (auto* constInt = dynamic_cast<ConstantInteger*>(index)) {
// ConstantInteger的getVal()返回variant需要提取int值
auto val = constInt->getVal();
if (std::holds_alternative<int>(val)) {
offset += std::get<int>(val);
}
}
}
return offset;
}
void SysYAliasAnalysisPass::printStatistics() const {
if (CurrentResult) {
CurrentResult->print();
}
}
void SysYAliasAnalysisPass::optimizeConstantIndexAccesses() {
// 优化常量索引访问的别名关系
// 对于相同基指针的访问,如果索引都是常量且不同,则确定无别名
auto& locationMap = CurrentResult->LocationMap;
std::vector<Value*> allPointers;
for (auto& pair : locationMap) {
allPointers.push_back(pair.first);
}
for (size_t i = 0; i < allPointers.size(); ++i) {
for (size_t j = i + 1; j < allPointers.size(); ++j) {
Value* ptr1 = allPointers[i];
Value* ptr2 = allPointers[j];
MemoryLocation* loc1 = locationMap[ptr1].get();
MemoryLocation* loc2 = locationMap[ptr2].get();
// 相同基指针且都有常量索引
if (loc1->basePointer == loc2->basePointer &&
loc1->hasConstantIndices && loc2->hasConstantIndices) {
// 比较常量偏移
if (loc1->constantOffset != loc2->constantOffset) {
// 不同的常量偏移,确定无别名
CurrentResult->addAliasRelation(ptr1, ptr2, AliasType::NO_ALIAS);
}
}
}
}
}
void SysYAliasAnalysisPass::optimizeSequentialAccesses() {
// 识别和优化顺序访问模式
// 这是一个简化的实现,主要用于识别数组的顺序遍历
// 在SysY中大多数数组访问都是通过循环进行的
// 对于非常量索引的访问,我们采用保守策略,不进行过多优化
// 这样可以保持分析的简单性和正确性
// 未来如果需要更精确的分析,可以在这里添加更复杂的逻辑
}
} // namespace sysy

View File

@ -0,0 +1,417 @@
#include "CallGraphAnalysis.h"
#include "SysYIRPrinter.h"
#include <iostream>
#include <stack>
#include <unordered_set>
extern int DEBUG;
namespace sysy {
// 静态成员初始化
void* CallGraphAnalysisPass::ID = (void*)&CallGraphAnalysisPass::ID;
// ========== CallGraphAnalysisResult 实现 ==========
CallGraphAnalysisResult::Statistics CallGraphAnalysisResult::getStatistics() const {
Statistics stats = {};
stats.totalFunctions = nodes.size();
size_t totalCallEdges = 0;
size_t recursiveFunctions = 0;
size_t selfRecursiveFunctions = 0;
size_t totalCallers = 0;
size_t totalCallees = 0;
for (const auto& pair : nodes) {
const auto& node = pair.second;
totalCallEdges += node->callees.size();
totalCallers += node->callers.size();
totalCallees += node->callees.size();
if (node->isRecursive) recursiveFunctions++;
if (node->isSelfRecursive) selfRecursiveFunctions++;
}
stats.totalCallEdges = totalCallEdges;
stats.recursiveFunctions = recursiveFunctions;
stats.selfRecursiveFunctions = selfRecursiveFunctions;
stats.stronglyConnectedComponents = sccs.size();
// 计算最大SCC大小
size_t maxSCCSize = 0;
for (const auto& scc : sccs) {
maxSCCSize = std::max(maxSCCSize, scc.size());
}
stats.maxSCCSize = maxSCCSize;
// 计算平均值
if (stats.totalFunctions > 0) {
stats.avgCallersPerFunction = static_cast<double>(totalCallers) / stats.totalFunctions;
stats.avgCalleesPerFunction = static_cast<double>(totalCallees) / stats.totalFunctions;
}
return stats;
}
void CallGraphAnalysisResult::print() const {
std::cout << "---- Call Graph Analysis Results for Module ----\n";
// 打印基本统计信息
auto stats = getStatistics();
std::cout << " Statistics:\n";
std::cout << " Total Functions: " << stats.totalFunctions << "\n";
std::cout << " Total Call Edges: " << stats.totalCallEdges << "\n";
std::cout << " Recursive Functions: " << stats.recursiveFunctions << "\n";
std::cout << " Self-Recursive Functions: " << stats.selfRecursiveFunctions << "\n";
std::cout << " Strongly Connected Components: " << stats.stronglyConnectedComponents << "\n";
std::cout << " Max SCC Size: " << stats.maxSCCSize << "\n";
std::cout << " Avg Callers per Function: " << stats.avgCallersPerFunction << "\n";
std::cout << " Avg Callees per Function: " << stats.avgCalleesPerFunction << "\n";
// 打印拓扑排序结果
std::cout << " Topological Order (" << topologicalOrder.size() << "):\n";
for (size_t i = 0; i < topologicalOrder.size(); ++i) {
std::cout << " " << i << ": " << topologicalOrder[i]->getName() << "\n";
}
// 打印强连通分量
if (!sccs.empty()) {
std::cout << " Strongly Connected Components:\n";
for (size_t i = 0; i < sccs.size(); ++i) {
std::cout << " SCC " << i << " (size " << sccs[i].size() << "): ";
for (size_t j = 0; j < sccs[i].size(); ++j) {
if (j > 0) std::cout << ", ";
std::cout << sccs[i][j]->getName();
}
std::cout << "\n";
}
}
// 打印每个函数的详细信息
std::cout << " Function Details:\n";
for (const auto& pair : nodes) {
const auto& node = pair.second;
std::cout << " Function: " << node->function->getName();
if (node->isRecursive) {
std::cout << " (Recursive";
if (node->isSelfRecursive) std::cout << ", Self";
if (node->recursiveDepth >= 0) std::cout << ", Depth=" << node->recursiveDepth;
std::cout << ")";
}
std::cout << "\n";
if (!node->callers.empty()) {
std::cout << " Callers (" << node->callers.size() << "): ";
bool first = true;
for (Function* caller : node->callers) {
if (!first) std::cout << ", ";
std::cout << caller->getName();
first = false;
}
std::cout << "\n";
}
if (!node->callees.empty()) {
std::cout << " Callees (" << node->callees.size() << "): ";
bool first = true;
for (Function* callee : node->callees) {
if (!first) std::cout << ", ";
std::cout << callee->getName();
first = false;
}
std::cout << "\n";
}
}
std::cout << "--------------------------------------------------\n";
}
void CallGraphAnalysisResult::addNode(Function* F) {
if (nodes.find(F) == nodes.end()) {
nodes[F] = std::make_unique<CallGraphNode>(F);
}
}
void CallGraphAnalysisResult::addCallEdge(Function* caller, Function* callee) {
// 确保两个函数都有对应的节点
addNode(caller);
addNode(callee);
// 添加调用边
nodes[caller]->callees.insert(callee);
nodes[callee]->callers.insert(caller);
// 更新统计信息
nodes[caller]->totalCallees = nodes[caller]->callees.size();
nodes[callee]->totalCallers = nodes[callee]->callers.size();
// 检查自递归
if (caller == callee) {
nodes[caller]->isSelfRecursive = true;
nodes[caller]->isRecursive = true;
}
}
void CallGraphAnalysisResult::computeTopologicalOrder() {
topologicalOrder.clear();
std::unordered_set<Function*> visited;
// 对每个未访问的函数进行DFS
for (const auto& pair : nodes) {
Function* F = pair.first;
if (visited.find(F) == visited.end()) {
dfsTopological(F, visited, topologicalOrder);
}
}
// 反转结果(因为我们在后序遍历中添加)
std::reverse(topologicalOrder.begin(), topologicalOrder.end());
}
void CallGraphAnalysisResult::dfsTopological(Function* F, std::unordered_set<Function*>& visited,
std::vector<Function*>& result) {
visited.insert(F);
auto node = getNode(F);
if (node) {
// 先访问所有被调用的函数
for (Function* callee : node->callees) {
if (visited.find(callee) == visited.end()) {
dfsTopological(callee, visited, result);
}
}
}
// 后序遍历:访问完所有子节点后添加当前节点
result.push_back(F);
}
void CallGraphAnalysisResult::computeStronglyConnectedComponents() {
tarjanSCC();
// 为每个函数设置其所属的SCC
functionToSCC.clear();
for (size_t i = 0; i < sccs.size(); ++i) {
for (Function* F : sccs[i]) {
functionToSCC[F] = static_cast<int>(i);
}
}
}
void CallGraphAnalysisResult::tarjanSCC() {
sccs.clear();
std::vector<int> indices(nodes.size(), -1);
std::vector<int> lowlinks(nodes.size(), -1);
std::vector<Function*> stack;
std::unordered_set<Function*> onStack;
int index = 0;
// 为函数分配索引
std::map<Function*, int> functionIndex;
int idx = 0;
for (const auto& pair : nodes) {
functionIndex[pair.first] = idx++;
}
// 对每个未访问的函数运行Tarjan算法
for (const auto& pair : nodes) {
Function* F = pair.first;
int fIdx = functionIndex[F];
if (indices[fIdx] == -1) {
tarjanDFS(F, index, indices, lowlinks, stack, onStack);
}
}
}
void CallGraphAnalysisResult::tarjanDFS(Function* F, int& index, std::vector<int>& indices,
std::vector<int>& lowlinks, std::vector<Function*>& stack,
std::unordered_set<Function*>& onStack) {
// 这里需要函数到索引的映射,简化实现
// 在实际实现中应该维护一个全局的函数索引映射
static std::map<Function*, int> functionIndex;
static int nextIndex = 0;
if (functionIndex.find(F) == functionIndex.end()) {
functionIndex[F] = nextIndex++;
}
int fIdx = functionIndex[F];
// 确保向量足够大
if (fIdx >= static_cast<int>(indices.size())) {
indices.resize(fIdx + 1, -1);
lowlinks.resize(fIdx + 1, -1);
}
indices[fIdx] = index;
lowlinks[fIdx] = index;
index++;
stack.push_back(F);
onStack.insert(F);
auto node = getNode(F);
if (node) {
for (Function* callee : node->callees) {
int calleeIdx = functionIndex[callee];
// 确保向量足够大
if (calleeIdx >= static_cast<int>(indices.size())) {
indices.resize(calleeIdx + 1, -1);
lowlinks.resize(calleeIdx + 1, -1);
}
if (indices[calleeIdx] == -1) {
// 递归访问
tarjanDFS(callee, index, indices, lowlinks, stack, onStack);
lowlinks[fIdx] = std::min(lowlinks[fIdx], lowlinks[calleeIdx]);
} else if (onStack.find(callee) != onStack.end()) {
// 后向边
lowlinks[fIdx] = std::min(lowlinks[fIdx], indices[calleeIdx]);
}
}
}
// 如果F是SCC的根
if (lowlinks[fIdx] == indices[fIdx]) {
std::vector<Function*> scc;
Function* w;
do {
w = stack.back();
stack.pop_back();
onStack.erase(w);
scc.push_back(w);
} while (w != F);
sccs.push_back(std::move(scc));
}
}
void CallGraphAnalysisResult::analyzeRecursion() {
// 基于SCC分析递归
for (const auto& scc : sccs) {
if (scc.size() > 1) {
// 多函数的SCC标记为相互递归
for (Function* F : scc) {
auto* node = getMutableNode(F);
if (node) {
node->isRecursive = true;
node->recursiveDepth = -1; // 相互递归,深度未定义
}
}
} else if (scc.size() == 1) {
// 单函数SCC检查是否自递归
Function* F = scc[0];
auto* node = getMutableNode(F);
if (node && node->callees.count(F) > 0) {
node->isSelfRecursive = true;
node->isRecursive = true;
node->recursiveDepth = -1; // 简化:不计算递归深度
}
}
}
}
// ========== CallGraphAnalysisPass 实现 ==========
bool CallGraphAnalysisPass::runOnModule(Module* M, AnalysisManager& AM) {
if (DEBUG) {
std::cout << "Running Call Graph Analysis on module\n";
}
// 创建分析结果
CurrentResult = std::make_unique<CallGraphAnalysisResult>(M);
// 执行主要分析步骤
buildCallGraph(M);
CurrentResult->computeTopologicalOrder();
CurrentResult->computeStronglyConnectedComponents();
CurrentResult->analyzeRecursion();
if (DEBUG) {
CurrentResult->print();
}
return false; // 分析遍不修改IR
}
void CallGraphAnalysisPass::buildCallGraph(Module* M) {
// 1. 为所有函数创建节点(包括声明但未定义的函数)
for (auto& pair : M->getFunctions()) {
Function* F = pair.second.get();
if (!isLibraryFunction(F) && !isIntrinsicFunction(F)) {
CurrentResult->addNode(F);
}
}
// 2. 扫描所有函数的调用关系
for (auto& pair : M->getFunctions()) {
Function* F = pair.second.get();
if (!isLibraryFunction(F) && !isIntrinsicFunction(F)) {
scanFunctionCalls(F);
}
}
}
void CallGraphAnalysisPass::scanFunctionCalls(Function* F) {
// 遍历函数中的所有基本块和指令
for (auto& BB : F->getBasicBlocks_NoRange()) {
for (auto& I : BB->getInstructions()) {
if (CallInst* call = dynamic_cast<CallInst*>(I.get())) {
processCallInstruction(call, F);
}
}
}
}
void CallGraphAnalysisPass::processCallInstruction(CallInst* call, Function* caller) {
Function* callee = call->getCallee();
if (!callee) {
// 间接调用,无法静态确定目标函数
return;
}
if (isLibraryFunction(callee) || isIntrinsicFunction(callee)) {
// 跳过标准库函数和内置函数
return;
}
// 添加调用边
CurrentResult->addCallEdge(caller, callee);
// 更新调用点统计
auto* node = CurrentResult->getMutableNode(caller);
if (node) {
node->callSiteCount++;
}
}
bool CallGraphAnalysisPass::isLibraryFunction(Function* F) const {
std::string name = F->getName();
// SysY标准库函数
return name == "getint" || name == "getch" || name == "getfloat" ||
name == "getarray" || name == "getfarray" ||
name == "putint" || name == "putch" || name == "putfloat" ||
name == "putarray" || name == "putfarray" ||
name == "_sysy_starttime" || name == "_sysy_stoptime";
}
bool CallGraphAnalysisPass::isIntrinsicFunction(Function* F) const {
std::string name = F->getName();
// 编译器内置函数(后续可以增加某些内置函数)
return name.substr(0, 5) == "llvm." || name.substr(0, 5) == "sysy.";
}
void CallGraphAnalysisPass::printStatistics() const {
if (CurrentResult) {
CurrentResult->print();
}
}
} // namespace sysy

View File

@ -1,21 +1,30 @@
#include "Dom.h"
#include <algorithm> // for std::set_intersection, std::set_difference, std::set_union
#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 {
// 初始化 支配树静态 ID
// ==============================================================
// 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()) {
@ -48,7 +57,7 @@ const std::set<BasicBlock *> *DominatorTree::getDominatorTreeChildren(BasicBlock
return nullptr;
}
// 辅助函数:打印 BasicBlock 集合
// 辅助函数:打印 BasicBlock 集合 (保持不变)
void printBBSet(const std::string &prefix, const std::set<BasicBlock *> &s) {
if (!DEBUG)
return;
@ -63,24 +72,52 @@ void printBBSet(const std::string &prefix, const std::set<BasicBlock *> &s) {
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_in_order; // 用于确定遍历顺序,如果需要的话
std::vector<BasicBlock*> bbs_rpo = computeReversePostOrder(F);
// 初始化:入口块只被自己支配,其他块被所有块支配
for (const auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *bb = bb_ptr.get();
bbs_in_order.push_back(bb); // 收集所有块
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;
if (DEBUG) std::cout << "Init Dominators[" << bb->getName() << "]: {" << bb->getName() << "}" << std::endl;
} else {
for (const auto &all_bb_ptr : F->getBasicBlocks()) {
Dominators[bb].insert(all_bb_ptr.get());
Dominators[bb].clear();
for (BasicBlock *all_bb : bbs_rpo) {
Dominators[bb].insert(all_bb);
}
if (DEBUG) {
std::cout << "Init Dominators[" << bb->getName() << "]: ";
@ -94,35 +131,29 @@ void DominatorTree::computeDominators(Function *F) {
while (changed) {
changed = false;
iteration++;
if (DEBUG)
std::cout << "Iteration " << iteration << std::endl;
if (DEBUG) std::cout << "Iteration " << iteration << std::endl;
// 确保遍历顺序一致性例如可以按照DFS或BFS顺序或者简单的迭代器顺序
// 如果Function::getBasicBlocks()返回的迭代器顺序稳定则无需bbs_in_order
for (const auto &bb_ptr : F->getBasicBlocks()) { // 假设这个迭代器顺序稳定
BasicBlock *bb = bb_ptr.get();
if (bb == entryBlock)
continue;
for (BasicBlock *bb : bbs_rpo) {
if (bb == entryBlock) continue;
// 计算所有前驱的支配者集合的交集
std::set<BasicBlock *> newDom;
bool firstPredProcessed = false;
for (BasicBlock *pred : bb->getPredecessors()) {
// 确保前驱的支配者集合已经计算过
if (Dominators.count(pred)) {
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;
}
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); // BB 永远支配自己
newDom.insert(bb);
if (newDom != Dominators[bb]) {
if (DEBUG) {
@ -140,78 +171,242 @@ void DominatorTree::computeDominators(Function *F) {
std::cout << "--- Dominators Computation Finished ---" << std::endl;
}
void DominatorTree::computeIDoms(Function *F) {
if (DEBUG)
std::cout << "--- Computing Immediate Dominators (IDoms) ---" << std::endl;
// ==============================================================
// 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) {
if (DEBUG)
std::cerr << "Warning: Dominators for " << bb->getName() << " not found!" << std::endl;
continue;
// 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++;
// 遍历bb的所有严格支配者 D (即 bb 的支配者中除了 bb 自身)
for (BasicBlock *D_candidate : *domsOfBB) {
if (D_candidate == bb)
continue; // 跳过bb自身
bool D_candidate_is_IDom = true;
// 检查是否存在另一个块 X使得 D_candidate 严格支配 X 且 X 严格支配 bb
// 或者更直接的,检查 D_candidate 是否被 bb 的所有其他严格支配者所支配
for (BasicBlock *X_other_dom : *domsOfBB) {
if (X_other_dom == bb || X_other_dom == D_candidate)
continue; // 跳过bb自身和D_candidate
// 如果 X_other_dom 严格支配 bb (它在 domsOfBB 中且不是bb自身)
// 并且 X_other_dom 不被 D_candidate 支配,那么 D_candidate 就不是 IDom
const std::set<BasicBlock *> *domsOfX_other_dom = getDominators(X_other_dom);
if (domsOfX_other_dom && domsOfX_other_dom->count(D_candidate)) { // X_other_dom 支配 D_candidate
// D_candidate 被另一个支配者 X_other_dom 支配
// 这说明 D_candidate 位于 X_other_dom 的“下方”X_other_dom 更接近 bb
// 因此 D_candidate 不是 IDom
D_candidate_is_IDom = false;
break;
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);
}
}
if (D_candidate_is_IDom) {
currentIDom = D_candidate;
break; // 找到即时支配者,可以退出循环,因为它是唯一的
}
}
IDoms[bb] = currentIDom;
if (DEBUG) {
std::cout << " IDom[" << bb->getName() << "] = " << (currentIDom ? currentIDom->getName() : "nullptr")
<< std::endl;
}
}
if (DEBUG)
std::cout << "--- Immediate Dominators Computation Finished ---" << std::endl;
}
/*
for each node n in a postorder traversal of the dominator tree:
df[n] = empty set
// compute DF_local(n)
for each child y of n in the CFG:
if idom[y] != n:
df[n] = df[n] U {y}
// compute DF_up(n)
for each child c of n in the dominator tree:
for each element w in df[c]:
if idom[w] != n:
df[n] = df[n] U {w}
*/
// 并查集:找到集合的代表,并进行路径压缩
// 同时更新 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)
@ -221,21 +416,17 @@ void DominatorTree::computeDominanceFrontiers(Function *F) {
BasicBlock *X = bb_ptr_X.get();
DominanceFrontiers[X].clear();
// 遍历所有可能的 Z (X支配Z或者Z就是X)
for (const auto &bb_ptr_Z : F->getBasicBlocks()) {
BasicBlock *Z = bb_ptr_Z.get();
const std::set<BasicBlock *> *domsOfZ = getDominators(Z);
// 如果 X 不支配 Z则 Z 与 DF(X) 无关
if (!domsOfZ || domsOfZ->find(X) == domsOfZ->end()) {
if (!domsOfZ || domsOfZ->find(X) == domsOfZ->end()) { // Z 不被 X 支配
continue;
}
// 遍历 Z 的所有后继 Y
for (BasicBlock *Y : Z->getSuccessors()) {
// 如果 Y 不被 X 严格支配,则 Y 在 DF(X) 中
// Y 不被 X 严格支配意味着 (Y不被X支配) 或 (Y就是X)
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);
}
@ -274,23 +465,21 @@ void DominatorTree::computeDominatorTreeChildren(Function *F) {
}
// ==============================================================
// DominatorTreeAnalysisPass 的实现
// DominatorTreeAnalysisPass 的实现 (保持不变)
// ==============================================================
bool DominatorTreeAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
// 每次运行时清空旧数据,确保重新计算
CurrentDominatorTree = std::make_unique<DominatorTree>(F);
// 不需要手动清空mapunique_ptr会创建新的DominatorTree对象其map是空的
CurrentDominatorTree->computeDominators(F);
CurrentDominatorTree->computeIDoms(F); // 修正后的IDoms算法
CurrentDominatorTree->computeIDoms(F); // 修正后的LT算法
CurrentDominatorTree->computeDominanceFrontiers(F);
CurrentDominatorTree->computeDominatorTreeChildren(F);
return false; // 分析遍通常返回 false表示不修改 IR
return false;
}
std::unique_ptr<AnalysisResultBase> DominatorTreeAnalysisPass::getResult() {
// 返回计算好的 DominatorTree 实例,所有权转移给 AnalysisManager
return std::move(CurrentDominatorTree);
}

View File

@ -0,0 +1,415 @@
#include "Dom.h" // 确保包含 DominatorTreeAnalysisPass 的定义
#include "Loop.h" //
#include "AliasAnalysis.h" // 添加别名分析依赖
#include "SideEffectAnalysis.h" // 添加副作用分析依赖
#include <iostream>
#include <queue> // 用于 BFS 遍历设置循环层级
// 调试模式开关
#ifndef DEBUG
#define DEBUG 0
#endif
namespace sysy {
// 定义 Pass 的唯一 ID
void *LoopAnalysisPass::ID = (void *)&LoopAnalysisPass::ID;
// 定义 Loop 类的静态变量
int Loop::NextLoopID = 0;
// **实现 LoopAnalysisResult::print() 方法**
void LoopAnalysisResult::printBBSet(const std::string &prefix, const std::set<BasicBlock *> &s) const{
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 << "}";
}
// **辅助函数:打印 Loop 指针向量**
void LoopAnalysisResult::printLoopVector(const std::string &prefix, const std::vector<Loop *> &loops) const {
if (!DEBUG) return;
std::cout << prefix << "[";
bool first = true;
for (const auto &loop : loops) {
if (!first) std::cout << ", ";
std::cout << loop->getName(); // 假设 Loop::getName() 存在
first = false;
}
std::cout << "]";
}
void LoopAnalysisResult::print() const {
if (!DEBUG) return; // 只有在 DEBUG 模式下才打印
std::cout << "\n--- Loop Analysis Results for Function: " << AssociatedFunction->getName() << " ---" << std::endl;
if (AllLoops.empty()) {
std::cout << " No loops found." << std::endl;
return;
}
std::cout << "Total Loops Found: " << AllLoops.size() << std::endl;
// 1. 按层级分组循环
std::map<int, std::vector<Loop*>> loopsByLevel;
int maxLevel = 0;
for (const auto& loop_ptr : AllLoops) {
if (loop_ptr->getLoopLevel() != -1) { // 确保层级已计算
loopsByLevel[loop_ptr->getLoopLevel()].push_back(loop_ptr.get());
if (loop_ptr->getLoopLevel() > maxLevel) {
maxLevel = loop_ptr->getLoopLevel();
}
}
}
// 2. 打印循环层次结构
std::cout << "\n--- Loop Hierarchy ---" << std::endl;
for (int level = 0; level <= maxLevel; ++level) {
if (loopsByLevel.count(level)) {
std::cout << "Level " << level << " Loops:" << std::endl;
for (Loop* loop : loopsByLevel[level]) {
std::string indent(level * 2, ' '); // 根据层级缩进
std::cout << indent << "- Loop Header: " << loop->getName() << std::endl;
std::cout << indent << " Blocks: ";
printBBSet("", loop->getBlocks());
std::cout << std::endl;
std::cout << indent << " Exit Blocks: ";
printBBSet("", loop->getExitBlocks());
std::cout << std::endl;
std::cout << indent << " Pre-Header: " << (loop->getPreHeader() ? loop->getPreHeader()->getName() : "None") << std::endl;
std::cout << indent << " Parent Loop: " << (loop->getParentLoop() ? loop->getParentLoop()->getName() : "None (Outermost)") << std::endl;
std::cout << indent << " Nested Loops: ";
printLoopVector("", loop->getNestedLoops());
std::cout << std::endl;
}
}
}
// 3. 打印最外层/最内层循环摘要
std::cout << "\n--- Loop Summary ---" << std::endl;
std::cout << "Outermost Loops: ";
printLoopVector("", getOutermostLoops());
std::cout << std::endl;
std::cout << "Innermost Loops: ";
printLoopVector("", getInnermostLoops());
std::cout << std::endl;
std::cout << "-----------------------------------------------" << std::endl;
}
bool LoopAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
if (F->getBasicBlocks().empty()) {
CurrentResult = std::make_unique<LoopAnalysisResult>(F);
return false; // 空函数,没有循环
}
if (DEBUG)
std::cout << "Running LoopAnalysisPass on function: " << F->getName() << std::endl;
// 获取支配树分析结果
// 这是循环分析的关键依赖
DominatorTree *DT = AM.getAnalysisResult<DominatorTree, DominatorTreeAnalysisPass>(F);
if (!DT) {
// 无法获取支配树,无法进行循环分析
std::cerr << "Error: DominatorTreeAnalysisResult not available for function " << F->getName() << std::endl;
CurrentResult = std::make_unique<LoopAnalysisResult>(F);
return false;
}
// 获取别名分析结果 - 用于循环内存访问分析
AliasAnalysisResult *aliasAnalysis = AM.getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(F);
if (DEBUG && aliasAnalysis) {
std::cout << "Loop Analysis: Using alias analysis results for enhanced memory pattern detection" << std::endl;
}
// 获取副作用分析结果 - 用于循环纯度分析
SideEffectAnalysisResult *sideEffectAnalysis = AM.getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>();
if (DEBUG && sideEffectAnalysis) {
std::cout << "Loop Analysis: Using side effect analysis results for loop purity detection" << std::endl;
}
CurrentResult = std::make_unique<LoopAnalysisResult>(F);
bool changed = false; // 循环分析本身不修改IR所以通常返回false
// 步骤 1: 识别回边和对应的自然循环
// 回边 (N -> D) 定义D 支配 N
std::vector<std::pair<BasicBlock *, BasicBlock *>> backEdges;
for (auto &BB : F->getBasicBlocks()) {
auto Block = BB.get();
for (BasicBlock *Succ : Block->getSuccessors()) {
if (DT->getDominators(Block) && DT->getDominators(Block)->count(Succ)) {
// Succ 支配 Block所以 (Block -> Succ) 是一条回边
backEdges.push_back({Block, Succ});
if (DEBUG)
std::cout << "Found back edge: " << Block->getName() << " -> " << Succ->getName() << std::endl;
}
}
}
if (DEBUG)
std::cout << "Total back edges found: " << backEdges.size() << std::endl;
// 步骤 2: 为每条回边构建自然循环
std::map<BasicBlock*, std::unique_ptr<Loop>> loopMap; // 按循环头分组
for (auto &edge : backEdges) {
BasicBlock *N = edge.first; // 回边的尾部
BasicBlock *D = edge.second; // 回边的头部 (循环头)
// 检查是否已经为此循环头创建了循环
if (loopMap.find(D) == loopMap.end()) {
// 创建新的 Loop 对象
loopMap[D] = std::make_unique<Loop>(D);
}
Loop* currentLoop = loopMap[D].get();
// 收集此回边对应的循环体块:从 N 逆向遍历到 D
std::set<BasicBlock *> loopBlocks; // 临时存储循环块
std::queue<BasicBlock *> q;
// 循环头总是循环体的一部分
loopBlocks.insert(D);
// 如果回边的尾部不是循环头本身,则将其加入队列进行遍历
if (N != D) {
q.push(N);
loopBlocks.insert(N);
}
while (!q.empty()) {
BasicBlock *current = q.front();
q.pop();
for (BasicBlock *pred : current->getPredecessors()) {
// 如果前驱还没有被访问过,则将其加入循环体并继续遍历
if (loopBlocks.find(pred) == loopBlocks.end()) {
loopBlocks.insert(pred);
q.push(pred);
}
}
}
// 将收集到的块添加到 Loop 对象中(合并所有回边的结果)
for (BasicBlock *loopBB : loopBlocks) {
currentLoop->addBlock(loopBB);
}
}
// 处理每个合并后的循环
for (auto &[header, currentLoop] : loopMap) {
const auto &loopBlocks = currentLoop->getBlocks();
// 步骤 3: 识别循环出口块 (Exit Blocks)
for (BasicBlock *loopBB : loopBlocks) {
for (BasicBlock *succ : loopBB->getSuccessors()) {
if (loopBlocks.find(succ) == loopBlocks.end()) {
// 如果后继不在循环体内,则 loopBB 是一个出口块
currentLoop->addExitBlock(loopBB);
}
}
}
// 步骤 4: 识别循环前置块 (Pre-Header)
BasicBlock *candidatePreHeader = nullptr;
int externalPredecessorCount = 0;
for (BasicBlock *predOfHeader : header->getPredecessors()) {
// 使用 currentLoop->contains() 来检查前驱是否在循环体内
if (!currentLoop->contains(predOfHeader)) {
// 如果前驱不在循环体内,则是一个外部前驱
externalPredecessorCount++;
candidatePreHeader = predOfHeader;
}
}
if (externalPredecessorCount == 1) {
currentLoop->setPreHeader(candidatePreHeader);
}
CurrentResult->addLoop(std::move(currentLoop));
}
// 步骤 5: 处理嵌套循环 (确定父子关系和层级)
const auto &allLoops = CurrentResult->getAllLoops();
// 1. 首先,清除所有循环已设置的父子关系和嵌套子循环列表,确保重新计算
for (const auto &loop_ptr : allLoops) {
loop_ptr->setParentLoop(nullptr); // 清除父指针
loop_ptr->clearNestedLoops(); // 清除子循环列表
loop_ptr->setLoopLevel(-1); // 重置循环层级
}
// 2. 遍历所有循环,为每个循环找到其直接父循环并建立关系
for (const auto &innerLoop_ptr : allLoops) {
Loop *innerLoop = innerLoop_ptr.get();
Loop *immediateParent = nullptr; // 用于存储当前 innerLoop 的最近父循环
for (const auto &outerLoop_ptr : allLoops) {
Loop *outerLoop = outerLoop_ptr.get();
// 一个循环不能是它自己的父循环
if (outerLoop == innerLoop) {
continue;
}
// 检查 outerLoop 是否包含 innerLoop 的所有条件:
// Condition 1: outerLoop 的头支配 innerLoop 的头
if (!(DT->getDominators(innerLoop->getHeader()) &&
DT->getDominators(innerLoop->getHeader())->count(outerLoop->getHeader()))) {
continue; // outerLoop 不支配 innerLoop 的头,因此不是一个外层循环
}
// Condition 2: innerLoop 的所有基本块都在 outerLoop 的基本块集合中
bool allInnerBlocksInOuter = true;
for (BasicBlock *innerBB : innerLoop->getBlocks()) {
if (!outerLoop->contains(innerBB)) { //
allInnerBlocksInOuter = false;
break;
}
}
if (!allInnerBlocksInOuter) {
continue; // outerLoop 不包含 innerLoop 的所有块
}
// 到此为止outerLoop 已经被确认为 innerLoop 的一个“候选父循环”(即它包含了 innerLoop
if (immediateParent == nullptr) {
// 这是找到的第一个候选父循环
immediateParent = outerLoop;
} else {
// 已经有了一个 immediateParent需要判断哪个是更“紧密”的父循环
// 更紧密的父循环是那个包含另一个候选父循环的。
// 如果当前的 immediateParent 包含了 outerLoop 的头,那么 outerLoop 是更深的循环(更接近 innerLoop
if (immediateParent->contains(outerLoop->getHeader())) { //
immediateParent = outerLoop; // outerLoop 是更紧密的父循环
}
// 否则outerLoop 包含了 immediateParent 的头),说明 immediateParent 更紧密,保持不变
// 或者它们互不包含(不应该发生,因为它们都包含了 innerLoop也保持 immediateParent
}
}
// 设置 innerLoop 的直接父循环,并添加到父循环的嵌套列表中
if (immediateParent) {
innerLoop->setParentLoop(immediateParent);
immediateParent->addNestedLoop(innerLoop);
}
}
// 3. 计算循环层级 (Level)
std::queue<Loop *> q_level;
// 查找所有最外层循环没有父循环的设置其层级为0并加入队列
for (const auto &loop_ptr : allLoops) {
if (loop_ptr->isOutermost()) {
loop_ptr->setLoopLevel(0);
q_level.push(loop_ptr.get());
}
}
// 使用 BFS 遍历循环树,计算所有嵌套循环的层级
while (!q_level.empty()) {
Loop *current = q_level.front();
q_level.pop();
for (Loop *nestedLoop : current->getNestedLoops()) {
nestedLoop->setLoopLevel(current->getLoopLevel() + 1);
q_level.push(nestedLoop);
}
}
if (DEBUG) {
std::cout << "Loop Analysis completed for function: " << F->getName() << std::endl;
std::cout << "Total loops found: " << CurrentResult->getLoopCount() << std::endl;
std::cout << "Max loop depth: " << CurrentResult->getMaxLoopDepth() << std::endl;
std::cout << "Innermost loops: " << CurrentResult->getInnermostLoops().size() << std::endl;
std::cout << "Outermost loops: " << CurrentResult->getOutermostLoops().size() << std::endl;
// 打印各深度的循环分布
for (int depth = 1; depth <= CurrentResult->getMaxLoopDepth(); ++depth) {
int count = CurrentResult->getLoopCountAtDepth(depth);
if (count > 0) {
std::cout << "Loops at depth " << depth << ": " << count << std::endl;
}
}
// 输出缓存统计
auto cacheStats = CurrentResult->getCacheStats();
std::cout << "Cache statistics - Total cached queries: " << cacheStats.totalCachedQueries << std::endl;
}
return changed;
}
// ========== Loop 类的新增方法实现 ==========
bool Loop::mayHaveSideEffects(SideEffectAnalysisResult* sideEffectAnalysis) const {
if (!sideEffectAnalysis) return true; // 保守假设
for (BasicBlock* bb : LoopBlocks) {
for (auto& inst : bb->getInstructions()) {
if (sideEffectAnalysis->hasSideEffect(inst.get())) {
return true;
}
}
}
return false;
}
bool Loop::accessesGlobalMemory(AliasAnalysisResult* aliasAnalysis) const {
if (!aliasAnalysis) return true; // 保守假设
for (BasicBlock* bb : LoopBlocks) {
for (auto& inst : bb->getInstructions()) {
if (auto* loadInst = dynamic_cast<LoadInst*>(inst.get())) {
if (!aliasAnalysis->isLocalArray(loadInst->getPointer())) {
return true;
}
} else if (auto* storeInst = dynamic_cast<StoreInst*>(inst.get())) {
if (!aliasAnalysis->isLocalArray(storeInst->getPointer())) {
return true;
}
}
}
}
return false;
}
bool Loop::hasMemoryAliasConflicts(AliasAnalysisResult* aliasAnalysis) const {
if (!aliasAnalysis) return true; // 保守假设
std::vector<Value*> memoryAccesses;
// 收集所有内存访问
for (BasicBlock* bb : LoopBlocks) {
for (auto& inst : bb->getInstructions()) {
if (auto* loadInst = dynamic_cast<LoadInst*>(inst.get())) {
memoryAccesses.push_back(loadInst->getPointer());
} else if (auto* storeInst = dynamic_cast<StoreInst*>(inst.get())) {
memoryAccesses.push_back(storeInst->getPointer());
}
}
}
// 检查两两之间是否有别名
for (size_t i = 0; i < memoryAccesses.size(); ++i) {
for (size_t j = i + 1; j < memoryAccesses.size(); ++j) {
auto aliasType = aliasAnalysis->queryAlias(memoryAccesses[i], memoryAccesses[j]);
if (aliasType == AliasType::SELF_ALIAS || aliasType == AliasType::POSSIBLE_ALIAS) {
return true;
}
}
}
return false;
}
} // namespace sysy

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,803 @@
#include "LoopVectorization.h"
#include "Dom.h"
#include "Loop.h"
#include "Liveness.h"
#include "AliasAnalysis.h"
#include "SideEffectAnalysis.h"
#include <iostream>
#include <algorithm>
#include <cmath>
#include <set>
extern int DEBUG;
namespace sysy {
// 定义 Pass 的唯一 ID
void *LoopVectorizationPass::ID = (void *)&LoopVectorizationPass::ID;
std::vector<int> DependenceVector::getDirectionVector() const {
std::vector<int> direction;
direction.reserve(distances.size());
for (int dist : distances) {
if (dist > 0) direction.push_back(1); // 前向依赖
else if (dist < 0) direction.push_back(-1); // 后向依赖
else direction.push_back(0); // 无依赖
}
return direction;
}
bool DependenceVector::isVectorizationSafe() const {
if (!isKnown) return false; // 未知依赖,不安全
// 对于向量化,我们主要关心最内层循环的依赖
if (distances.empty()) return true;
int innermostDistance = distances.back(); // 最内层循环的距离
// 前向依赖 (距离 > 0) 通常是安全的,可以通过调整向量化顺序处理
// 后向依赖 (距离 < 0) 通常不安全,会阻止向量化
// 距离 = 0 表示同一迭代内的依赖,通常安全
return innermostDistance >= 0;
}
size_t LoopVectorizationResult::getVectorizableLoopCount() const {
size_t count = 0;
for (const auto& [loop, analysis] : VectorizationMap) {
if (analysis.isVectorizable) count++;
}
return count;
}
size_t LoopVectorizationResult::getParallelizableLoopCount() const {
size_t count = 0;
for (const auto& [loop, analysis] : ParallelizationMap) {
if (analysis.isParallelizable) count++;
}
return count;
}
std::vector<Loop*> LoopVectorizationResult::getVectorizationCandidates() const {
std::vector<Loop*> candidates;
for (const auto& [loop, analysis] : VectorizationMap) {
if (analysis.isVectorizable) {
candidates.push_back(loop);
}
}
// 按建议的向量宽度排序,优先处理收益更大的循环
std::sort(candidates.begin(), candidates.end(),
[this](Loop* a, Loop* b) {
const auto& analysisA = VectorizationMap.at(a);
const auto& analysisB = VectorizationMap.at(b);
return analysisA.suggestedVectorWidth > analysisB.suggestedVectorWidth;
});
return candidates;
}
std::vector<Loop*> LoopVectorizationResult::getParallelizationCandidates() const {
std::vector<Loop*> candidates;
for (const auto& [loop, analysis] : ParallelizationMap) {
if (analysis.isParallelizable) {
candidates.push_back(loop);
}
}
// 按建议的线程数排序
std::sort(candidates.begin(), candidates.end(),
[this](Loop* a, Loop* b) {
const auto& analysisA = ParallelizationMap.at(a);
const auto& analysisB = ParallelizationMap.at(b);
return analysisA.suggestedThreadCount > analysisB.suggestedThreadCount;
});
return candidates;
}
void LoopVectorizationResult::print() const {
if (!DEBUG) return;
std::cout << "\n--- Loop Vectorization/Parallelization Analysis Results for Function: "
<< AssociatedFunction->getName() << " ---" << std::endl;
if (VectorizationMap.empty() && ParallelizationMap.empty()) {
std::cout << " No vectorization/parallelization analysis results." << std::endl;
return;
}
// 统计信息
std::cout << "\n=== Summary ===" << std::endl;
std::cout << "Total Loops Analyzed: " << VectorizationMap.size() << std::endl;
std::cout << "Vectorizable Loops: " << getVectorizableLoopCount() << std::endl;
std::cout << "Parallelizable Loops: " << getParallelizableLoopCount() << std::endl;
// 详细分析结果
for (const auto& [loop, vecAnalysis] : VectorizationMap) {
std::cout << "\n--- Loop: " << loop->getName() << " ---" << std::endl;
// 向量化分析 (暂时搁置)
std::cout << " Vectorization: " << (vecAnalysis.isVectorizable ? "YES" : "NO") << std::endl;
if (!vecAnalysis.preventingFactors.empty()) {
std::cout << " Preventing Factors: ";
for (const auto& factor : vecAnalysis.preventingFactors) {
std::cout << factor << " ";
}
std::cout << std::endl;
}
// 并行化分析
auto parallelIt = ParallelizationMap.find(loop);
if (parallelIt != ParallelizationMap.end()) {
const auto& parAnalysis = parallelIt->second;
std::cout << " Parallelization: " << (parAnalysis.isParallelizable ? "YES" : "NO") << std::endl;
if (parAnalysis.isParallelizable) {
std::cout << " Suggested Thread Count: " << parAnalysis.suggestedThreadCount << std::endl;
if (parAnalysis.requiresReduction) {
std::cout << " Requires Reduction: Yes" << std::endl;
}
if (parAnalysis.requiresBarrier) {
std::cout << " Requires Barrier: Yes" << std::endl;
}
} else if (!parAnalysis.preventingFactors.empty()) {
std::cout << " Preventing Factors: ";
for (const auto& factor : parAnalysis.preventingFactors) {
std::cout << factor << " ";
}
std::cout << std::endl;
}
}
// 依赖关系
auto depIt = DependenceMap.find(loop);
if (depIt != DependenceMap.end()) {
const auto& dependences = depIt->second;
std::cout << " Dependences: " << dependences.size() << " found" << std::endl;
for (const auto& dep : dependences) {
if (dep.dependenceVector.isKnown) {
std::cout << " " << dep.source->getName() << " -> " << dep.sink->getName();
std::cout << " [";
for (size_t i = 0; i < dep.dependenceVector.distances.size(); ++i) {
if (i > 0) std::cout << ",";
std::cout << dep.dependenceVector.distances[i];
}
std::cout << "]" << std::endl;
}
}
}
}
std::cout << "-----------------------------------------------" << std::endl;
}
bool LoopVectorizationPass::runOnFunction(Function *F, AnalysisManager &AM) {
if (F->getBasicBlocks().empty()) {
CurrentResult = std::make_unique<LoopVectorizationResult>(F);
return false;
}
if (DEBUG) {
std::cout << "Running LoopVectorizationPass on function: " << F->getName() << std::endl;
}
// 获取循环分析结果
auto* loopAnalysisResult = AM.getAnalysisResult<LoopAnalysisResult, LoopAnalysisPass>(F);
if (!loopAnalysisResult || !loopAnalysisResult->hasLoops()) {
CurrentResult = std::make_unique<LoopVectorizationResult>(F);
return false;
}
// 获取循环特征分析结果
auto* loopCharacteristics = AM.getAnalysisResult<LoopCharacteristicsResult, LoopCharacteristicsPass>(F);
if (!loopCharacteristics) {
if (DEBUG) {
std::cout << "Warning: LoopCharacteristics analysis not available" << std::endl;
}
}
// 获取别名分析结果
auto* aliasAnalysis = AM.getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(F);
// 获取副作用分析结果
auto* sideEffectAnalysis = AM.getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>();
CurrentResult = std::make_unique<LoopVectorizationResult>(F);
// 分析每个循环的向量化/并行化可行性
for (const auto& loop_ptr : loopAnalysisResult->getAllLoops()) {
Loop* loop = loop_ptr.get();
// 获取该循环的特征信息
LoopCharacteristics* characteristics = nullptr;
if (loopCharacteristics) {
characteristics = const_cast<LoopCharacteristics*>(loopCharacteristics->getCharacteristics(loop));
}
analyzeLoop(loop, characteristics, aliasAnalysis, sideEffectAnalysis);
}
if (DEBUG) {
std::cout << "LoopVectorizationPass completed. Found "
<< CurrentResult->getVectorizableLoopCount() << " vectorizable loops, "
<< CurrentResult->getParallelizableLoopCount() << " parallelizable loops" << std::endl;
}
return false; // 分析遍不修改IR
}
void LoopVectorizationPass::analyzeLoop(Loop* loop, LoopCharacteristics* characteristics,
AliasAnalysisResult* aliasAnalysis, SideEffectAnalysisResult* sideEffectAnalysis) {
if (DEBUG) {
std::cout << " Analyzing advanced features for loop: " << loop->getName() << std::endl;
}
// 1. 计算精确依赖向量
auto dependences = computeDependenceVectors(loop, aliasAnalysis);
CurrentResult->addDependenceAnalysis(loop, dependences);
// 2. 分析向量化可行性 (暂时搁置,总是返回不可向量化)
auto vecAnalysis = analyzeVectorizability(loop, dependences, characteristics);
CurrentResult->addVectorizationAnalysis(loop, vecAnalysis);
// 3. 分析并行化可行性
auto parAnalysis = analyzeParallelizability(loop, dependences, characteristics);
CurrentResult->addParallelizationAnalysis(loop, parAnalysis);
}
// ========== 依赖向量分析实现 ==========
std::vector<PreciseDependence> LoopVectorizationPass::computeDependenceVectors(Loop* loop,
AliasAnalysisResult* aliasAnalysis) {
std::vector<PreciseDependence> dependences;
std::vector<Instruction*> memoryInsts;
// 收集所有内存操作指令
for (BasicBlock* bb : loop->getBlocks()) {
for (auto& inst : bb->getInstructions()) {
if (dynamic_cast<LoadInst*>(inst.get()) || dynamic_cast<StoreInst*>(inst.get())) {
memoryInsts.push_back(inst.get());
}
}
}
// 分析每对内存操作之间的依赖关系
for (size_t i = 0; i < memoryInsts.size(); ++i) {
for (size_t j = i + 1; j < memoryInsts.size(); ++j) {
Instruction* inst1 = memoryInsts[i];
Instruction* inst2 = memoryInsts[j];
Value* ptr1 = nullptr;
Value* ptr2 = nullptr;
if (auto* load = dynamic_cast<LoadInst*>(inst1)) {
ptr1 = load->getPointer();
} else if (auto* store = dynamic_cast<StoreInst*>(inst1)) {
ptr1 = store->getPointer();
}
if (auto* load = dynamic_cast<LoadInst*>(inst2)) {
ptr2 = load->getPointer();
} else if (auto* store = dynamic_cast<StoreInst*>(inst2)) {
ptr2 = store->getPointer();
}
if (!ptr1 || !ptr2) continue;
// 检查是否可能存在别名关系
bool mayAlias = false;
if (aliasAnalysis) {
mayAlias = aliasAnalysis->queryAlias(ptr1, ptr2) != AliasType::NO_ALIAS;
} else {
mayAlias = (ptr1 != ptr2); // 保守估计
}
if (mayAlias) {
// 创建依赖关系
PreciseDependence dep(loop->getLoopDepth());
dep.source = inst1;
dep.sink = inst2;
dep.memoryLocation = ptr1;
// 确定依赖类型
bool isStore1 = dynamic_cast<StoreInst*>(inst1) != nullptr;
bool isStore2 = dynamic_cast<StoreInst*>(inst2) != nullptr;
if (isStore1 && !isStore2) {
dep.type = DependenceType::TRUE_DEPENDENCE; // Write -> Read (RAW)
} else if (!isStore1 && isStore2) {
dep.type = DependenceType::ANTI_DEPENDENCE; // Read -> Write (WAR)
} else if (isStore1 && isStore2) {
dep.type = DependenceType::OUTPUT_DEPENDENCE; // Write -> Write (WAW)
} else {
continue; // Read -> Read (RAR) - 跳过,不是真正的依赖
}
// 计算依赖向量
dep.dependenceVector = computeAccessDependence(inst1, inst2, loop);
// 判断是否允许并行化
dep.allowsParallelization = dep.dependenceVector.isLoopIndependent() ||
(dep.dependenceVector.isKnown &&
std::all_of(dep.dependenceVector.distances.begin(),
dep.dependenceVector.distances.end(),
[](int d) { return d >= 0; }));
dependences.push_back(dep);
if (DEBUG && dep.dependenceVector.isKnown) {
std::cout << " Found dependence: " << inst1->getName()
<< " -> " << inst2->getName() << " [";
for (size_t k = 0; k < dep.dependenceVector.distances.size(); ++k) {
if (k > 0) std::cout << ",";
std::cout << dep.dependenceVector.distances[k];
}
std::cout << "]" << std::endl;
}
}
}
}
return dependences;
}
DependenceVector LoopVectorizationPass::computeAccessDependence(Instruction* inst1, Instruction* inst2, Loop* loop) {
DependenceVector depVec(loop->getLoopDepth());
Value* ptr1 = nullptr;
Value* ptr2 = nullptr;
if (auto* load = dynamic_cast<LoadInst*>(inst1)) {
ptr1 = load->getPointer();
} else if (auto* store = dynamic_cast<StoreInst*>(inst1)) {
ptr1 = store->getPointer();
}
if (auto* load = dynamic_cast<LoadInst*>(inst2)) {
ptr2 = load->getPointer();
} else if (auto* store = dynamic_cast<StoreInst*>(inst2)) {
ptr2 = store->getPointer();
}
if (!ptr1 || !ptr2) return depVec;
// 尝试分析仿射关系
if (areAccessesAffinelyRelated(ptr1, ptr2, loop)) {
auto coeff1 = extractInductionCoefficients(ptr1, loop);
auto coeff2 = extractInductionCoefficients(ptr2, loop);
if (coeff1.size() == coeff2.size()) {
depVec.isKnown = true;
depVec.isConstant = true;
for (size_t i = 0; i < coeff1.size(); ++i) {
depVec.distances[i] = coeff2[i] - coeff1[i];
}
}
}
return depVec;
}
bool LoopVectorizationPass::areAccessesAffinelyRelated(Value* ptr1, Value* ptr2, Loop* loop) {
// 简化实现:检查是否都是基于归纳变量的数组访问
// 真正的实现需要复杂的仿射关系分析
// 检查是否为 GEP 指令
auto* gep1 = dynamic_cast<GetElementPtrInst*>(ptr1);
auto* gep2 = dynamic_cast<GetElementPtrInst*>(ptr2);
if (!gep1 || !gep2) return false;
// 检查是否访问同一个数组基址
if (gep1->getBasePointer() != gep2->getBasePointer()) return false;
// 简化:假设都是仿射的
return true;
}
// ========== 向量化分析实现 (暂时搁置) ==========
VectorizationAnalysis LoopVectorizationPass::analyzeVectorizability(Loop* loop,
const std::vector<PreciseDependence>& dependences,
LoopCharacteristics* characteristics) {
VectorizationAnalysis analysis; // 构造函数已设置为不可向量化
if (DEBUG) {
std::cout << " Vectorization analysis: DISABLED (temporarily)" << std::endl;
}
// 向量化功能暂时搁置,总是返回不可向量化
// 这里可以添加一些基本的诊断信息用于日志
if (!loop->isInnermost()) {
analysis.preventingFactors.push_back("Not innermost loop");
}
if (loop->getBlocks().size() > 1) {
analysis.preventingFactors.push_back("Complex control flow");
}
if (!dependences.empty()) {
analysis.preventingFactors.push_back("Has dependences (not analyzed in detail)");
}
return analysis;
}
// ========== 并行化分析实现 ==========
ParallelizationAnalysis LoopVectorizationPass::analyzeParallelizability(Loop* loop,
const std::vector<PreciseDependence>& dependences,
LoopCharacteristics* characteristics) {
ParallelizationAnalysis analysis;
if (DEBUG) {
std::cout << " Analyzing parallelizability for loop: " << loop->getName() << std::endl;
std::cout << " Found " << dependences.size() << " dependences" << std::endl;
}
// 按依赖类型分类分析
bool hasTrueDependences = false;
bool hasAntiDependences = false;
bool hasOutputDependences = false;
for (const auto& dep : dependences) {
switch (dep.type) {
case DependenceType::TRUE_DEPENDENCE:
hasTrueDependences = true;
// 真依赖通常是最难处理的,需要检查是否为归约模式
if (dep.isReductionDependence) {
analysis.requiresReduction = true;
analysis.reductionVariables.insert(dep.memoryLocation);
} else {
analysis.preventingFactors.push_back("Non-reduction true dependence");
}
break;
case DependenceType::ANTI_DEPENDENCE:
hasAntiDependences = true;
// 反依赖可以通过变量私有化解决
analysis.privatizableVariables.insert(dep.memoryLocation);
break;
case DependenceType::OUTPUT_DEPENDENCE:
hasOutputDependences = true;
// 输出依赖可以通过变量私有化或原子操作解决
analysis.sharedVariables.insert(dep.memoryLocation);
break;
}
}
// 确定并行化类型
analysis.parallelType = determineParallelizationType(loop, dependences);
// 基于依赖类型评估可并行性
if (!hasTrueDependences && !hasOutputDependences) {
// 只有反依赖或无依赖,完全可并行
analysis.parallelType = ParallelizationAnalysis::EMBARRASSINGLY_PARALLEL;
analysis.isParallelizable = true;
} else if (analysis.requiresReduction) {
// 有归约模式,可以并行但需要特殊处理
analysis.parallelType = ParallelizationAnalysis::REDUCTION_PARALLEL;
analysis.isParallelizable = true;
} else if (hasTrueDependences) {
// 有非归约的真依赖,通常不能并行化
analysis.isParallelizable = false;
analysis.preventingFactors.push_back("Non-reduction loop-carried true dependences");
}
if (analysis.isParallelizable) {
// 进一步分析并行化收益和成本
estimateParallelizationBenefit(loop, &analysis, characteristics);
analyzeSynchronizationNeeds(loop, &analysis, dependences);
analysis.suggestedThreadCount = estimateOptimalThreadCount(loop, characteristics);
}
if (DEBUG) {
std::cout << " Parallelizable: " << (analysis.isParallelizable ? "YES" : "NO") << std::endl;
if (analysis.isParallelizable) {
std::cout << " Type: " << (int)analysis.parallelType << ", Threads: " << analysis.suggestedThreadCount << std::endl;
}
}
return analysis;
}
bool LoopVectorizationPass::checkParallelizationLegality(Loop* loop, const std::vector<PreciseDependence>& dependences) {
// 检查所有依赖是否允许并行化
for (const auto& dep : dependences) {
if (!dep.allowsParallelization) {
return false;
}
}
// 检查是否有无法并行化的操作
for (BasicBlock* bb : loop->getBlocks()) {
for (auto& inst : bb->getInstructions()) {
// 检查原子操作、同步操作等
if (auto* call = dynamic_cast<CallInst*>(inst.get())) {
// 简化:假设函数调用需要特殊处理
// 在实际实现中,需要分析函数的副作用
return false;
}
}
}
return true;
}
int LoopVectorizationPass::estimateOptimalThreadCount(Loop* loop, LoopCharacteristics* characteristics) {
// 基于循环特征估计最优线程数
if (!characteristics) return 2;
// 基于循环体大小和计算密度
int baseThreads = 2;
if (characteristics->instructionCount > 50) baseThreads = 4;
if (characteristics->instructionCount > 200) baseThreads = 8;
// 基于计算与内存比率调整
if (characteristics->computeToMemoryRatio > 2.0) {
baseThreads *= 2; // 计算密集型,可以使用更多线程
}
return std::min(baseThreads, 16); // 限制最大线程数
}
// ========== 辅助方法实现 ==========
bool LoopVectorizationPass::isConstantStride(Value* ptr, Loop* loop, int& stride) {
// 简化实现:检查是否为常量步长访问
stride = 1; // 默认步长
auto* gep = dynamic_cast<GetElementPtrInst*>(ptr);
if (!gep) return false;
// 检查最后一个索引是否为归纳变量 + 常量
if (gep->getNumIndices() > 0) {
Value* lastIndex = gep->getIndex(gep->getNumIndices() - 1);
// 简化:假设是 i 或 i+c 的形式
if (auto* binInst = dynamic_cast<BinaryInst*>(lastIndex)) {
if (binInst->getKind() == Instruction::kAdd) {
// 检查是否为 i + constant
if (auto* constInt = dynamic_cast<ConstantInteger*>(binInst->getRhs())) {
stride = constInt->getInt();
return true;
}
}
}
// 默认为步长1的连续访问
stride = 1;
return true;
}
return false;
}
std::vector<int> LoopVectorizationPass::extractInductionCoefficients(Value* ptr, Loop* loop) {
// 简化实现:返回默认的仿射系数
std::vector<int> coefficients;
// 假设是简单的 a[i] 形式,系数为 [0, 1]
coefficients.push_back(0); // 常数项
coefficients.push_back(1); // 归纳变量系数
return coefficients;
}
// ========== 缺失的方法实现 ==========
ParallelizationAnalysis::ParallelizationType LoopVectorizationPass::determineParallelizationType(
Loop* loop, const std::vector<PreciseDependence>& dependences) {
// 检查是否有任何依赖
if (dependences.empty()) {
return ParallelizationAnalysis::EMBARRASSINGLY_PARALLEL;
}
// 检查是否只有归约模式
bool hasReduction = false;
bool hasOtherDependences = false;
for (const auto& dep : dependences) {
if (dep.isReductionDependence) {
hasReduction = true;
} else if (dep.type == DependenceType::TRUE_DEPENDENCE) {
hasOtherDependences = true;
}
}
if (hasReduction && !hasOtherDependences) {
return ParallelizationAnalysis::REDUCTION_PARALLEL;
} else if (!hasOtherDependences) {
return ParallelizationAnalysis::EMBARRASSINGLY_PARALLEL;
}
return ParallelizationAnalysis::NONE;
}
void LoopVectorizationPass::analyzeReductionPatterns(Loop* loop, ParallelizationAnalysis* analysis) {
// 简化实现:查找常见的归约模式
for (BasicBlock* bb : loop->getBlocks()) {
for (auto& inst : bb->getInstructions()) {
if (auto* binInst = dynamic_cast<BinaryInst*>(inst.get())) {
if (binInst->getKind() == Instruction::kAdd || binInst->getKind() == Instruction::kMul) {
// 检查是否为累加/累乘模式
Value* lhs = binInst->getLhs();
if (hasReductionPattern(lhs, loop)) {
analysis->requiresReduction = true;
analysis->reductionVariables.insert(lhs);
}
}
}
}
}
}
void LoopVectorizationPass::analyzeMemoryAccessPatterns(Loop* loop, ParallelizationAnalysis* analysis,
AliasAnalysisResult* aliasAnalysis) {
std::vector<Value*> memoryAccesses;
// 收集所有内存访问
for (BasicBlock* bb : loop->getBlocks()) {
for (auto& inst : bb->getInstructions()) {
if (auto* load = dynamic_cast<LoadInst*>(inst.get())) {
memoryAccesses.push_back(load->getPointer());
} else if (auto* store = dynamic_cast<StoreInst*>(inst.get())) {
memoryAccesses.push_back(store->getPointer());
}
}
}
// 分析内存访问独立性
bool hasIndependentAccess = true;
for (size_t i = 0; i < memoryAccesses.size(); ++i) {
for (size_t j = i + 1; j < memoryAccesses.size(); ++j) {
if (!isIndependentMemoryAccess(memoryAccesses[i], memoryAccesses[j], loop)) {
hasIndependentAccess = false;
analysis->hasMemoryConflicts = true;
}
}
}
analysis->hasIndependentAccess = hasIndependentAccess;
}
void LoopVectorizationPass::estimateParallelizationBenefit(Loop* loop, ParallelizationAnalysis* analysis,
LoopCharacteristics* characteristics) {
if (!analysis->isParallelizable) {
analysis->parallelizationBenefit = 0.0;
return;
}
// 基于计算复杂度和并行度计算收益
double workComplexity = estimateWorkComplexity(loop);
double parallelFraction = 1.0; // 假设完全可并行
// 根据依赖调整并行度
if (analysis->requiresReduction) {
parallelFraction *= 0.8; // 归约降低并行效率
}
if (analysis->hasMemoryConflicts) {
parallelFraction *= 0.6; // 内存冲突降低效率
}
// Amdahl定律估算
double serialFraction = 1.0 - parallelFraction;
int threadCount = analysis->suggestedThreadCount;
double speedup = 1.0 / (serialFraction + parallelFraction / threadCount);
analysis->parallelizationBenefit = std::min((speedup - 1.0) / threadCount, 1.0);
// 估算同步和通信开销
analysis->synchronizationCost = analysis->requiresBarrier ? 100 : 0;
analysis->communicationCost = analysis->sharedVariables.size() * 50;
}
void LoopVectorizationPass::identifyPrivatizableVariables(Loop* loop, ParallelizationAnalysis* analysis) {
// 简化实现:标识循环内定义的变量为可私有化
for (BasicBlock* bb : loop->getBlocks()) {
for (auto& inst : bb->getInstructions()) {
if (!inst->getType()->isVoid()) {
// 如果变量只在循环内使用,可能可以私有化
bool onlyUsedInLoop = true;
for (auto& use : inst->getUses()) {
if (auto* userInst = dynamic_cast<Instruction*>(use->getUser())) {
if (!loop->contains(userInst->getParent())) {
onlyUsedInLoop = false;
break;
}
}
}
if (onlyUsedInLoop) {
analysis->privatizableVariables.insert(inst.get());
}
}
}
}
}
void LoopVectorizationPass::analyzeSynchronizationNeeds(Loop* loop, ParallelizationAnalysis* analysis,
const std::vector<PreciseDependence>& dependences) {
// 根据依赖类型确定同步需求
for (const auto& dep : dependences) {
if (dep.type == DependenceType::OUTPUT_DEPENDENCE) {
analysis->requiresBarrier = true;
analysis->sharedVariables.insert(dep.memoryLocation);
}
}
// 如果有归约,需要特殊的归约同步
if (analysis->requiresReduction) {
analysis->requiresBarrier = true;
}
}
bool LoopVectorizationPass::isIndependentMemoryAccess(Value* ptr1, Value* ptr2, Loop* loop) {
// 简化实现:基本的独立性检查
if (ptr1 == ptr2) return false;
// 如果是不同的基址,认为是独立的
auto* gep1 = dynamic_cast<GetElementPtrInst*>(ptr1);
auto* gep2 = dynamic_cast<GetElementPtrInst*>(ptr2);
if (gep1 && gep2) {
if (gep1->getBasePointer() != gep2->getBasePointer()) {
return true; // 不同的基址
}
// 相同基址,需要更精细的分析(这里简化为不独立)
return false;
}
return true; // 默认认为独立
}
double LoopVectorizationPass::estimateWorkComplexity(Loop* loop) {
double complexity = 0.0;
for (BasicBlock* bb : loop->getBlocks()) {
for (auto& inst : bb->getInstructions()) {
// 基于指令类型分配复杂度权重
if (auto* binInst = dynamic_cast<BinaryInst*>(inst.get())) {
switch (binInst->getKind()) {
case Instruction::kAdd:
case Instruction::kSub:
complexity += 1.0;
break;
case Instruction::kMul:
complexity += 3.0;
break;
case Instruction::kDiv:
complexity += 10.0;
break;
default:
complexity += 2.0;
}
} else if (dynamic_cast<LoadInst*>(inst.get()) || dynamic_cast<StoreInst*>(inst.get())) {
complexity += 2.0; // 内存访问
} else {
complexity += 1.0; // 其他指令
}
}
}
return complexity;
}
bool LoopVectorizationPass::hasReductionPattern(Value* var, Loop* loop) {
// 简化实现:检查是否为简单的累加/累乘模式
for (auto& use : var->getUses()) {
if (auto* binInst = dynamic_cast<BinaryInst*>(use->getUser())) {
if (binInst->getKind() == Instruction::kAdd || binInst->getKind() == Instruction::kMul) {
// 检查是否为 var = var op something 的模式
if (binInst->getLhs() == var || binInst->getRhs() == var) {
return true;
}
}
}
}
return false;
}
} // namespace sysy

View File

@ -0,0 +1,413 @@
#include "SideEffectAnalysis.h"
#include "AliasAnalysis.h"
#include "CallGraphAnalysis.h"
#include "SysYIRPrinter.h"
#include <iostream>
namespace sysy {
// 副作用分析遍的静态 ID
void *SysYSideEffectAnalysisPass::ID = (void *)&SysYSideEffectAnalysisPass::ID;
// ======================================================================
// SideEffectAnalysisResult 类的实现
// ======================================================================
SideEffectAnalysisResult::SideEffectAnalysisResult() { initializeKnownFunctions(); }
const SideEffectInfo &SideEffectAnalysisResult::getInstructionSideEffect(Instruction *inst) const {
auto it = instructionSideEffects.find(inst);
if (it != instructionSideEffects.end()) {
return it->second;
}
// 返回默认的无副作用信息
static SideEffectInfo noEffect;
return noEffect;
}
const SideEffectInfo &SideEffectAnalysisResult::getFunctionSideEffect(Function *func) const {
// 首先检查分析过的用户定义函数
auto it = functionSideEffects.find(func);
if (it != functionSideEffects.end()) {
return it->second;
}
// 如果没有找到,检查是否为已知的库函数
if (func) {
std::string funcName = func->getName();
const SideEffectInfo *knownInfo = getKnownFunctionSideEffect(funcName);
if (knownInfo) {
return *knownInfo;
}
}
// 返回默认的无副作用信息
static SideEffectInfo noEffect;
return noEffect;
}
void SideEffectAnalysisResult::setInstructionSideEffect(Instruction *inst, const SideEffectInfo &info) {
instructionSideEffects[inst] = info;
}
void SideEffectAnalysisResult::setFunctionSideEffect(Function *func, const SideEffectInfo &info) {
functionSideEffects[func] = info;
}
bool SideEffectAnalysisResult::hasSideEffect(Instruction *inst) const {
const auto &info = getInstructionSideEffect(inst);
return info.type != SideEffectType::NO_SIDE_EFFECT;
}
bool SideEffectAnalysisResult::mayModifyMemory(Instruction *inst) const {
const auto &info = getInstructionSideEffect(inst);
return info.mayModifyMemory;
}
bool SideEffectAnalysisResult::mayModifyGlobal(Instruction *inst) const {
const auto &info = getInstructionSideEffect(inst);
return info.mayModifyGlobal;
}
bool SideEffectAnalysisResult::isPureFunction(Function *func) const {
const auto &info = getFunctionSideEffect(func);
return info.isPure;
}
void SideEffectAnalysisResult::initializeKnownFunctions() {
// SysY标准库函数的副作用信息
// I/O函数 - 有副作用
SideEffectInfo ioEffect;
ioEffect.type = SideEffectType::IO_OPERATION;
ioEffect.mayModifyGlobal = true;
ioEffect.mayModifyMemory = true;
ioEffect.mayCallFunction = true;
ioEffect.isPure = false;
// knownFunctions["printf"] = ioEffect;
// knownFunctions["scanf"] = ioEffect;
knownFunctions["getint"] = ioEffect;
knownFunctions["getch"] = ioEffect;
knownFunctions["getfloat"] = ioEffect;
knownFunctions["getarray"] = ioEffect;
knownFunctions["getfarray"] = ioEffect;
knownFunctions["putint"] = ioEffect;
knownFunctions["putch"] = ioEffect;
knownFunctions["putfloat"] = ioEffect;
knownFunctions["putarray"] = ioEffect;
knownFunctions["putfarray"] = ioEffect;
// 时间函数 - 有副作用
SideEffectInfo timeEffect;
timeEffect.type = SideEffectType::FUNCTION_CALL;
timeEffect.mayModifyGlobal = true;
timeEffect.mayModifyMemory = false;
timeEffect.mayCallFunction = true;
timeEffect.isPure = false;
knownFunctions["_sysy_starttime"] = timeEffect;
knownFunctions["_sysy_stoptime"] = timeEffect;
}
const SideEffectInfo *SideEffectAnalysisResult::getKnownFunctionSideEffect(const std::string &funcName) const {
auto it = knownFunctions.find(funcName);
return (it != knownFunctions.end()) ? &it->second : nullptr;
}
// ======================================================================
// SysYSideEffectAnalysisPass 类的实现
// ======================================================================
bool SysYSideEffectAnalysisPass::runOnModule(Module *M, AnalysisManager &AM) {
if (DEBUG) {
std::cout << "Running SideEffect analysis on module" << std::endl;
}
// 创建分析结果构造函数中已经调用了initializeKnownFunctions
result = std::make_unique<SideEffectAnalysisResult>();
// 获取调用图分析结果
callGraphAnalysis = AM.getAnalysisResult<CallGraphAnalysisResult, CallGraphAnalysisPass>();
if (!callGraphAnalysis) {
std::cerr << "Warning: CallGraphAnalysis not available, falling back to conservative analysis" << std::endl;
}
// 按拓扑序分析函数,确保被调用函数先于调用者分析
if (callGraphAnalysis) {
// 使用调用图的拓扑排序结果
const auto &topOrder = callGraphAnalysis->getTopologicalOrder();
// 处理强连通分量(递归函数群)
const auto &sccs = callGraphAnalysis->getStronglyConnectedComponents();
for (const auto &scc : sccs) {
if (scc.size() > 1) {
// 多个函数的强连通分量,使用不动点算法
analyzeStronglyConnectedComponent(scc, AM);
} else {
// 单个函数,检查是否自递归
Function *func = scc[0];
if (callGraphAnalysis->isSelfRecursive(func)) {
// 自递归函数也需要不动点算法
analyzeStronglyConnectedComponent(scc, AM);
} else {
// 非递归函数,直接分析
SideEffectInfo funcEffect = analyzeFunction(func, AM);
result->setFunctionSideEffect(func, funcEffect);
}
}
}
} else {
// 没有调用图,保守地分析每个函数
for (auto &pair : M->getFunctions()) {
Function *func = pair.second.get();
SideEffectInfo funcEffect = analyzeFunction(func, AM);
result->setFunctionSideEffect(func, funcEffect);
}
}
if (DEBUG) {
std::cout << "---- Side Effect Analysis Results for Module ----\n";
for (auto &pair : M->getFunctions()) {
Function *func = pair.second.get();
const auto &funcInfo = result->getFunctionSideEffect(func);
std::cout << "Function " << func->getName() << ": ";
switch (funcInfo.type) {
case SideEffectType::NO_SIDE_EFFECT:
std::cout << "No Side Effect";
break;
case SideEffectType::MEMORY_WRITE:
std::cout << "Memory Write";
break;
case SideEffectType::FUNCTION_CALL:
std::cout << "Function Call";
break;
case SideEffectType::IO_OPERATION:
std::cout << "I/O Operation";
break;
case SideEffectType::UNKNOWN:
std::cout << "Unknown";
break;
}
std::cout << " (Pure: " << (funcInfo.isPure ? "Yes" : "No")
<< ", Modifies Global: " << (funcInfo.mayModifyGlobal ? "Yes" : "No") << ")\n";
}
std::cout << "--------------------------------------------------\n";
}
return false; // Analysis passes return false since they don't modify the IR
}
std::unique_ptr<AnalysisResultBase> SysYSideEffectAnalysisPass::getResult() { return std::move(result); }
SideEffectInfo SysYSideEffectAnalysisPass::analyzeFunction(Function *func, AnalysisManager &AM) {
SideEffectInfo functionSideEffect;
// 为每个指令分析副作用
for (auto &BB : func->getBasicBlocks()) {
for (auto &I : BB->getInstructions_Range()) {
Instruction *inst = I.get();
SideEffectInfo instEffect = analyzeInstruction(inst, func, AM);
// 记录指令的副作用信息
result->setInstructionSideEffect(inst, instEffect);
// 合并到函数级别的副作用信息中
functionSideEffect = functionSideEffect.merge(instEffect);
}
}
return functionSideEffect;
}
void SysYSideEffectAnalysisPass::analyzeStronglyConnectedComponent(const std::vector<Function *> &scc,
AnalysisManager &AM) {
// 使用不动点算法处理递归函数群
std::unordered_map<Function *, SideEffectInfo> currentEffects;
std::unordered_map<Function *, SideEffectInfo> previousEffects;
// 初始化:所有函数都假设为纯函数
for (Function *func : scc) {
SideEffectInfo initialEffect;
initialEffect.isPure = true;
currentEffects[func] = initialEffect;
result->setFunctionSideEffect(func, initialEffect);
}
bool converged = false;
int iterations = 0;
const int maxIterations = 10; // 防止无限循环
while (!converged && iterations < maxIterations) {
previousEffects = currentEffects;
// 重新分析每个函数
for (Function *func : scc) {
SideEffectInfo newEffect = analyzeFunction(func, AM);
currentEffects[func] = newEffect;
result->setFunctionSideEffect(func, newEffect);
}
// 检查是否收敛
converged = hasConverged(previousEffects, currentEffects);
iterations++;
}
if (iterations >= maxIterations) {
std::cerr << "Warning: SideEffect analysis did not converge for SCC after " << maxIterations << " iterations"
<< std::endl;
}
}
bool SysYSideEffectAnalysisPass::hasConverged(const std::unordered_map<Function *, SideEffectInfo> &oldEffects,
const std::unordered_map<Function *, SideEffectInfo> &newEffects) const {
for (const auto &pair : oldEffects) {
Function *func = pair.first;
const SideEffectInfo &oldEffect = pair.second;
auto it = newEffects.find(func);
if (it == newEffects.end()) {
return false; // 函数不存在于新结果中
}
const SideEffectInfo &newEffect = it->second;
// 比较关键属性是否相同
if (oldEffect.type != newEffect.type || oldEffect.mayModifyGlobal != newEffect.mayModifyGlobal ||
oldEffect.mayModifyMemory != newEffect.mayModifyMemory ||
oldEffect.mayCallFunction != newEffect.mayCallFunction || oldEffect.isPure != newEffect.isPure) {
return false;
}
}
return true;
}
SideEffectInfo SysYSideEffectAnalysisPass::analyzeInstruction(Instruction *inst, Function *currentFunc,
AnalysisManager &AM) {
SideEffectInfo info;
// 根据指令类型进行分析
if (inst->isCall()) {
return analyzeCallInstruction(static_cast<CallInst *>(inst), currentFunc, AM);
} else if (inst->isStore()) {
return analyzeStoreInstruction(static_cast<StoreInst *>(inst), currentFunc, AM);
} else if (inst->isMemset()) {
return analyzeMemsetInstruction(static_cast<MemsetInst *>(inst), currentFunc, AM);
} else if (inst->isBranch() || inst->isReturn()) {
// 控制流指令无副作用,但必须保留
info.type = SideEffectType::NO_SIDE_EFFECT;
info.isPure = true;
} else {
// 其他指令(算术、逻辑、比较等)通常无副作用
info.type = SideEffectType::NO_SIDE_EFFECT;
info.isPure = true;
}
return info;
}
SideEffectInfo SysYSideEffectAnalysisPass::analyzeCallInstruction(CallInst *call, Function *currentFunc,
AnalysisManager &AM) {
SideEffectInfo info;
// 获取被调用的函数
Function *calledFunc = call->getCallee();
if (!calledFunc) {
// 间接调用,保守处理
info.type = SideEffectType::UNKNOWN;
info.mayModifyGlobal = true;
info.mayModifyMemory = true;
info.mayCallFunction = true;
info.isPure = false;
return info;
}
std::string funcName = calledFunc->getName();
// 检查是否为已知的标准库函数
const SideEffectInfo *knownInfo = result->getKnownFunctionSideEffect(funcName);
if (knownInfo) {
return *knownInfo;
}
// 利用调用图分析结果进行精确分析
if (callGraphAnalysis) {
// 检查被调用函数是否已分析过
const SideEffectInfo &funcEffect = result->getFunctionSideEffect(calledFunc);
if (funcEffect.type != SideEffectType::NO_SIDE_EFFECT || !funcEffect.isPure) {
return funcEffect;
}
// 检查递归调用
if (callGraphAnalysis->isRecursive(calledFunc)) {
// 递归函数保守处理(在不动点算法中会精确分析)
info.type = SideEffectType::FUNCTION_CALL;
info.mayModifyGlobal = true;
info.mayModifyMemory = true;
info.mayCallFunction = true;
info.isPure = false;
return info;
}
}
// 对于未分析的用户函数,保守处理
info.type = SideEffectType::FUNCTION_CALL;
info.mayModifyGlobal = true;
info.mayModifyMemory = true;
info.mayCallFunction = true;
info.isPure = false;
return info;
}
SideEffectInfo SysYSideEffectAnalysisPass::analyzeStoreInstruction(StoreInst *store, Function *currentFunc,
AnalysisManager &AM) {
SideEffectInfo info;
info.type = SideEffectType::MEMORY_WRITE;
info.mayModifyMemory = true;
info.isPure = false;
// 获取函数的别名分析结果
AliasAnalysisResult *aliasAnalysis = AM.getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(currentFunc);
if (aliasAnalysis) {
Value *storePtr = store->getPointer();
// 如果存储到全局变量或可能别名的位置,则可能修改全局状态
if (!aliasAnalysis->isLocalArray(storePtr)) {
info.mayModifyGlobal = true;
}
} else {
// 没有别名分析结果,保守处理
info.mayModifyGlobal = true;
}
return info;
}
SideEffectInfo SysYSideEffectAnalysisPass::analyzeMemsetInstruction(MemsetInst *memset, Function *currentFunc,
AnalysisManager &AM) {
SideEffectInfo info;
info.type = SideEffectType::MEMORY_WRITE;
info.mayModifyMemory = true;
info.isPure = false;
// 获取函数的别名分析结果
AliasAnalysisResult *aliasAnalysis = AM.getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(currentFunc);
if (aliasAnalysis) {
Value *memsetPtr = memset->getPointer();
// 如果memset操作全局变量或可能别名的位置则可能修改全局状态
if (!aliasAnalysis->isLocalArray(memsetPtr)) {
info.mayModifyGlobal = true;
}
} else {
// 没有别名分析结果,保守处理
info.mayModifyGlobal = true;
}
return info;
}
} // 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

@ -1,9 +1,9 @@
#include "DCE.h" // 包含DCE遍的头文件
#include "IR.h" // 包含IR相关的定义
#include "SysYIROptUtils.h" // 包含SysY IR优化工具类的定义
#include <cassert> // 用于断言
#include <iostream> // 用于调试输出
#include <set> // 包含set虽然DCEContext内部用unordered_set但这里保留
#include "DCE.h"
#include "SysYIROptUtils.h"
#include "SideEffectAnalysis.h"
#include <cassert>
#include <iostream>
#include <set>
namespace sysy {
@ -17,10 +17,26 @@ void *DCE::ID = (void *)&DCE::ID;
// DCEContext 的 run 方法实现
void DCEContext::run(Function *func, AnalysisManager *AM, bool &changed) {
// 获取别名分析结果
if (AM) {
aliasAnalysis = AM->getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(func);
// 获取副作用分析结果Module级别
sideEffectAnalysis = AM->getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>();
if (DEBUG) {
if (aliasAnalysis) {
std::cout << "DCE: Using alias analysis results" << std::endl;
}
if (sideEffectAnalysis) {
std::cout << "DCE: Using side effect analysis results" << std::endl;
}
}
}
// 清空活跃指令集合,确保每次运行都是新的状态
alive_insts.clear();
// 第一次遍历:扫描所有指令,识别天然活跃的指令并将其及其依赖标记为活跃
// 第一次遍历:扫描所有指令,识别"天然活跃"的指令并将其及其依赖标记为活跃
// 使用 func->getBasicBlocks() 获取基本块列表,保留用户风格
auto basicBlocks = func->getBasicBlocks();
for (auto &basicBlock : basicBlocks) {
@ -51,7 +67,7 @@ void DCEContext::run(Function *func, AnalysisManager *AM, bool &changed) {
// 如果指令不在活跃集合中,则删除它。
// 分支和返回指令由 isAlive 处理,并会被保留。
if (alive_insts.count(currentInst) == 0) {
instIter = SysYIROptUtils::usedelete(instIter); // 删除后返回下一个迭代器
instIter = SysYIROptUtils::usedelete(instIter); // 删除后返回下一个迭代器
changed = true; // 标记 IR 已被修改
} else {
++instIter; // 指令活跃,移动到下一个
@ -60,20 +76,58 @@ void DCEContext::run(Function *func, AnalysisManager *AM, bool &changed) {
}
}
// 判断指令是否是天然活跃的实现
// 判断指令是否是"天然活跃"的实现
// 只有具有副作用的指令(如存储、函数调用、原子操作)
// 和控制流指令(如分支、返回)是天然活跃的。
bool DCEContext::isAlive(Instruction *inst) {
// TODO: 后续程序并发考虑原子操作
// 其结果不被其他指令使用的指令(例如 StoreInst, BranchInst, ReturnInst
// dynamic_cast<ir::CallInst>(inst) 检查是否是函数调用指令,
// 函数调用通常有副作用。
// 终止指令 (BranchInst, ReturnInst) 必须是活跃的,因为它控制了程序的执行流程。
// 保留用户提供的 isAlive 逻辑
bool isBranchOrReturn = inst->isBranch() || inst->isReturn();
bool isCall = inst->isCall();
bool isStoreOrMemset = inst->isStore() || inst->isMemset();
return isBranchOrReturn || isCall || isStoreOrMemset;
// 终止指令 (BranchInst, ReturnInst) 必须是活跃的,因为它控制了程序的执行流程
if (inst->isBranch() || inst->isReturn()) {
return true;
}
// 使用副作用分析来判断指令是否有副作用
if (sideEffectAnalysis && sideEffectAnalysis->hasSideEffect(inst)) {
return true;
}
// 特殊处理Store指令使用别名分析进行更精确的判断
if (inst->isStore()) {
auto* storeInst = static_cast<StoreInst*>(inst);
return mayHaveSideEffect(storeInst);
}
// 特殊处理Memset指令总是保留因为它修改内存
if (inst->isMemset()) {
return true;
}
// 函数调用指令:总是保留(可能有未知副作用)
if (inst->isCall()) {
return true;
}
// 其他指令算术、逻辑、Load等无副作用可以删除
return false;
}
// 检查Store指令是否可能有副作用通过别名分析
bool DCEContext::mayHaveSideEffect(StoreInst* store) {
if (!aliasAnalysis) {
// 没有别名分析结果时保守地认为所有store都有副作用
return true;
}
Value* storePtr = store->getPointer();
// 如果是对本地数组的存储且访问模式是常量,可能可以安全删除
if (aliasAnalysis->isLocalArray(storePtr)) {
// 检查是否有其他指令可能读取这个位置
// 这里需要更复杂的活性分析,暂时保守处理
return true; // 保守地保留所有本地数组的存储
}
// 对全局变量、函数参数等的存储总是有副作用
return true;
}
// 递归地将活跃指令及其依赖加入到 alive_insts 集合中
@ -102,7 +156,6 @@ void DCEContext::addAlive(Instruction *inst) {
// DCE 遍的 runOnFunction 方法实现
bool DCE::runOnFunction(Function *func, AnalysisManager &AM) {
DCEContext ctx;
bool changed = false;
ctx.run(func, &AM, changed); // 运行 DCE 优化
@ -120,7 +173,11 @@ bool DCE::runOnFunction(Function *func, AnalysisManager &AM) {
// 声明DCE遍的分析依赖和失效信息
void DCE::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
// DCE依赖特定的分析结果,它通过遍历和副作用判断来工作。
// DCE依赖别名分析来更精确地判断Store指令的副作用
analysisDependencies.insert(&SysYAliasAnalysisPass::ID);
// DCE依赖副作用分析来判断指令是否有副作用
analysisDependencies.insert(&SysYSideEffectAnalysisPass::ID);
// DCE会删除指令这会影响许多分析结果。
// 至少,它会影响活跃性分析、支配树、控制流图(如果删除导致基本块为空并被合并)。

View File

@ -0,0 +1,492 @@
#include "GVN.h"
#include "Dom.h"
#include "SysYIROptUtils.h"
#include <algorithm>
#include <cassert>
#include <iostream>
#include <unordered_map>
#include <unordered_set>
extern int DEBUG;
namespace sysy {
// GVN 遍的静态 ID
void *GVN::ID = (void *)&GVN::ID;
// ======================================================================
// GVN 类的实现
// ======================================================================
bool GVN::runOnFunction(Function *func, AnalysisManager &AM) {
if (func->getBasicBlocks().empty()) {
return false;
}
if (DEBUG) {
std::cout << "\n=== Running GVN on function: " << func->getName() << " ===" << std::endl;
}
bool changed = false;
GVNContext context;
context.run(func, &AM, changed);
if (DEBUG) {
if (changed) {
std::cout << "GVN: Function " << func->getName() << " was modified" << std::endl;
} else {
std::cout << "GVN: Function " << func->getName() << " was not modified" << std::endl;
}
std::cout << "=== GVN completed for function: " << func->getName() << " ===" << std::endl;
}
return changed;
}
void GVN::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
// GVN依赖以下分析
// 1. 支配树分析 - 用于检查指令的支配关系,确保替换的安全性
analysisDependencies.insert(&DominatorTreeAnalysisPass::ID);
// 2. 副作用分析 - 用于判断函数调用是否可以进行GVN
analysisDependencies.insert(&SysYSideEffectAnalysisPass::ID);
// GVN不会使任何分析失效因为
// - GVN只删除冗余计算不改变CFG结构
// - GVN不修改程序的语义只是消除重复计算
// - 支配关系保持不变
// - 副作用分析结果保持不变
// analysisInvalidations 保持为空
if (DEBUG) {
std::cout << "GVN: Declared analysis dependencies (DominatorTree, SideEffectAnalysis)" << std::endl;
}
}
// ======================================================================
// GVNContext 类的实现 - 重构版本
// ======================================================================
// 简单的表达式哈希结构
struct ExpressionKey {
enum Type { BINARY, UNARY, LOAD, GEP, CALL } type;
int opcode;
std::vector<Value*> operands;
Type* resultType;
bool operator==(const ExpressionKey& other) const {
return type == other.type && opcode == other.opcode &&
operands == other.operands && resultType == other.resultType;
}
};
struct ExpressionKeyHash {
size_t operator()(const ExpressionKey& key) const {
size_t hash = std::hash<int>()(static_cast<int>(key.type)) ^
std::hash<int>()(key.opcode);
for (auto op : key.operands) {
hash ^= std::hash<Value*>()(op) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
}
return hash;
}
};
void GVNContext::run(Function *func, AnalysisManager *AM, bool &changed) {
if (DEBUG) {
std::cout << " Starting GVN analysis for function: " << func->getName() << std::endl;
}
// 获取分析结果
if (AM) {
domTree = AM->getAnalysisResult<DominatorTree, DominatorTreeAnalysisPass>(func);
sideEffectAnalysis = AM->getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>();
if (DEBUG) {
if (domTree) {
std::cout << " GVN: Using dominator tree analysis" << std::endl;
} else {
std::cout << " GVN: Warning - dominator tree analysis not available" << std::endl;
}
if (sideEffectAnalysis) {
std::cout << " GVN: Using side effect analysis" << std::endl;
} else {
std::cout << " GVN: Warning - side effect analysis not available" << std::endl;
}
}
}
// 清空状态
valueToNumber.clear();
numberToValue.clear();
expressionToNumber.clear();
nextValueNumber = 1;
visited.clear();
rpoBlocks.clear();
needRemove.clear();
// 计算逆后序遍历
computeRPO(func);
if (DEBUG) {
std::cout << " Computed RPO with " << rpoBlocks.size() << " blocks" << std::endl;
}
// 按逆后序遍历基本块进行GVN
int blockCount = 0;
for (auto bb : rpoBlocks) {
if (DEBUG) {
std::cout << " Processing block " << ++blockCount << "/" << rpoBlocks.size()
<< ": " << bb->getName() << std::endl;
}
processBasicBlock(bb, changed);
}
if (DEBUG) {
std::cout << " Found " << needRemove.size() << " redundant instructions to remove" << std::endl;
}
// 删除冗余指令
eliminateRedundantInstructions(changed);
if (DEBUG) {
std::cout << " GVN analysis completed for function: " << func->getName() << std::endl;
std::cout << " Total values numbered: " << valueToNumber.size() << std::endl;
std::cout << " Instructions eliminated: " << needRemove.size() << std::endl;
}
}
void GVNContext::computeRPO(Function *func) {
rpoBlocks.clear();
visited.clear();
auto entry = func->getEntryBlock();
if (entry) {
dfs(entry);
std::reverse(rpoBlocks.begin(), rpoBlocks.end());
}
}
void GVNContext::dfs(BasicBlock *bb) {
if (!bb || visited.count(bb)) {
return;
}
visited.insert(bb);
// 访问所有后继基本块
for (auto succ : bb->getSuccessors()) {
if (visited.find(succ) == visited.end()) {
dfs(succ);
}
}
rpoBlocks.push_back(bb);
}
unsigned GVNContext::getValueNumber(Value* value) {
// 如果已经有值编号,直接返回
auto it = valueToNumber.find(value);
if (it != valueToNumber.end()) {
return it->second;
}
// 为新值分配编号
return assignValueNumber(value);
}
unsigned GVNContext::assignValueNumber(Value* value) {
unsigned number = nextValueNumber++;
valueToNumber[value] = number;
numberToValue[number] = value;
if (DEBUG >= 2) {
std::cout << " Assigned value number " << number
<< " to " << value->getName() << std::endl;
}
return number;
}
void GVNContext::processBasicBlock(BasicBlock* bb, bool& changed) {
int instCount = 0;
for (auto &instPtr : bb->getInstructions()) {
if (DEBUG) {
std::cout << " Processing instruction " << ++instCount
<< ": " << instPtr->getName() << std::endl;
}
if (processInstruction(instPtr.get())) {
changed = true;
}
}
}
bool GVNContext::processInstruction(Instruction* inst) {
// 跳过分支指令和其他不可优化的指令
if (inst->isBranch() || dynamic_cast<ReturnInst*>(inst) ||
dynamic_cast<AllocaInst*>(inst) || dynamic_cast<StoreInst*>(inst)) {
// 如果是store指令需要使相关的内存值失效
if (auto store = dynamic_cast<StoreInst*>(inst)) {
invalidateMemoryValues(store);
}
// 为这些指令分配值编号但不尝试优化
getValueNumber(inst);
return false;
}
if (DEBUG) {
std::cout << " Processing optimizable instruction: " << inst->getName()
<< " (kind: " << static_cast<int>(inst->getKind()) << ")" << std::endl;
}
// 构建表达式键
std::string exprKey = buildExpressionKey(inst);
if (exprKey.empty()) {
// 不可优化的指令,只分配值编号
getValueNumber(inst);
return false;
}
if (DEBUG >= 2) {
std::cout << " Expression key: " << exprKey << std::endl;
}
// 查找已存在的等价值
Value* existing = findExistingValue(exprKey, inst);
if (existing && existing != inst) {
// 检查支配关系
if (auto existingInst = dynamic_cast<Instruction*>(existing)) {
if (dominates(existingInst, inst)) {
if (DEBUG) {
std::cout << " GVN: Replacing " << inst->getName()
<< " with existing " << existing->getName() << std::endl;
}
// 用已存在的值替换当前指令
inst->replaceAllUsesWith(existing);
needRemove.insert(inst);
// 将当前指令的值编号指向已存在的值
unsigned existingNumber = getValueNumber(existing);
valueToNumber[inst] = existingNumber;
return true;
} else {
if (DEBUG) {
std::cout << " Found equivalent but dominance check failed" << std::endl;
}
}
}
}
// 没有找到等价值,为这个表达式分配新的值编号
unsigned number = assignValueNumber(inst);
expressionToNumber[exprKey] = number;
if (DEBUG) {
std::cout << " Instruction " << inst->getName() << " is unique" << std::endl;
}
return false;
}
std::string GVNContext::buildExpressionKey(Instruction* inst) {
std::ostringstream oss;
if (auto binary = dynamic_cast<BinaryInst*>(inst)) {
oss << "binary_" << static_cast<int>(binary->getKind()) << "_";
oss << getValueNumber(binary->getLhs()) << "_" << getValueNumber(binary->getRhs());
// 对于可交换操作,确保操作数顺序一致
if (binary->isCommutative()) {
unsigned lhsNum = getValueNumber(binary->getLhs());
unsigned rhsNum = getValueNumber(binary->getRhs());
if (lhsNum > rhsNum) {
oss.str("");
oss << "binary_" << static_cast<int>(binary->getKind()) << "_";
oss << rhsNum << "_" << lhsNum;
}
}
} else if (auto unary = dynamic_cast<UnaryInst*>(inst)) {
oss << "unary_" << static_cast<int>(unary->getKind()) << "_";
oss << getValueNumber(unary->getOperand());
} else if (auto gep = dynamic_cast<GetElementPtrInst*>(inst)) {
oss << "gep_" << getValueNumber(gep->getBasePointer());
for (unsigned i = 0; i < gep->getNumIndices(); ++i) {
oss << "_" << getValueNumber(gep->getIndex(i));
}
} else if (auto load = dynamic_cast<LoadInst*>(inst)) {
oss << "load_" << getValueNumber(load->getPointer());
oss << "_" << reinterpret_cast<uintptr_t>(load->getType()); // 类型区分
} else if (auto call = dynamic_cast<CallInst*>(inst)) {
// 只为无副作用的函数调用建立表达式
if (sideEffectAnalysis && sideEffectAnalysis->isPureFunction(call->getCallee())) {
oss << "call_" << call->getCallee()->getName();
for (size_t i = 1; i < call->getNumOperands(); ++i) { // 跳过函数指针
oss << "_" << getValueNumber(call->getOperand(i));
}
} else {
return ""; // 有副作用的函数调用不可优化
}
} else {
return ""; // 不支持的指令类型
}
return oss.str();
}
Value* GVNContext::findExistingValue(const std::string& exprKey, Instruction* inst) {
auto it = expressionToNumber.find(exprKey);
if (it != expressionToNumber.end()) {
unsigned number = it->second;
auto valueIt = numberToValue.find(number);
if (valueIt != numberToValue.end()) {
Value* existing = valueIt->second;
// 对于load指令需要额外检查内存安全性
if (auto loadInst = dynamic_cast<LoadInst*>(inst)) {
if (auto existingLoad = dynamic_cast<LoadInst*>(existing)) {
if (!isMemorySafe(existingLoad, loadInst)) {
return nullptr;
}
}
}
return existing;
}
}
return nullptr;
}
bool GVNContext::dominates(Instruction* a, Instruction* b) {
auto aBB = a->getParent();
auto bBB = b->getParent();
// 同一基本块内的情况
if (aBB == bBB) {
auto &insts = aBB->getInstructions();
auto aIt = std::find_if(insts.begin(), insts.end(),
[a](const auto &ptr) { return ptr.get() == a; });
auto bIt = std::find_if(insts.begin(), insts.end(),
[b](const auto &ptr) { return ptr.get() == b; });
if (aIt == insts.end() || bIt == insts.end()) {
return false;
}
return std::distance(insts.begin(), aIt) < std::distance(insts.begin(), bIt);
}
// 不同基本块的情况,使用支配树
if (domTree) {
auto dominators = domTree->getDominators(bBB);
return dominators && dominators->count(aBB);
}
return false; // 保守做法
}
bool GVNContext::isMemorySafe(LoadInst* earlierLoad, LoadInst* laterLoad) {
// 检查两个load是否访问相同的内存位置
unsigned earlierPtr = getValueNumber(earlierLoad->getPointer());
unsigned laterPtr = getValueNumber(laterLoad->getPointer());
if (earlierPtr != laterPtr) {
return false; // 不同的内存位置
}
// 检查类型是否匹配
if (earlierLoad->getType() != laterLoad->getType()) {
return false;
}
// 简单情况如果在同一个基本块且没有中间的store则安全
auto earlierBB = earlierLoad->getParent();
auto laterBB = laterLoad->getParent();
if (earlierBB != laterBB) {
// 跨基本块的情况需要更复杂的分析,暂时保守处理
return false;
}
// 同一基本块内检查是否有中间的store
auto &insts = earlierBB->getInstructions();
auto earlierIt = std::find_if(insts.begin(), insts.end(),
[earlierLoad](const auto &ptr) { return ptr.get() == earlierLoad; });
auto laterIt = std::find_if(insts.begin(), insts.end(),
[laterLoad](const auto &ptr) { return ptr.get() == laterLoad; });
if (earlierIt == insts.end() || laterIt == insts.end()) {
return false;
}
// 确保earlierLoad真的在laterLoad之前
if (std::distance(insts.begin(), earlierIt) >= std::distance(insts.begin(), laterIt)) {
return false;
}
// 检查中间是否有store指令修改了相同的内存位置
for (auto it = std::next(earlierIt); it != laterIt; ++it) {
if (auto store = dynamic_cast<StoreInst*>(it->get())) {
unsigned storePtr = getValueNumber(store->getPointer());
if (storePtr == earlierPtr) {
return false; // 找到中间的store
}
}
// 检查函数调用是否可能修改内存
if (auto call = dynamic_cast<CallInst*>(it->get())) {
if (sideEffectAnalysis && !sideEffectAnalysis->isPureFunction(call->getCallee())) {
// 保守处理:有副作用的函数可能修改内存
return false;
}
}
}
return true; // 安全
}
void GVNContext::invalidateMemoryValues(StoreInst* store) {
unsigned storePtr = getValueNumber(store->getPointer());
if (DEBUG) {
std::cout << " Invalidating memory values affected by store" << std::endl;
}
// 找到所有可能被这个store影响的load表达式
std::vector<std::string> toRemove;
for (auto& [exprKey, number] : expressionToNumber) {
if (exprKey.find("load_" + std::to_string(storePtr)) == 0) {
toRemove.push_back(exprKey);
if (DEBUG) {
std::cout << " Invalidating expression: " << exprKey << std::endl;
}
}
}
// 移除失效的表达式
for (const auto& key : toRemove) {
expressionToNumber.erase(key);
}
}
void GVNContext::eliminateRedundantInstructions(bool& changed) {
int removeCount = 0;
for (auto inst : needRemove) {
if (DEBUG) {
std::cout << " Removing redundant instruction " << ++removeCount
<< "/" << needRemove.size() << ": " << inst->getName() << std::endl;
}
// 删除指令前先断开所有使用关系
// inst->replaceAllUsesWith 已在 processInstruction 中调用
SysYIROptUtils::usedelete(inst);
changed = true;
}
}
} // namespace sysy

View File

@ -0,0 +1,897 @@
#include "GlobalStrengthReduction.h"
#include "SysYIROptUtils.h"
#include "IRBuilder.h"
#include <algorithm>
#include <cassert>
#include <iostream>
#include <cmath>
extern int DEBUG;
namespace sysy {
// 全局强度削弱优化遍的静态 ID
void *GlobalStrengthReduction::ID = (void *)&GlobalStrengthReduction::ID;
// ======================================================================
// GlobalStrengthReduction 类的实现
// ======================================================================
bool GlobalStrengthReduction::runOnFunction(Function *func, AnalysisManager &AM) {
if (func->getBasicBlocks().empty()) {
return false;
}
if (DEBUG) {
std::cout << "\n=== Running GlobalStrengthReduction on function: " << func->getName() << " ===" << std::endl;
}
bool changed = false;
GlobalStrengthReductionContext context(builder);
context.run(func, &AM, changed);
if (DEBUG) {
if (changed) {
std::cout << "GlobalStrengthReduction: Function " << func->getName() << " was modified" << std::endl;
} else {
std::cout << "GlobalStrengthReduction: Function " << func->getName() << " was not modified" << std::endl;
}
std::cout << "=== GlobalStrengthReduction completed for function: " << func->getName() << " ===" << std::endl;
}
return changed;
}
void GlobalStrengthReduction::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
// 强度削弱依赖副作用分析来判断指令是否可以安全优化
analysisDependencies.insert(&SysYSideEffectAnalysisPass::ID);
// 强度削弱不会使分析失效,因为:
// - 只替换计算指令,不改变控制流
// - 不修改内存,不影响别名分析
// - 保持程序语义不变
// analysisInvalidations 保持为空
if (DEBUG) {
std::cout << "GlobalStrengthReduction: Declared analysis dependencies (SideEffectAnalysis)" << std::endl;
}
}
// ======================================================================
// GlobalStrengthReductionContext 类的实现
// ======================================================================
void GlobalStrengthReductionContext::run(Function *func, AnalysisManager *AM, bool &changed) {
if (DEBUG) {
std::cout << " Starting GlobalStrengthReduction analysis for function: " << func->getName() << std::endl;
}
// 获取分析结果
if (AM) {
sideEffectAnalysis = AM->getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>();
if (DEBUG) {
if (sideEffectAnalysis) {
std::cout << " GlobalStrengthReduction: Using side effect analysis" << std::endl;
} else {
std::cout << " GlobalStrengthReduction: Warning - side effect analysis not available" << std::endl;
}
}
}
// 重置计数器
algebraicOptCount = 0;
strengthReductionCount = 0;
divisionOptCount = 0;
// 遍历所有基本块进行优化
for (auto &bb_ptr : func->getBasicBlocks()) {
if (processBasicBlock(bb_ptr.get())) {
changed = true;
}
}
if (DEBUG) {
std::cout << " GlobalStrengthReduction completed for function: " << func->getName() << std::endl;
std::cout << " Algebraic optimizations: " << algebraicOptCount << std::endl;
std::cout << " Strength reductions: " << strengthReductionCount << std::endl;
std::cout << " Division optimizations: " << divisionOptCount << std::endl;
}
}
bool GlobalStrengthReductionContext::processBasicBlock(BasicBlock *bb) {
bool changed = false;
if (DEBUG) {
std::cout << " Processing block: " << bb->getName() << std::endl;
}
// 收集需要处理的指令(避免迭代器失效)
std::vector<Instruction*> instructions;
for (auto &inst_ptr : bb->getInstructions()) {
instructions.push_back(inst_ptr.get());
}
// 处理每条指令
for (auto inst : instructions) {
if (processInstruction(inst)) {
changed = true;
}
}
return changed;
}
bool GlobalStrengthReductionContext::processInstruction(Instruction *inst) {
if (DEBUG) {
std::cout << " Processing instruction: " << inst->getName() << std::endl;
}
// 先尝试代数优化
if (tryAlgebraicOptimization(inst)) {
algebraicOptCount++;
return true;
}
// 再尝试强度削弱
if (tryStrengthReduction(inst)) {
strengthReductionCount++;
return true;
}
return false;
}
// ======================================================================
// 代数优化方法
// ======================================================================
bool GlobalStrengthReductionContext::tryAlgebraicOptimization(Instruction *inst) {
auto binary = dynamic_cast<BinaryInst*>(inst);
if (!binary) {
return false;
}
switch (binary->getKind()) {
case Instruction::kAdd:
return optimizeAddition(binary);
case Instruction::kSub:
return optimizeSubtraction(binary);
case Instruction::kMul:
return optimizeMultiplication(binary);
case Instruction::kDiv:
return optimizeDivision(binary);
case Instruction::kICmpEQ:
case Instruction::kICmpNE:
case Instruction::kICmpLT:
case Instruction::kICmpGT:
case Instruction::kICmpLE:
case Instruction::kICmpGE:
return optimizeComparison(binary);
case Instruction::kAnd:
case Instruction::kOr:
return optimizeLogical(binary);
default:
return false;
}
}
bool GlobalStrengthReductionContext::optimizeAddition(BinaryInst *inst) {
Value *lhs = inst->getLhs();
Value *rhs = inst->getRhs();
int constVal;
// x + 0 = x
if (isConstantInt(rhs, constVal) && constVal == 0) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x + 0 -> x" << std::endl;
}
replaceWithOptimized(inst, lhs);
return true;
}
// 0 + x = x
if (isConstantInt(lhs, constVal) && constVal == 0) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = 0 + x -> x" << std::endl;
}
replaceWithOptimized(inst, rhs);
return true;
}
// x + (-y) = x - y
if (auto rhsInst = dynamic_cast<UnaryInst*>(rhs)) {
if (rhsInst->getKind() == Instruction::kNeg) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x + (-y) -> x - y" << std::endl;
}
// 创建减法指令
builder->setPosition(inst->getParent(), inst->getParent()->findInstIterator(inst));
auto subInst = builder->createSubInst(lhs, rhsInst->getOperand());
replaceWithOptimized(inst, subInst);
return true;
}
}
return false;
}
bool GlobalStrengthReductionContext::optimizeSubtraction(BinaryInst *inst) {
Value *lhs = inst->getLhs();
Value *rhs = inst->getRhs();
int constVal;
// x - 0 = x
if (isConstantInt(rhs, constVal) && constVal == 0) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x - 0 -> x" << std::endl;
}
replaceWithOptimized(inst, lhs);
return true;
}
// x - x = 0 (如果x没有副作用)
if (lhs == rhs && hasOnlyLocalUses(dynamic_cast<Instruction*>(lhs))) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x - x -> 0" << std::endl;
}
replaceWithOptimized(inst, getConstantInt(0));
return true;
}
// x - (-y) = x + y
if (auto rhsInst = dynamic_cast<UnaryInst*>(rhs)) {
if (rhsInst->getKind() == Instruction::kNeg) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x - (-y) -> x + y" << std::endl;
}
builder->setPosition(inst->getParent(), inst->getParent()->findInstIterator(inst));
auto addInst = builder->createAddInst(lhs, rhsInst->getOperand());
replaceWithOptimized(inst, addInst);
return true;
}
}
return false;
}
bool GlobalStrengthReductionContext::optimizeMultiplication(BinaryInst *inst) {
Value *lhs = inst->getLhs();
Value *rhs = inst->getRhs();
int constVal;
// x * 0 = 0
if (isConstantInt(rhs, constVal) && constVal == 0) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x * 0 -> 0" << std::endl;
}
replaceWithOptimized(inst, getConstantInt(0));
return true;
}
// 0 * x = 0
if (isConstantInt(lhs, constVal) && constVal == 0) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = 0 * x -> 0" << std::endl;
}
replaceWithOptimized(inst, getConstantInt(0));
return true;
}
// x * 1 = x
if (isConstantInt(rhs, constVal) && constVal == 1) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x * 1 -> x" << std::endl;
}
replaceWithOptimized(inst, lhs);
return true;
}
// 1 * x = x
if (isConstantInt(lhs, constVal) && constVal == 1) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = 1 * x -> x" << std::endl;
}
replaceWithOptimized(inst, rhs);
return true;
}
// x * (-1) = -x
if (isConstantInt(rhs, constVal) && constVal == -1) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x * (-1) -> -x" << std::endl;
}
builder->setPosition(inst->getParent(), inst->getParent()->findInstIterator(inst));
auto negInst = builder->createNegInst(lhs);
replaceWithOptimized(inst, negInst);
return true;
}
return false;
}
bool GlobalStrengthReductionContext::optimizeDivision(BinaryInst *inst) {
Value *lhs = inst->getLhs();
Value *rhs = inst->getRhs();
int constVal;
// x / 1 = x
if (isConstantInt(rhs, constVal) && constVal == 1) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x / 1 -> x" << std::endl;
}
replaceWithOptimized(inst, lhs);
return true;
}
// x / (-1) = -x
if (isConstantInt(rhs, constVal) && constVal == -1) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x / (-1) -> -x" << std::endl;
}
builder->setPosition(inst->getParent(), inst->getParent()->findInstIterator(inst));
auto negInst = builder->createNegInst(lhs);
replaceWithOptimized(inst, negInst);
return true;
}
// x / x = 1 (如果x != 0且没有副作用)
if (lhs == rhs && hasOnlyLocalUses(dynamic_cast<Instruction*>(lhs))) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x / x -> 1" << std::endl;
}
replaceWithOptimized(inst, getConstantInt(1));
return true;
}
return false;
}
bool GlobalStrengthReductionContext::optimizeComparison(BinaryInst *inst) {
Value *lhs = inst->getLhs();
Value *rhs = inst->getRhs();
// x == x = true (如果x没有副作用)
if (inst->getKind() == Instruction::kICmpEQ && lhs == rhs &&
hasOnlyLocalUses(dynamic_cast<Instruction*>(lhs))) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x == x -> true" << std::endl;
}
replaceWithOptimized(inst, getConstantInt(1));
return true;
}
// x != x = false (如果x没有副作用)
if (inst->getKind() == Instruction::kICmpNE && lhs == rhs &&
hasOnlyLocalUses(dynamic_cast<Instruction*>(lhs))) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x != x -> false" << std::endl;
}
replaceWithOptimized(inst, getConstantInt(0));
return true;
}
return false;
}
bool GlobalStrengthReductionContext::optimizeLogical(BinaryInst *inst) {
Value *lhs = inst->getLhs();
Value *rhs = inst->getRhs();
int constVal;
if (inst->getKind() == Instruction::kAnd) {
// x && 0 = 0
if (isConstantInt(rhs, constVal) && constVal == 0) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x && 0 -> 0" << std::endl;
}
replaceWithOptimized(inst, getConstantInt(0));
return true;
}
// x && -1 = x
if (isConstantInt(rhs, constVal) && constVal == -1) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x && 1 -> x" << std::endl;
}
replaceWithOptimized(inst, lhs);
return true;
}
// x && x = x
if (lhs == rhs) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x && x -> x" << std::endl;
}
replaceWithOptimized(inst, lhs);
return true;
}
} else if (inst->getKind() == Instruction::kOr) {
// x || 0 = x
if (isConstantInt(rhs, constVal) && constVal == 0) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x || 0 -> x" << std::endl;
}
replaceWithOptimized(inst, lhs);
return true;
}
// x || x = x
if (lhs == rhs) {
if (DEBUG) {
std::cout << " Algebraic: " << inst->getName() << " = x || x -> x" << std::endl;
}
replaceWithOptimized(inst, lhs);
return true;
}
}
return false;
}
// ======================================================================
// 强度削弱方法
// ======================================================================
bool GlobalStrengthReductionContext::tryStrengthReduction(Instruction *inst) {
if (auto binary = dynamic_cast<BinaryInst*>(inst)) {
switch (binary->getKind()) {
case Instruction::kMul:
return reduceMultiplication(binary);
case Instruction::kDiv:
return reduceDivision(binary);
default:
return false;
}
} else if (auto call = dynamic_cast<CallInst*>(inst)) {
return reducePower(call);
}
return false;
}
bool GlobalStrengthReductionContext::reduceMultiplication(BinaryInst *inst) {
Value *lhs = inst->getLhs();
Value *rhs = inst->getRhs();
int constVal;
// 尝试右操作数为常数
Value* variable = lhs;
if (isConstantInt(rhs, constVal) && constVal > 0) {
return tryComplexMultiplication(inst, variable, constVal);
}
// 尝试左操作数为常数
if (isConstantInt(lhs, constVal) && constVal > 0) {
variable = rhs;
return tryComplexMultiplication(inst, variable, constVal);
}
return false;
}
bool GlobalStrengthReductionContext::tryComplexMultiplication(BinaryInst* inst, Value* variable, int constant) {
// 首先检查是否为2的幂使用简单位移
if (isPowerOfTwo(constant)) {
int shiftAmount = log2OfPowerOfTwo(constant);
if (DEBUG) {
std::cout << " StrengthReduction: " << inst->getName()
<< " = x * " << constant << " -> x << " << shiftAmount << std::endl;
}
builder->setPosition(inst->getParent(), inst->getParent()->findInstIterator(inst));
auto shiftInst = builder->createBinaryInst(Instruction::kSll, Type::getIntType(), variable, getConstantInt(shiftAmount));
replaceWithOptimized(inst, shiftInst);
return true;
}
// 尝试分解为位移和加法的组合
std::vector<int> shifts;
if (findOptimalShiftDecomposition(constant, shifts)) {
if (DEBUG) {
std::cout << " StrengthReduction: " << inst->getName()
<< " = x * " << constant << " -> shift decomposition with " << shifts.size() << " terms" << std::endl;
}
Value* result = createShiftDecomposition(inst, variable, shifts);
if (result) {
replaceWithOptimized(inst, result);
return true;
}
}
return false;
}
bool GlobalStrengthReductionContext::findOptimalShiftDecomposition(int constant, std::vector<int>& shifts) {
shifts.clear();
// 常见的有效分解模式
switch (constant) {
case 3: // 3 = 2^1 + 2^0 -> (x << 1) + x
shifts = {1, 0};
return true;
case 5: // 5 = 2^2 + 2^0 -> (x << 2) + x
shifts = {2, 0};
return true;
case 6: // 6 = 2^2 + 2^1 -> (x << 2) + (x << 1)
shifts = {2, 1};
return true;
case 7: // 7 = 2^2 + 2^1 + 2^0 -> (x << 2) + (x << 1) + x
shifts = {2, 1, 0};
return true;
case 9: // 9 = 2^3 + 2^0 -> (x << 3) + x
shifts = {3, 0};
return true;
case 10: // 10 = 2^3 + 2^1 -> (x << 3) + (x << 1)
shifts = {3, 1};
return true;
case 11: // 11 = 2^3 + 2^1 + 2^0 -> (x << 3) + (x << 1) + x
shifts = {3, 1, 0};
return true;
case 12: // 12 = 2^3 + 2^2 -> (x << 3) + (x << 2)
shifts = {3, 2};
return true;
case 13: // 13 = 2^3 + 2^2 + 2^0 -> (x << 3) + (x << 2) + x
shifts = {3, 2, 0};
return true;
case 14: // 14 = 2^3 + 2^2 + 2^1 -> (x << 3) + (x << 2) + (x << 1)
shifts = {3, 2, 1};
return true;
case 15: // 15 = 2^3 + 2^2 + 2^1 + 2^0 -> (x << 3) + (x << 2) + (x << 1) + x
shifts = {3, 2, 1, 0};
return true;
case 17: // 17 = 2^4 + 2^0 -> (x << 4) + x
shifts = {4, 0};
return true;
case 18: // 18 = 2^4 + 2^1 -> (x << 4) + (x << 1)
shifts = {4, 1};
return true;
case 20: // 20 = 2^4 + 2^2 -> (x << 4) + (x << 2)
shifts = {4, 2};
return true;
case 24: // 24 = 2^4 + 2^3 -> (x << 4) + (x << 3)
shifts = {4, 3};
return true;
case 25: // 25 = 2^4 + 2^3 + 2^0 -> (x << 4) + (x << 3) + x
shifts = {4, 3, 0};
return true;
case 100: // 100 = 2^6 + 2^5 + 2^2 -> (x << 6) + (x << 5) + (x << 2)
shifts = {6, 5, 2};
return true;
}
// 通用二进制分解最多4个项避免过度复杂化
if (constant > 0 && constant < 256) {
std::vector<int> binaryShifts;
int temp = constant;
int bit = 0;
while (temp > 0 && binaryShifts.size() < 4) {
if (temp & 1) {
binaryShifts.push_back(bit);
}
temp >>= 1;
bit++;
}
// 只有当项数不超过3个时才使用二进制分解比直接乘法更有效
if (binaryShifts.size() <= 3 && binaryShifts.size() >= 2) {
shifts = binaryShifts;
return true;
}
}
return false;
}
Value* GlobalStrengthReductionContext::createShiftDecomposition(BinaryInst* inst, Value* variable, const std::vector<int>& shifts) {
if (shifts.empty()) return nullptr;
builder->setPosition(inst->getParent(), inst->getParent()->findInstIterator(inst));
Value* result = nullptr;
for (int shift : shifts) {
Value* term;
if (shift == 0) {
// 0位移就是原变量
term = variable;
} else {
// 创建位移指令
term = builder->createBinaryInst(Instruction::kSll, Type::getIntType(), variable, getConstantInt(shift));
}
if (result == nullptr) {
result = term;
} else {
// 累加到结果中
result = builder->createAddInst(result, term);
}
}
return result;
}
bool GlobalStrengthReductionContext::reduceDivision(BinaryInst *inst) {
Value *lhs = inst->getLhs();
Value *rhs = inst->getRhs();
uint32_t constVal;
// x / 2^n = x >> n (对于无符号除法或已知为正数的情况)
if (isConstantInt(rhs, constVal) && constVal > 0 && isPowerOfTwo(constVal)) {
builder->setPosition(inst->getParent(), inst->getParent()->findInstIterator(inst));
int shiftAmount = log2OfPowerOfTwo(constVal);
// 有符号除法校正:(x + (x >> 31) & mask) >> k
int maskValue = constVal - 1;
// x >> 31 (算术右移获取符号位)
Value* signShift = ConstantInteger::get(31);
Value* signBits = builder->createBinaryInst(
Instruction::Kind::kSra, // 算术右移
lhs->getType(),
lhs,
signShift
);
// (x >> 31) & mask
Value* mask = ConstantInteger::get(maskValue);
Value* correction = builder->createBinaryInst(
Instruction::Kind::kAnd,
lhs->getType(),
signBits,
mask
);
// x + correction
Value* corrected = builder->createAddInst(lhs, correction);
// (x + correction) >> k
Value* divShift = ConstantInteger::get(shiftAmount);
Value* shiftInst = builder->createBinaryInst(
Instruction::Kind::kSra, // 算术右移
lhs->getType(),
corrected,
divShift
);
if (DEBUG) {
std::cout << " StrengthReduction: " << inst->getName()
<< " = x / " << constVal << " -> (x + (x >> 31) & mask) >> " << shiftAmount << std::endl;
}
// builder->setPosition(inst->getParent(), inst->getParent()->findInstIterator(inst));
// Value* divisor_minus_1 = ConstantInteger::get(constVal - 1);
// Value* adjusted = builder->createAddInst(lhs, divisor_minus_1);
// Value* shiftInst = builder->createBinaryInst(Instruction::kSra, Type::getIntType(), adjusted, getConstantInt(shiftAmount));
replaceWithOptimized(inst, shiftInst);
strengthReductionCount++;
return true;
}
// x / c = x * magic_number (魔数乘法优化 - 使用libdivide算法)
if (isConstantInt(rhs, constVal) && constVal > 1 && constVal != (uint32_t)(-1)) {
// auto magicPair = computeMulhMagicNumbers(static_cast<int>(constVal));
Value* magicResult = createMagicDivisionLibdivide(inst, static_cast<int>(constVal));
replaceWithOptimized(inst, magicResult);
divisionOptCount++;
return true;
}
return false;
}
bool GlobalStrengthReductionContext::reducePower(CallInst *inst) {
// 检查是否是pow函数调用
Function* callee = inst->getCallee();
if (!callee || callee->getName() != "pow") {
return false;
}
// pow(x, 2) = x * x
if (inst->getNumOperands() >= 2) {
int exponent;
if (isConstantInt(inst->getOperand(1), exponent)) {
if (exponent == 2) {
if (DEBUG) {
std::cout << " StrengthReduction: pow(x, 2) -> x * x" << std::endl;
}
Value* base = inst->getOperand(0);
builder->setPosition(inst->getParent(), inst->getParent()->findInstIterator(inst));
auto mulInst = builder->createMulInst(base, base);
replaceWithOptimized(inst, mulInst);
strengthReductionCount++;
return true;
} else if (exponent >= 3 && exponent <= 8) {
// 对于小的指数,展开为连续乘法
if (DEBUG) {
std::cout << " StrengthReduction: pow(x, " << exponent << ") -> repeated multiplication" << std::endl;
}
Value* base = inst->getOperand(0);
Value* result = base;
builder->setPosition(inst->getParent(), inst->getParent()->findInstIterator(inst));
for (int i = 1; i < exponent; i++) {
result = builder->createMulInst(result, base);
}
replaceWithOptimized(inst, result);
strengthReductionCount++;
return true;
}
}
}
return false;
}
Value* GlobalStrengthReductionContext::createMagicDivisionLibdivide(BinaryInst* divInst, int divisor) {
builder->setPosition(divInst->getParent(), divInst->getParent()->findInstIterator(divInst));
// 使用mulh指令优化任意常数除法
auto [magic, shift] = SysYIROptUtils::computeMulhMagicNumbers(divisor);
// 检查是否无法优化magic == -1, shift == -1 表示失败)
if (magic == -1 && shift == -1) {
if (DEBUG) {
std::cout << "[SR] Cannot optimize division by " << divisor
<< ", keeping original division" << std::endl;
}
// 返回 nullptr 表示无法优化,调用方应该保持原始除法
return nullptr;
}
// 2的幂次方除法可以用移位优化但这不是魔数法的情况这种情况应该不会被分类到这里但是还是做一个保护措施
if ((divisor & (divisor - 1)) == 0 && divisor > 0) {
// 是2的幂次方可以用移位
int shift_amount = 0;
int temp = divisor;
while (temp > 1) {
temp >>= 1;
shift_amount++;
}
Value* shiftConstant = ConstantInteger::get(shift_amount);
// 对于有符号除法,需要先加上除数-1然后再移位为了正确处理负数舍入
Value* divisor_minus_1 = ConstantInteger::get(divisor - 1);
Value* adjusted = builder->createAddInst(divInst->getOperand(0), divisor_minus_1);
return builder->createBinaryInst(
Instruction::Kind::kSra, // 算术右移
divInst->getOperand(0)->getType(),
adjusted,
shiftConstant
);
}
// 创建魔数常量
// 检查魔数是否能放入32位如果不能则不进行优化
if (magic > INT32_MAX || magic < INT32_MIN) {
if (DEBUG) {
std::cout << "[SR] Magic number " << magic << " exceeds 32-bit range, skipping optimization" << std::endl;
}
return nullptr; // 无法优化,保持原始除法
}
Value* magicConstant = ConstantInteger::get((int32_t)magic);
// 检查是否需要ADD_MARKER处理加法调整
bool needAdd = (shift & 0x40) != 0;
int actualShift = shift & 0x3F; // 提取真实的移位量
if (DEBUG) {
std::cout << "[SR] IR Generation: magic=" << magic << ", needAdd=" << needAdd
<< ", actualShift=" << actualShift << std::endl;
}
// 执行高位乘法mulh(x, magic)
Value* mulhResult = builder->createBinaryInst(
Instruction::Kind::kMulh, // 高位乘法
divInst->getOperand(0)->getType(),
divInst->getOperand(0),
magicConstant
);
if (needAdd) {
// ADD_MARKER 情况:需要在移位前加上被除数
// 这对应于 libdivide 的加法调整算法
if (DEBUG) {
std::cout << "[SR] Applying ADD_MARKER: adding dividend before shift" << std::endl;
}
mulhResult = builder->createAddInst(mulhResult, divInst->getOperand(0));
}
if (actualShift > 0) {
// 如果需要额外移位
Value* shiftConstant = ConstantInteger::get(actualShift);
mulhResult = builder->createBinaryInst(
Instruction::Kind::kSra, // 算术右移
divInst->getOperand(0)->getType(),
mulhResult,
shiftConstant
);
}
// 标准的有符号除法符号修正如果被除数为负商需要加1
// 这对所有有符号除法都需要,不管是否可能有负数
Value* isNegative = builder->createICmpLTInst(divInst->getOperand(0), ConstantInteger::get(0));
// 将i1转换为i32负数时为1非负数时为0 ICmpLTInst的结果会默认转化为32位
mulhResult = builder->createAddInst(mulhResult, isNegative);
return mulhResult;
}
// ======================================================================
// 辅助方法
// ======================================================================
bool GlobalStrengthReductionContext::isPowerOfTwo(uint32_t n) {
return n > 0 && (n & (n - 1)) == 0;
}
int GlobalStrengthReductionContext::log2OfPowerOfTwo(uint32_t n) {
int result = 0;
while (n > 1) {
n >>= 1;
result++;
}
return result;
}
bool GlobalStrengthReductionContext::isConstantInt(Value* val, int& constVal) {
if (auto constInt = dynamic_cast<ConstantInteger*>(val)) {
constVal = std::get<int>(constInt->getVal());
return true;
}
return false;
}
bool GlobalStrengthReductionContext::isConstantInt(Value* val, uint32_t& constVal) {
if (auto constInt = dynamic_cast<ConstantInteger*>(val)) {
int signedVal = std::get<int>(constInt->getVal());
if (signedVal >= 0) {
constVal = static_cast<uint32_t>(signedVal);
return true;
}
}
return false;
}
ConstantInteger* GlobalStrengthReductionContext::getConstantInt(int val) {
return ConstantInteger::get(val);
}
bool GlobalStrengthReductionContext::hasOnlyLocalUses(Instruction* inst) {
if (!inst) return true;
// 简单检查:如果指令没有副作用,则认为是本地的
if (sideEffectAnalysis) {
auto sideEffect = sideEffectAnalysis->getInstructionSideEffect(inst);
return sideEffect.type == SideEffectType::NO_SIDE_EFFECT;
}
// 没有副作用分析时,保守处理
return !inst->isCall() && !inst->isStore() && !inst->isLoad();
}
void GlobalStrengthReductionContext::replaceWithOptimized(Instruction* original, Value* replacement) {
if (DEBUG) {
std::cout << " Replacing " << original->getName()
<< " with " << replacement->getName() << std::endl;
}
original->replaceAllUsesWith(replacement);
// 如果替换值是新创建的指令,确保它有合适的名字
// if (auto replInst = dynamic_cast<Instruction*>(replacement)) {
// if (replInst->getName().empty()) {
// replInst->setName(original->getName() + "_opt");
// }
// }
// 删除原指令,让调用者处理
SysYIROptUtils::usedelete(original);
}
} // namespace sysy

View File

@ -0,0 +1,916 @@
#include "InductionVariableElimination.h"
#include "LoopCharacteristics.h"
#include "Loop.h"
#include "Dom.h"
#include "SideEffectAnalysis.h"
#include "AliasAnalysis.h"
#include "SysYIROptUtils.h"
#include <iostream>
#include <algorithm>
// 使用全局调试开关
extern int DEBUG;
namespace sysy {
// 定义 Pass 的唯一 ID
void *InductionVariableElimination::ID = (void *)&InductionVariableElimination::ID;
bool InductionVariableElimination::runOnFunction(Function* F, AnalysisManager& AM) {
if (F->getBasicBlocks().empty()) {
return false; // 空函数
}
if (DEBUG) {
std::cout << "Running InductionVariableElimination on function: " << F->getName() << std::endl;
}
// 创建优化上下文并运行
InductionVariableEliminationContext context;
bool modified = context.run(F, AM);
if (DEBUG) {
std::cout << "InductionVariableElimination " << (modified ? "modified" : "did not modify")
<< " function: " << F->getName() << std::endl;
}
return modified;
}
void InductionVariableElimination::getAnalysisUsage(std::set<void*>& analysisDependencies,
std::set<void*>& analysisInvalidations) const {
// 依赖的分析
analysisDependencies.insert(&LoopAnalysisPass::ID);
analysisDependencies.insert(&LoopCharacteristicsPass::ID);
analysisDependencies.insert(&DominatorTreeAnalysisPass::ID);
analysisDependencies.insert(&SysYSideEffectAnalysisPass::ID);
analysisDependencies.insert(&SysYAliasAnalysisPass::ID);
// 会使失效的分析归纳变量消除会修改IR结构
analysisInvalidations.insert(&LoopCharacteristicsPass::ID);
// 注意:支配树分析通常不会因为归纳变量消除而失效,因为我们不改变控制流
}
// ========== InductionVariableEliminationContext 实现 ==========
bool InductionVariableEliminationContext::run(Function* F, AnalysisManager& AM) {
if (DEBUG) {
std::cout << " Starting induction variable elimination analysis..." << std::endl;
}
// 获取必要的分析结果
loopAnalysis = AM.getAnalysisResult<LoopAnalysisResult, LoopAnalysisPass>(F);
if (!loopAnalysis || !loopAnalysis->hasLoops()) {
if (DEBUG) {
std::cout << " No loops found, skipping induction variable elimination" << std::endl;
}
return false;
}
loopCharacteristics = AM.getAnalysisResult<LoopCharacteristicsResult, LoopCharacteristicsPass>(F);
if (!loopCharacteristics) {
if (DEBUG) {
std::cout << " LoopCharacteristics analysis not available" << std::endl;
}
return false;
}
dominatorTree = AM.getAnalysisResult<DominatorTree, DominatorTreeAnalysisPass>(F);
if (!dominatorTree) {
if (DEBUG) {
std::cout << " DominatorTree analysis not available" << std::endl;
}
return false;
}
sideEffectAnalysis = AM.getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>();
if (!sideEffectAnalysis) {
if (DEBUG) {
std::cout << " SideEffectAnalysis not available, using conservative approach" << std::endl;
}
// 可以继续执行,但会使用更保守的策略
} else {
if (DEBUG) {
std::cout << " Using SideEffectAnalysis for safety checks" << std::endl;
}
}
aliasAnalysis = AM.getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(F);
if (!aliasAnalysis) {
if (DEBUG) {
std::cout << " AliasAnalysis not available, using conservative approach" << std::endl;
}
// 可以继续执行,但会使用更保守的策略
} else {
if (DEBUG) {
std::cout << " Using AliasAnalysis for memory safety checks" << std::endl;
}
}
// 执行三个阶段的优化
// 阶段1识别死归纳变量
identifyDeadInductionVariables(F);
if (deadIVs.empty()) {
if (DEBUG) {
std::cout << " No dead induction variables found" << std::endl;
}
return false;
}
if (DEBUG) {
std::cout << " Found " << deadIVs.size() << " potentially dead induction variables" << std::endl;
}
// 阶段2分析安全性
analyzeSafetyForElimination();
// 阶段3执行消除
bool modified = performInductionVariableElimination();
if (DEBUG) {
printDebugInfo();
}
return modified;
}
void InductionVariableEliminationContext::identifyDeadInductionVariables(Function* F) {
if (DEBUG) {
std::cout << " === Phase 1: Identifying Dead Induction Variables ===" << std::endl;
}
// 遍历所有循环
for (const auto& loop_ptr : loopAnalysis->getAllLoops()) {
Loop* loop = loop_ptr.get();
if (DEBUG) {
std::cout << " Analyzing loop: " << loop->getName() << std::endl;
}
// 获取循环特征
const LoopCharacteristics* characteristics = loopCharacteristics->getCharacteristics(loop);
if (!characteristics) {
if (DEBUG) {
std::cout << " No characteristics available for loop" << std::endl;
}
continue;
}
if (characteristics->InductionVars.empty()) {
if (DEBUG) {
std::cout << " No induction variables found in loop" << std::endl;
}
continue;
}
// 检查每个归纳变量是否为死归纳变量
for (const auto& iv : characteristics->InductionVars) {
auto deadIV = isDeadInductionVariable(iv.get(), loop);
if (deadIV) {
if (DEBUG) {
std::cout << " Found potential dead IV: %" << deadIV->phiInst->getName() << std::endl;
}
// 添加到候选项列表
loopToDeadIVs[loop].push_back(deadIV.get());
deadIVs.push_back(std::move(deadIV));
}
}
}
if (DEBUG) {
std::cout << " === End Phase 1: Found " << deadIVs.size() << " candidates ===" << std::endl;
}
}
std::unique_ptr<DeadInductionVariable>
InductionVariableEliminationContext::isDeadInductionVariable(const InductionVarInfo* iv, Loop* loop) {
// 获取 phi 指令
auto* phiInst = dynamic_cast<PhiInst*>(iv->div);
if (!phiInst) {
return nullptr; // 不是 phi 指令
}
// 新的逻辑递归分析整个use-def链判断是否有真实的使用
if (!isPhiInstructionDeadRecursively(phiInst, loop)) {
return nullptr; // 有真实的使用,不能删除
}
// 创建死归纳变量信息
auto deadIV = std::make_unique<DeadInductionVariable>(phiInst, loop);
deadIV->relatedInsts = collectRelatedInstructions(phiInst, loop);
return deadIV;
}
// 递归分析phi指令及其使用链是否都是死代码
bool InductionVariableEliminationContext::isPhiInstructionDeadRecursively(PhiInst* phiInst, Loop* loop) {
if (DEBUG) {
std::cout << " 递归分析归纳变量 " << phiInst->getName() << " 的完整使用链" << std::endl;
}
// 使用访问集合避免无限递归
std::set<Instruction*> visitedInstructions;
std::set<Instruction*> currentPath; // 用于检测循环依赖
// 核心逻辑:递归分析使用链,寻找任何"逃逸点"
return isInstructionUseChainDeadRecursively(phiInst, loop, visitedInstructions, currentPath);
}
// 递归分析指令的使用链是否都是死代码
bool InductionVariableEliminationContext::isInstructionUseChainDeadRecursively(
Instruction* inst, Loop* loop,
std::set<Instruction*>& visited,
std::set<Instruction*>& currentPath) {
if (DEBUG && visited.size() < 10) { // 限制debug输出
std::cout << " 分析指令 " << inst->getName() << " (" << inst->getKindString() << ")" << std::endl;
}
// 避免无限递归
if (currentPath.count(inst) > 0) {
// 发现循环依赖,这在归纳变量中是正常的,继续分析其他路径
if (DEBUG && visited.size() < 10) {
std::cout << " 发现循环依赖,继续分析其他路径" << std::endl;
}
return true; // 循环依赖本身不是逃逸点
}
if (visited.count(inst) > 0) {
// 已经分析过这个指令
return true; // 假设之前的分析是正确的
}
visited.insert(inst);
currentPath.insert(inst);
// 1. 检查是否有副作用(逃逸点)
if (sideEffectAnalysis && sideEffectAnalysis->hasSideEffect(inst)) {
if (DEBUG && visited.size() < 10) {
std::cout << " 指令有副作用,是逃逸点" << std::endl;
}
currentPath.erase(inst);
return false; // 有副作用的指令是逃逸点
}
// 1.5. 特殊检查:控制流指令永远不是死代码
auto instKind = inst->getKind();
if (instKind == Instruction::Kind::kCondBr ||
instKind == Instruction::Kind::kBr ||
instKind == Instruction::Kind::kReturn) {
if (DEBUG && visited.size() < 10) {
std::cout << " 控制流指令,是逃逸点" << std::endl;
}
currentPath.erase(inst);
return false; // 控制流指令是逃逸点
}
// 2. 检查指令的所有使用
bool allUsesAreDead = true;
for (auto use : inst->getUses()) {
auto user = use->getUser();
auto* userInst = dynamic_cast<Instruction*>(user);
if (!userInst) {
// 被非指令使用(如函数返回值),是逃逸点
if (DEBUG && visited.size() < 10) {
std::cout << " 被非指令使用,是逃逸点" << std::endl;
}
allUsesAreDead = false;
break;
}
// 检查使用是否在循环外(逃逸点)
if (!loop->contains(userInst->getParent())) {
if (DEBUG && visited.size() < 10) {
std::cout << " 在循环外被 " << userInst->getName() << " 使用,是逃逸点" << std::endl;
}
allUsesAreDead = false;
break;
}
// 特殊检查:如果使用者是循环的退出条件,需要进一步分析
// 对于用于退出条件的归纳变量,需要更谨慎的处理
if (isUsedInLoopExitCondition(userInst, loop)) {
// 修复逻辑:用于循环退出条件的归纳变量通常不应该被消除
// 除非整个循环都可以被证明是完全无用的(这需要更复杂的分析)
if (DEBUG && visited.size() < 10) {
std::cout << " 被用于循环退出条件,是逃逸点(避免破坏循环语义)" << std::endl;
}
allUsesAreDead = false;
break;
}
// 递归分析使用者的使用链
if (!isInstructionUseChainDeadRecursively(userInst, loop, visited, currentPath)) {
allUsesAreDead = false;
break; // 找到逃逸点,不需要继续分析
}
}
currentPath.erase(inst);
if (allUsesAreDead && DEBUG && visited.size() < 10) {
std::cout << " 指令 " << inst->getName() << " 的所有使用都是死代码" << std::endl;
}
return allUsesAreDead;
}
// 检查循环是否有副作用
bool InductionVariableEliminationContext::loopHasSideEffects(Loop* loop) {
// 遍历循环中的所有指令,检查是否有副作用
for (BasicBlock* bb : loop->getBlocks()) {
for (auto& inst : bb->getInstructions()) {
Instruction* instPtr = inst.get();
// 使用副作用分析(如果可用)
if (sideEffectAnalysis && sideEffectAnalysis->hasSideEffect(instPtr)) {
if (DEBUG) {
std::cout << " 循环中发现有副作用的指令: " << instPtr->getName() << std::endl;
}
return true;
}
// 如果没有副作用分析,使用保守的判断
if (!sideEffectAnalysis) {
auto kind = instPtr->getKind();
// 这些指令通常有副作用
if (kind == Instruction::Kind::kCall ||
kind == Instruction::Kind::kStore ||
kind == Instruction::Kind::kReturn) {
if (DEBUG) {
std::cout << " 循环中发现潜在有副作用的指令: " << instPtr->getName() << std::endl;
}
return true;
}
}
}
}
// 重要修复:检查是否为嵌套循环的外层循环
// 如果当前循环包含其他循环,那么它有潜在的副作用
for (const auto& loop_ptr : loopAnalysis->getAllLoops()) {
Loop* otherLoop = loop_ptr.get();
if(loopAnalysis->getLowestCommonAncestor(otherLoop, loop) == loop) {
if (DEBUG) {
std::cout << " 循环 " << loop->getName() << " 是其他循环的外层循环,视为有副作用" << std::endl;
}
return true; // 外层循环被视为有副作用
}
// if (otherLoop != loop && loop->contains(otherLoop->getHeader())) {
// if (DEBUG) {
// std::cout << " 循环 " << loop->getName() << " 包含子循环 " << otherLoop->getName() << ",视为有副作用" << std::endl;
// }
// return true; // 包含子循环的外层循环被视为有副作用
// }
}
if (DEBUG) {
std::cout << " 循环 " << loop->getName() << " 无副作用" << std::endl;
}
return false; // 循环无副作用
}
// 检查指令是否被用于循环退出条件
bool InductionVariableEliminationContext::isUsedInLoopExitCondition(Instruction* inst, Loop* loop) {
// 检查指令是否被循环的退出条件使用
for (BasicBlock* exitingBB : loop->getExitingBlocks()) {
auto terminatorIt = exitingBB->terminator();
if (terminatorIt != exitingBB->end()) {
Instruction* terminator = terminatorIt->get();
if (terminator) {
// 检查终结指令的操作数
for (size_t i = 0; i < terminator->getNumOperands(); ++i) {
if (terminator->getOperand(i) == inst) {
if (DEBUG) {
std::cout << " 指令 " << inst->getName() << " 用于循环退出条件" << std::endl;
}
return true;
}
}
// 对于条件分支,还需要检查条件指令的操作数
if (terminator->getKind() == Instruction::Kind::kCondBr) {
auto* condBr = dynamic_cast<CondBrInst*>(terminator);
if (condBr) {
Value* condition = condBr->getCondition();
if (condition == inst) {
if (DEBUG) {
std::cout << " 指令 " << inst->getName() << " 是循环条件" << std::endl;
}
return true;
}
// 递归检查条件指令的操作数(比如比较指令)
auto* condInst = dynamic_cast<Instruction*>(condition);
if (condInst) {
for (size_t i = 0; i < condInst->getNumOperands(); ++i) {
if (condInst->getOperand(i) == inst) {
if (DEBUG) {
std::cout << " 指令 " << inst->getName() << " 用于循环条件的操作数" << std::endl;
}
return true;
}
}
}
}
}
}
}
}
return false;
}
// 检查指令的结果是否未被有效使用
bool InductionVariableEliminationContext::isInstructionResultUnused(Instruction* inst, Loop* loop) {
// 检查指令的所有使用
if (inst->getUses().empty()) {
return true; // 没有使用,肯定是未使用
}
for (auto use : inst->getUses()) {
auto user = use->getUser();
auto* userInst = dynamic_cast<Instruction*>(user);
if (!userInst) {
return false; // 被非指令使用,认为是有效使用
}
// 如果在循环外被使用,认为是有效使用
if (!loop->contains(userInst->getParent())) {
return false;
}
// 递归检查使用这个结果的指令是否也是死代码
// 为了避免无限递归,限制递归深度
if (!isInstructionEffectivelyDead(userInst, loop, 3)) {
return false; // 存在有效使用
}
}
return true; // 所有使用都是无效的
}
// 检查store指令是否存储到死地址利用别名分析
bool InductionVariableEliminationContext::isStoreToDeadLocation(StoreInst* store, Loop* loop) {
if (!aliasAnalysis) {
return false; // 没有别名分析保守返回false
}
Value* storePtr = store->getPointer();
// 检查是否存储到局部临时变量且该变量在循环外不被读取
const MemoryLocation* memLoc = aliasAnalysis->getMemoryLocation(storePtr);
if (!memLoc) {
return false; // 无法确定内存位置
}
// 如果是局部数组且只在循环内被访问
if (memLoc->isLocalArray) {
// 检查该内存位置是否在循环外被读取
for (auto* accessInst : memLoc->accessInsts) {
if (accessInst->getKind() == Instruction::Kind::kLoad) {
if (!loop->contains(accessInst->getParent())) {
return false; // 在循环外被读取,不是死存储
}
}
}
if (DEBUG) {
std::cout << " 存储到局部数组且仅在循环内访问" << std::endl;
}
return true; // 存储到仅循环内访问的局部数组
}
return false;
}
// 检查指令是否有效死代码(带递归深度限制)
bool InductionVariableEliminationContext::isInstructionEffectivelyDead(Instruction* inst, Loop* loop, int maxDepth) {
if (maxDepth <= 0) {
return false; // 达到递归深度限制保守返回false
}
// 利用副作用分析
if (sideEffectAnalysis && sideEffectAnalysis->hasSideEffect(inst)) {
return false; // 有副作用的指令不是死代码
}
// 检查特殊指令类型
switch (inst->getKind()) {
case Instruction::Kind::kStore:
// Store指令可能是死存储
return isStoreToDeadLocation(dynamic_cast<StoreInst*>(inst), loop);
case Instruction::Kind::kCall:
// 函数调用通常有副作用
if (sideEffectAnalysis) {
return !sideEffectAnalysis->hasSideEffect(inst);
}
return false; // 保守地认为函数调用有效果
case Instruction::Kind::kReturn:
case Instruction::Kind::kBr:
case Instruction::Kind::kCondBr:
// 控制流指令不是死代码
return false;
default:
// 其他指令检查其使用是否有效
break;
}
// 检查指令的使用
if (inst->getUses().empty()) {
return true; // 没有使用的纯指令是死代码
}
// 递归检查所有使用
for (auto use : inst->getUses()) {
auto user = use->getUser();
auto* userInst = dynamic_cast<Instruction*>(user);
if (!userInst) {
return false; // 被非指令使用
}
if (!loop->contains(userInst->getParent())) {
return false; // 在循环外被使用
}
// 递归检查使用者
if (!isInstructionEffectivelyDead(userInst, loop, maxDepth - 1)) {
return false; // 存在有效使用
}
}
return true; // 所有使用都是死代码
}
// 原有的函数保持兼容,但现在使用增强的死代码分析
bool InductionVariableEliminationContext::isInstructionDeadOrInternalOnly(Instruction* inst, Loop* loop) {
return isInstructionEffectivelyDead(inst, loop, 5);
}
// 检查store指令是否有后续的load操作
bool InductionVariableEliminationContext::hasSubsequentLoad(StoreInst* store, Loop* loop) {
if (!aliasAnalysis) {
// 没有别名分析,保守地假设有后续读取
return true;
}
Value* storePtr = store->getPointer();
const MemoryLocation* storeLoc = aliasAnalysis->getMemoryLocation(storePtr);
if (!storeLoc) {
// 无法确定内存位置,保守处理
return true;
}
// 在循环中和循环后查找对同一位置的load操作
std::vector<BasicBlock*> blocksToCheck;
// 添加循环内的所有基本块
for (auto* bb : loop->getBlocks()) {
blocksToCheck.push_back(bb);
}
// 添加循环的退出块
auto exitBlocks = loop->getExitBlocks();
for (auto* exitBB : exitBlocks) {
blocksToCheck.push_back(exitBB);
}
// 搜索load操作
for (auto* bb : blocksToCheck) {
for (auto& inst : bb->getInstructions()) {
if (inst->getKind() == Instruction::Kind::kLoad) {
LoadInst* loadInst = static_cast<LoadInst*>(inst.get());
Value* loadPtr = loadInst->getPointer();
const MemoryLocation* loadLoc = aliasAnalysis->getMemoryLocation(loadPtr);
if (loadLoc && aliasAnalysis->queryAlias(storePtr, loadPtr) != AliasType::NO_ALIAS) {
// 找到可能读取同一位置的load操作
if (DEBUG) {
std::cout << " 找到后续load操作: " << loadInst->getName() << std::endl;
}
return true;
}
}
}
}
// 检查是否通过函数调用间接访问
for (auto* bb : blocksToCheck) {
for (auto& inst : bb->getInstructions()) {
if (inst->getKind() == Instruction::Kind::kCall) {
CallInst* callInst = static_cast<CallInst*>(inst.get());
if (callInst && sideEffectAnalysis && sideEffectAnalysis->hasSideEffect(callInst)) {
// 函数调用可能间接读取内存
if (DEBUG) {
std::cout << " 函数调用可能读取内存: " << callInst->getName() << std::endl;
}
return true;
}
}
}
}
if (DEBUG) {
std::cout << " 未找到后续load操作" << std::endl;
}
return false; // 没有找到后续读取
}
// 检查指令是否在循环外有使用
bool InductionVariableEliminationContext::hasUsageOutsideLoop(Instruction* inst, Loop* loop) {
for (auto use : inst->getUses()) {
auto user = use->getUser();
auto* userInst = dynamic_cast<Instruction*>(user);
if (!userInst) {
// 被非指令使用,可能在循环外
return true;
}
if (!loop->contains(userInst->getParent())) {
// 在循环外被使用
if (DEBUG) {
std::cout << " 指令 " << inst->getName() << " 在循环外被 "
<< userInst->getName() << " 使用" << std::endl;
}
return true;
}
}
return false; // 没有循环外使用
}
// 检查store指令是否在循环外有后续的load操作
bool InductionVariableEliminationContext::hasSubsequentLoadOutsideLoop(StoreInst* store, Loop* loop) {
if (!aliasAnalysis) {
// 没有别名分析,保守地假设有后续读取
return true;
}
Value* storePtr = store->getPointer();
// 检查循环的退出块及其后继
auto exitBlocks = loop->getExitBlocks();
std::set<BasicBlock*> visitedBlocks;
for (auto* exitBB : exitBlocks) {
if (hasLoadInSubtree(exitBB, storePtr, visitedBlocks)) {
if (DEBUG) {
std::cout << " 找到循环外的后续load操作" << std::endl;
}
return true;
}
}
return false; // 没有找到循环外的后续读取
}
// 递归检查基本块子树中是否有对指定位置的load操作
bool InductionVariableEliminationContext::hasLoadInSubtree(BasicBlock* bb, Value* ptr, std::set<BasicBlock*>& visited) {
if (visited.count(bb) > 0) {
return false; // 已经访问过,避免无限循环
}
visited.insert(bb);
// 检查当前基本块中的指令
for (auto& inst : bb->getInstructions()) {
if (inst->getKind() == Instruction::Kind::kLoad) {
LoadInst* loadInst = static_cast<LoadInst*>(inst.get());
if (aliasAnalysis && aliasAnalysis->queryAlias(ptr, loadInst->getPointer()) != AliasType::NO_ALIAS) {
return true; // 找到了对相同或别名位置的load
}
} else if (inst->getKind() == Instruction::Kind::kCall) {
// 函数调用可能间接读取内存
CallInst* callInst = static_cast<CallInst*>(inst.get());
if (sideEffectAnalysis && sideEffectAnalysis->hasSideEffect(callInst)) {
return true; // 保守地认为函数调用可能读取内存
}
}
}
// 递归检查后继基本块(限制深度以避免过度搜索)
static int searchDepth = 0;
if (searchDepth < 10) { // 限制搜索深度
searchDepth++;
for (auto* succ : bb->getSuccessors()) {
if (hasLoadInSubtree(succ, ptr, visited)) {
searchDepth--;
return true;
}
}
searchDepth--;
}
return false;
}
std::vector<Instruction*> InductionVariableEliminationContext::collectRelatedInstructions(
PhiInst* phiInst, Loop* loop) {
std::vector<Instruction*> relatedInsts;
// 收集所有与该归纳变量相关的指令
for (auto use : phiInst->getUses()) {
auto user = use->getUser();
auto* userInst = dynamic_cast<Instruction*>(user);
if (userInst && loop->contains(userInst->getParent())) {
relatedInsts.push_back(userInst);
}
}
return relatedInsts;
}
void InductionVariableEliminationContext::analyzeSafetyForElimination() {
if (DEBUG) {
std::cout << " === Phase 2: Analyzing Safety for Elimination ===" << std::endl;
}
// 为每个死归纳变量检查消除的安全性
for (auto& deadIV : deadIVs) {
bool isSafe = isSafeToEliminate(deadIV.get());
deadIV->canEliminate = isSafe;
if (DEBUG) {
std::cout << " Dead IV " << deadIV->phiInst->getName()
<< ": " << (isSafe ? "SAFE" : "UNSAFE") << " to eliminate" << std::endl;
}
}
if (DEBUG) {
size_t safeCount = 0;
for (const auto& deadIV : deadIVs) {
if (deadIV->canEliminate) safeCount++;
}
std::cout << " === End Phase 2: " << safeCount << " of " << deadIVs.size()
<< " variables are safe to eliminate ===" << std::endl;
}
}
bool InductionVariableEliminationContext::isSafeToEliminate(const DeadInductionVariable* deadIV) {
// 1. 确保归纳变量在循环头
if (deadIV->phiInst->getParent() != deadIV->containingLoop->getHeader()) {
if (DEBUG) {
std::cout << " Unsafe: phi not in loop header" << std::endl;
}
return false;
}
// 2. 确保相关指令都在循环内
for (auto* inst : deadIV->relatedInsts) {
if (!deadIV->containingLoop->contains(inst->getParent())) {
if (DEBUG) {
std::cout << " Unsafe: related instruction outside loop" << std::endl;
}
return false;
}
}
// 3. 确保没有副作用
for (auto* inst : deadIV->relatedInsts) {
if (sideEffectAnalysis) {
// 使用副作用分析进行精确检查
if (sideEffectAnalysis->hasSideEffect(inst)) {
if (DEBUG) {
std::cout << " Unsafe: related instruction " << inst->getName()
<< " has side effects" << std::endl;
}
return false;
}
} else {
// 没有副作用分析时使用保守策略:只允许基本算术运算
auto kind = inst->getKind();
if (kind != Instruction::Kind::kAdd &&
kind != Instruction::Kind::kSub &&
kind != Instruction::Kind::kMul) {
if (DEBUG) {
std::cout << " Unsafe: related instruction may have side effects (conservative)" << std::endl;
}
return false;
}
}
}
// 4. 确保不影响循环的退出条件
for (BasicBlock* exitingBB : deadIV->containingLoop->getExitingBlocks()) {
auto terminatorIt = exitingBB->terminator();
if (terminatorIt != exitingBB->end()) {
Instruction* terminator = terminatorIt->get();
if (terminator) {
for (size_t i = 0; i < terminator->getNumOperands(); ++i) {
if (terminator->getOperand(i) == deadIV->phiInst) {
if (DEBUG) {
std::cout << " Unsafe: phi used in loop exit condition" << std::endl;
}
return false;
}
}
}
}
}
return true;
}
bool InductionVariableEliminationContext::performInductionVariableElimination() {
if (DEBUG) {
std::cout << " === Phase 3: Performing Induction Variable Elimination ===" << std::endl;
}
bool modified = false;
for (auto& deadIV : deadIVs) {
if (!deadIV->canEliminate) {
continue;
}
if (DEBUG) {
std::cout << " Eliminating dead IV: " << deadIV->phiInst->getName() << std::endl;
}
if (eliminateDeadInductionVariable(deadIV.get())) {
if (DEBUG) {
std::cout << " Successfully eliminated: " << deadIV->phiInst->getName() << std::endl;
}
modified = true;
} else {
if (DEBUG) {
std::cout << " Failed to eliminate: " << deadIV->phiInst->getName() << std::endl;
}
}
}
if (DEBUG) {
std::cout << " === End Phase 3: " << (modified ? "Eliminations performed" : "No eliminations") << " ===" << std::endl;
}
return modified;
}
bool InductionVariableEliminationContext::eliminateDeadInductionVariable(DeadInductionVariable* deadIV) {
// 1. 删除所有相关指令
for (auto* inst : deadIV->relatedInsts) {
auto* bb = inst->getParent();
auto it = bb->findInstIterator(inst);
if (it != bb->end()) {
SysYIROptUtils::usedelete(it);
// bb->getInstructions().erase(it);
if (DEBUG) {
std::cout << " Removed related instruction: " << inst->getName() << std::endl;
}
}
}
// 2. 删除 phi 指令
auto* bb = deadIV->phiInst->getParent();
auto it = bb->findInstIterator(deadIV->phiInst);
if (it != bb->end()) {
SysYIROptUtils::usedelete(it);
// bb->getInstructions().erase(it);
if (DEBUG) {
std::cout << " Removed phi instruction: " << deadIV->phiInst->getName() << std::endl;
}
return true;
}
return false;
}
void InductionVariableEliminationContext::printDebugInfo() {
if (!DEBUG) return;
std::cout << "\n=== Induction Variable Elimination Summary ===" << std::endl;
std::cout << "Total dead IVs found: " << deadIVs.size() << std::endl;
size_t eliminatedCount = 0;
for (auto& [loop, loopDeadIVs] : loopToDeadIVs) {
size_t loopEliminatedCount = 0;
for (auto* deadIV : loopDeadIVs) {
if (deadIV->canEliminate) {
loopEliminatedCount++;
eliminatedCount++;
}
}
if (loopEliminatedCount > 0) {
std::cout << "Loop " << loop->getName() << ": " << loopEliminatedCount
<< " of " << loopDeadIVs.size() << " IVs eliminated" << std::endl;
}
}
std::cout << "Total eliminated: " << eliminatedCount << " of " << deadIVs.size() << std::endl;
std::cout << "=============================================" << std::endl;
}
} // namespace sysy

View File

@ -0,0 +1,264 @@
#include "LICM.h"
#include "IR.h"
extern int DEBUG;
namespace sysy {
void *LICM::ID = (void *)&LICM::ID;
bool LICMContext::run() { return hoistInstructions(); }
bool LICMContext::hoistInstructions() {
bool changed = false;
BasicBlock *preheader = loop->getPreHeader();
if (!preheader || !chars)
return false;
// 1. 先收集所有可外提指令
std::unordered_set<Instruction *> workSet(chars->invariantInsts.begin(), chars->invariantInsts.end());
if (DEBUG) {
std::cout << "LICM: Found " << workSet.size() << " candidate invariant instructions to hoist:" << std::endl;
for (auto *inst : workSet) {
std::cout << " - " << inst->getName() << " (kind: " << static_cast<int>(inst->getKind())
<< ", in BB: " << inst->getParent()->getName() << ")" << std::endl;
}
}
// 2. 计算每个指令被依赖的次数(入度)
std::unordered_map<Instruction *, int> indegree;
std::unordered_map<Instruction *, std::vector<Instruction *>> dependencies; // 记录依赖关系
std::unordered_map<Instruction *, std::vector<Instruction *>> dependents; // 记录被依赖关系
for (auto *inst : workSet) {
indegree[inst] = 0;
dependencies[inst] = {};
dependents[inst] = {};
}
if (DEBUG) {
std::cout << "LICM: Analyzing dependencies between invariant instructions..." << std::endl;
}
for (auto *inst : workSet) {
for (size_t i = 0; i < inst->getNumOperands(); ++i) {
if (auto *dep = dynamic_cast<Instruction *>(inst->getOperand(i))) {
if (workSet.count(dep)) {
indegree[inst]++;
dependencies[inst].push_back(dep);
dependents[dep].push_back(inst);
if (DEBUG) {
std::cout << " Dependency: " << inst->getName() << " depends on " << dep->getName() << std::endl;
}
}
}
}
}
if (DEBUG) {
std::cout << "LICM: Initial indegree analysis:" << std::endl;
for (auto &[inst, deg] : indegree) {
std::cout << " " << inst->getName() << ": indegree=" << deg;
if (deg > 0) {
std::cout << ", depends on: ";
for (auto *dep : dependencies[inst]) {
std::cout << dep->getName() << " ";
}
}
std::cout << std::endl;
}
}
// 3. Kahn拓扑排序
std::vector<Instruction *> sorted;
std::queue<Instruction *> q;
if (DEBUG) {
std::cout << "LICM: Starting topological sort..." << std::endl;
}
for (auto &[inst, deg] : indegree) {
if (deg == 0) {
q.push(inst);
if (DEBUG) {
std::cout << " Initial zero-indegree instruction: " << inst->getName() << std::endl;
}
}
}
int sortStep = 0;
while (!q.empty()) {
auto *inst = q.front();
q.pop();
sorted.push_back(inst);
if (DEBUG) {
std::cout << " Step " << (++sortStep) << ": Processing " << inst->getName() << std::endl;
}
if (DEBUG) {
std::cout << " Reducing indegree of dependents of " << inst->getName() << std::endl;
}
// 正确的拓扑排序当处理一个指令时应该减少其所有使用者dependents的入度
for (auto *dependent : dependents[inst]) {
indegree[dependent]--;
if (DEBUG) {
std::cout << " Reducing indegree of " << dependent->getName() << " to " << indegree[dependent] << std::endl;
}
if (indegree[dependent] == 0) {
q.push(dependent);
if (DEBUG) {
std::cout << " Adding " << dependent->getName() << " to queue (indegree=0)" << std::endl;
}
}
}
}
// 检查是否全部排序,若未全部排序,打印错误信息
// 这可能是因为存在循环依赖或其他问题导致无法完成拓扑排序
if (sorted.size() != workSet.size()) {
if (DEBUG) {
std::cout << "LICM: Topological sort failed! Sorted " << sorted.size()
<< " instructions out of " << workSet.size() << " total." << std::endl;
// 找出未被排序的指令(形成循环依赖的指令)
std::unordered_set<Instruction *> remaining;
for (auto *inst : workSet) {
bool found = false;
for (auto *sortedInst : sorted) {
if (inst == sortedInst) {
found = true;
break;
}
}
if (!found) {
remaining.insert(inst);
}
}
std::cout << "LICM: Instructions involved in dependency cycle:" << std::endl;
for (auto *inst : remaining) {
std::cout << " - " << inst->getName() << " (indegree=" << indegree[inst] << ")" << std::endl;
std::cout << " Dependencies within cycle: ";
for (auto *dep : dependencies[inst]) {
if (remaining.count(dep)) {
std::cout << dep->getName() << " ";
}
}
std::cout << std::endl;
std::cout << " Dependents within cycle: ";
for (auto *dependent : dependents[inst]) {
if (remaining.count(dependent)) {
std::cout << dependent->getName() << " ";
}
}
std::cout << std::endl;
}
// 尝试找出一个具体的循环路径
std::cout << "LICM: Attempting to trace a dependency cycle:" << std::endl;
if (!remaining.empty()) {
auto *start = *remaining.begin();
std::unordered_set<Instruction *> visited;
std::vector<Instruction *> path;
std::function<bool(Instruction *)> findCycle = [&](Instruction *current) -> bool {
if (visited.count(current)) {
// 找到环
auto it = std::find(path.begin(), path.end(), current);
if (it != path.end()) {
std::cout << " Cycle found: ";
for (auto cycleIt = it; cycleIt != path.end(); ++cycleIt) {
std::cout << (*cycleIt)->getName() << " -> ";
}
std::cout << current->getName() << std::endl;
return true;
}
return false;
}
visited.insert(current);
path.push_back(current);
for (auto *dep : dependencies[current]) {
if (remaining.count(dep)) {
if (findCycle(dep)) {
return true;
}
}
}
path.pop_back();
return false;
};
findCycle(start);
}
}
return false;
}
// 4. 按拓扑序外提
if (DEBUG) {
std::cout << "LICM: Successfully completed topological sort. Hoisting instructions in order:" << std::endl;
}
for (auto *inst : sorted) {
if (!inst)
continue;
BasicBlock *parent = inst->getParent();
if (parent && loop->contains(parent)) {
if (DEBUG) {
std::cout << " Hoisting " << inst->getName() << " from " << parent->getName()
<< " to preheader " << preheader->getName() << std::endl;
}
auto sourcePos = parent->findInstIterator(inst);
auto targetPos = preheader->terminator();
parent->moveInst(sourcePos, targetPos, preheader);
changed = true;
}
}
if (DEBUG && changed) {
std::cout << "LICM: Successfully hoisted " << sorted.size() << " invariant instructions" << std::endl;
}
return changed;
}
// ---- LICM Pass Implementation ----
bool LICM::runOnFunction(Function *F, AnalysisManager &AM) {
auto *loopAnalysis = AM.getAnalysisResult<LoopAnalysisResult, LoopAnalysisPass>(F);
auto *loopCharsResult = AM.getAnalysisResult<LoopCharacteristicsResult, LoopCharacteristicsPass>(F);
if (!loopAnalysis || !loopCharsResult)
return false;
bool changed = false;
// 对每个函数内的所有循环做处理
for (const auto &loop_ptr : loopAnalysis->getAllLoops()) {
Loop *loop = loop_ptr.get();
if (DEBUG) {
std::cout << "LICM: Processing loop in function " << F->getName() << ": " << loop->getName() << std::endl;
}
const LoopCharacteristics *chars = loopCharsResult->getCharacteristics(loop);
if (!chars || !loop->getPreHeader())
continue; // 没有分析结果或没有前置块则跳过
LICMContext ctx(F, loop, builder, chars);
changed |= ctx.run();
}
return changed;
}
void LICM::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
analysisDependencies.insert(&LoopAnalysisPass::ID);
analysisDependencies.insert(&LoopCharacteristicsPass::ID);
analysisInvalidations.insert(&LoopCharacteristicsPass::ID);
analysisInvalidations.insert(&LivenessAnalysisPass::ID);
}
} // namespace sysy

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,528 @@
#include "LoopNormalization.h"
#include "Dom.h"
#include "Loop.h"
#include "SysYIROptUtils.h"
#include <iostream>
#include <algorithm>
#include <sstream>
// 使用全局调试开关
extern int DEBUG;
namespace sysy {
// 定义 Pass 的唯一 ID
void *LoopNormalizationPass::ID = (void *)&LoopNormalizationPass::ID;
bool LoopNormalizationPass::runOnFunction(Function *F, AnalysisManager &AM) {
if (F->getBasicBlocks().empty()) {
return false; // 空函数
}
if (DEBUG)
std::cout << "Running LoopNormalizationPass on function: " << F->getName() << std::endl;
// 获取并缓存所有需要的分析结果
loopAnalysis = AM.getAnalysisResult<LoopAnalysisResult, LoopAnalysisPass>(F);
if (!loopAnalysis || !loopAnalysis->hasLoops()) {
if (DEBUG)
std::cout << "No loops found in function " << F->getName() << ", skipping normalization" << std::endl;
return false; // 没有循环需要规范化
}
domTree = AM.getAnalysisResult<DominatorTree, DominatorTreeAnalysisPass>(F);
if (!domTree) {
std::cerr << "Error: DominatorTree not available for function " << F->getName() << std::endl;
return false;
}
// 重置统计信息
stats = NormalizationStats();
bool modified = false;
const auto& allLoops = loopAnalysis->getAllLoops();
stats.totalLoops = allLoops.size();
if (DEBUG) {
std::cout << "Found " << stats.totalLoops << " loops to analyze for normalization" << std::endl;
}
// 按循环深度从外到内处理,确保外层循环先规范化
std::vector<Loop*> sortedLoops;
for (const auto& loop_ptr : allLoops) {
sortedLoops.push_back(loop_ptr.get());
}
std::sort(sortedLoops.begin(), sortedLoops.end(), [](Loop* a, Loop* b) {
return a->getLoopDepth() < b->getLoopDepth(); // 按深度升序排列
});
// 逐个规范化循环
for (Loop* loop : sortedLoops) {
if (needsPreheader(loop)) {
stats.loopsNeedingPreheader++;
if (DEBUG) {
std::cout << " Loop " << loop->getName() << " needs preheader (depth="
<< loop->getLoopDepth() << ")" << std::endl;
}
if (normalizeLoop(loop)) {
modified = true;
stats.loopsNormalized++;
// 验证规范化结果
if (!validateNormalization(loop)) {
std::cerr << "Warning: Loop normalization validation failed for loop "
<< loop->getName() << std::endl;
}
}
} else {
if (DEBUG) {
auto* preheader = getExistingPreheader(loop);
if (preheader) {
std::cout << " Loop " << loop->getName() << " already has preheader: "
<< preheader->getName() << std::endl;
}
}
}
}
if (DEBUG && modified) {
printStats(F);
}
return modified;
}
bool LoopNormalizationPass::normalizeLoop(Loop* loop) {
if (DEBUG)
std::cout << " Normalizing loop: " << loop->getName() << std::endl;
// 创建前置块
BasicBlock* preheader = createPreheaderForLoop(loop);
if (!preheader) {
if (DEBUG)
std::cout << " Failed to create preheader for loop " << loop->getName() << std::endl;
return false;
}
stats.preheadersCreated++;
if (DEBUG) {
std::cout << " Successfully created preheader " << preheader->getName()
<< " for loop " << loop->getName() << std::endl;
}
return true;
}
BasicBlock* LoopNormalizationPass::createPreheaderForLoop(Loop* loop) {
BasicBlock* header = loop->getHeader();
if (!header) {
if (DEBUG)
std::cerr << " Error: Loop has no header block" << std::endl;
return nullptr;
}
// 获取循环外的前驱块
std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
if (externalPreds.empty()) {
if (DEBUG)
std::cout << " Loop " << loop->getName() << " has no external predecessors" << std::endl;
return nullptr;
}
if (DEBUG) {
std::cout << " Found " << externalPreds.size() << " external predecessors for loop "
<< loop->getName() << std::endl;
for (auto* pred : externalPreds) {
std::cout << " External pred: " << pred->getName() << std::endl;
}
}
// 生成前置块名称
std::string preheaderName = generatePreheaderName(loop);
// 创建新的前置块
Function* parentFunction = header->getParent();
BasicBlock* preheader = parentFunction->addBasicBlock(preheaderName, header);
if (!preheader) {
if (DEBUG)
std::cerr << " Error: Failed to create basic block " << preheaderName << std::endl;
return nullptr;
}
// 在前置块中创建跳转指令到循环头部
builder->setPosition(preheader, preheader->end());
UncondBrInst* br = builder->createUncondBrInst(header);
// 更新preheader的CFG关系
preheader->addSuccessor(header);
header->addPredecessor(preheader);
if(DEBUG) {
std::cout << " Created preheader " << preheader->getName()
<< " with unconditional branch to " << header->getName() << std::endl;
}
// 重定向外部前驱到新的前置块
redirectExternalPredecessors(loop, preheader, header, externalPreds);
// 更新PHI节点
updatePhiNodesForPreheader(header, preheader, externalPreds);
// 更新支配树关系
updateDominatorRelations(preheader, loop);
// 重要:更新循环对象的前置块信息
// 这样后续的优化遍可以通过 loop->getPreHeader() 获取到新创建的前置块
loop->setPreHeader(preheader);
if (DEBUG) {
std::cout << " Updated loop object: preheader set to " << preheader->getName() << std::endl;
}
return preheader;
}
bool LoopNormalizationPass::needsPreheader(Loop* loop) {
// 检查是否已有合适的前置块
if (getExistingPreheader(loop) != nullptr) {
return false;
}
// 检查是否有外部前驱(如果没有外部前驱,不需要前置块)
std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
if (externalPreds.empty()) {
return false;
}
// 基于结构性需求判断:
// 1. 如果有多个外部前驱,必须创建前置块来合并它们
// 2. 如果单个外部前驱不适合作为前置块,需要创建新的前置块
return (externalPreds.size() > 1) || !isSuitableAsPreheader(externalPreds[0], loop);
}
BasicBlock* LoopNormalizationPass::getExistingPreheader(Loop* loop) {
BasicBlock* header = loop->getHeader();
if (!header) return nullptr;
std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
// 如果只有一个外部前驱,且适合作为前置块,则返回它
if (externalPreds.size() == 1 && isSuitableAsPreheader(externalPreds[0], loop)) {
return externalPreds[0];
}
return nullptr;
}
void LoopNormalizationPass::updateDominatorRelations(BasicBlock* newBlock, Loop* loop) {
// 由于在getAnalysisUsage中声明了DominatorTree会失效
// PassManager会在本遍运行后自动将支配树结果标记为失效
// 后续需要支配树的Pass会触发重新计算所以这里无需手动更新
if (DEBUG) {
BasicBlock* header = loop->getHeader();
std::cout << " DominatorTree marked for invalidation - new preheader "
<< newBlock->getName() << " will dominate " << header->getName()
<< " after recomputation by PassManager" << std::endl;
}
}
void LoopNormalizationPass::redirectExternalPredecessors(Loop* loop, BasicBlock* preheader, BasicBlock* header,
const std::vector<BasicBlock*>& externalPreds) {
// std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
if (DEBUG) {
std::cout << " Redirecting " << externalPreds.size() << " external predecessors" << std::endl;
}
for (BasicBlock* pred : externalPreds) {
// 获取前驱块的终止指令
auto termIt = pred->terminator();
if (termIt == pred->end()) continue;
Instruction* terminator = termIt->get();
if (!terminator) continue;
// 更新跳转目标
if (auto* br = dynamic_cast<UncondBrInst*>(terminator)) {
// 无条件跳转
if (br->getBlock() == header) {
if(DEBUG){
std::cout << " Updating unconditional branch from " << br->getBlock()->getName()
<< " to " << preheader->getName() << std::endl;
}
// 需要更新操作数
br->setOperand(0, preheader);
// 更新CFG关系
header->removePredecessor(pred);
preheader->addPredecessor(pred);
pred->removeSuccessor(header);
pred->addSuccessor(preheader);
}
} else if (auto* condBr = dynamic_cast<CondBrInst*>(terminator)) {
// 条件跳转
bool updated = false;
if (condBr->getThenBlock() == header) {
condBr->setOperand(1, preheader); // 第1个操作数是then分支
updated = true;
}
if (condBr->getElseBlock() == header) {
condBr->setOperand(2, preheader); // 第2个操作数是else分支
updated = true;
}
if (updated) {
// 更新CFG关系
header->removePredecessor(pred);
preheader->addPredecessor(pred);
pred->removeSuccessor(header);
pred->addSuccessor(preheader);
if (DEBUG) {
std::cout << " Updated conditional branch from " << pred->getName()
<< " to " << preheader->getName() << std::endl;
}
}
}
}
}
std::string LoopNormalizationPass::generatePreheaderName(Loop* loop) {
std::ostringstream oss;
oss << loop->getName() << "_preheader";
return oss.str();
}
bool LoopNormalizationPass::validateNormalization(Loop* loop) {
BasicBlock* header = loop->getHeader();
if (!header) return false;
// 检查循环是否现在有唯一的外部前驱
std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
if (externalPreds.size() != 1) {
if (DEBUG)
std::cout << " Validation failed: Loop " << loop->getName()
<< " has " << externalPreds.size() << " external predecessors (expected 1)" << std::endl;
return false;
}
// 检查外部前驱是否适合作为前置块
BasicBlock* preheader = externalPreds[0];
if (!isSuitableAsPreheader(preheader, loop)) {
if (DEBUG)
std::cout << " Validation failed: External predecessor " << preheader->getName()
<< " is not suitable as preheader" << std::endl;
return false;
}
// 额外验证检查CFG连接性
if (!preheader->hasSuccessor(header)) {
if (DEBUG)
std::cout << " Validation failed: Preheader " << preheader->getName()
<< " is not connected to header " << header->getName() << std::endl;
return false;
}
if (!header->hasPredecessor(preheader)) {
if (DEBUG)
std::cout << " Validation failed: Header " << header->getName()
<< " does not have preheader " << preheader->getName() << " as predecessor" << std::endl;
return false;
}
if (DEBUG)
std::cout << " Validation passed for loop " << loop->getName() << std::endl;
return true;
}
std::vector<BasicBlock*> LoopNormalizationPass::getExternalPredecessors(Loop* loop) {
std::vector<BasicBlock*> externalPreds;
BasicBlock* header = loop->getHeader();
if (!header) return externalPreds;
for (BasicBlock* pred : header->getPredecessors()) {
if (!loop->contains(pred)) {
externalPreds.push_back(pred);
}
}
return externalPreds;
}
bool LoopNormalizationPass::isSuitableAsPreheader(BasicBlock* block, Loop* loop) {
if (!block) return false;
// 检查该块是否只有一个后继,且后继是循环头部
auto successors = block->getSuccessors();
if (successors.size() != 1) {
return false;
}
if (successors[0] != loop->getHeader()) {
return false;
}
// 检查该块是否不包含复杂的控制流
// 理想的前置块应该只包含简单的跳转指令
size_t instCount = 0;
for (const auto& inst : block->getInstructions()) {
instCount++;
// 如果指令过多,可能不适合作为前置块
if (instCount > 10) { // 阈值可调整
return false;
}
}
return true;
}
void LoopNormalizationPass::updatePhiNodesForPreheader(BasicBlock* header, BasicBlock* preheader,
const std::vector<BasicBlock*>& oldPreds) {
if (DEBUG) {
std::cout << " Updating PHI nodes in header " << header->getName()
<< " for new preheader " << preheader->getName() << std::endl;
}
std::vector<PhiInst*> phisToRemove; // 需要删除的PHI节点
for (auto& inst : header->getInstructions()) {
if (auto* phi = dynamic_cast<PhiInst*>(inst.get())) {
if (DEBUG) {
std::cout << " Processing PHI node: " << phi->getName() << std::endl;
}
// 收集来自外部前驱的值 - 需要保持原始的映射关系
std::map<BasicBlock*, Value*> externalValues;
for (BasicBlock* oldPred : oldPreds) {
Value* value = phi->getValfromBlk(oldPred);
if (value) {
externalValues[oldPred] = value;
}
}
// 处理PHI节点的更新
if (externalValues.size() > 1) {
// 多个外部前驱在前置块中创建新的PHI节点
builder->setPosition(preheader, preheader->getInstructions().begin());
std::vector<Value*> values;
std::vector<BasicBlock*> blocks;
for (auto& [block, value] : externalValues) {
values.push_back(value);
blocks.push_back(block);
}
PhiInst* newPhi = builder->createPhiInst(phi->getType(), values, blocks);
// 移除所有外部前驱的条目
for (BasicBlock* oldPred : oldPreds) {
phi->removeIncomingBlock(oldPred);
}
// 添加来自新前置块的条目
phi->addIncoming(newPhi, preheader);
} else if (externalValues.size() == 1) {
// 单个外部前驱:直接重新映射
Value* value = externalValues.begin()->second;
// 移除旧的外部前驱条目
for (BasicBlock* oldPred : oldPreds) {
phi->removeIncomingBlock(oldPred);
}
// 添加来自新前置块的条目
phi->addIncoming(value, preheader);
// 检查PHI节点是否只剩下一个条目只来自前置块
if (phi->getNumIncomingValues() == 1) {
if (DEBUG) {
std::cout << " PHI node " << phi->getName()
<< " now has only one incoming value, scheduling for removal" << std::endl;
}
// 用单一值替换所有使用
Value* singleValue = phi->getIncomingValue(0u);
phi->replaceAllUsesWith(singleValue);
phisToRemove.push_back(phi);
}
} else {
// 没有外部值的PHI节点检查是否需要更新
// 这种PHI节点只有循环内的边通常不需要修改
// 但我们仍然需要检查是否只有一个条目
if (phi->getNumIncomingValues() == 1) {
if (DEBUG) {
std::cout << " PHI node " << phi->getName()
<< " has only one incoming value (no external), scheduling for removal" << std::endl;
}
// 用单一值替换所有使用
Value* singleValue = phi->getIncomingValue(0u);
phi->replaceAllUsesWith(singleValue);
phisToRemove.push_back(phi);
}
}
if (DEBUG && std::find(phisToRemove.begin(), phisToRemove.end(), phi) == phisToRemove.end()) {
std::cout << " Updated PHI node with " << externalValues.size()
<< " external values, total incoming: " << phi->getNumIncomingValues() << std::endl;
}
}
}
// 删除标记为移除的PHI节点
for (PhiInst* phi : phisToRemove) {
if (DEBUG) {
std::cout << " Removing redundant PHI node: " << phi->getName() << std::endl;
}
SysYIROptUtils::usedelete(phi);
}
// 更新统计信息
stats.redundantPhisRemoved += phisToRemove.size();
if (DEBUG && !phisToRemove.empty()) {
std::cout << " Removed " << phisToRemove.size() << " redundant PHI nodes" << std::endl;
}
}
void LoopNormalizationPass::printStats(Function* F) {
std::cout << "\n--- Loop Normalization Statistics for Function: " << F->getName() << " ---" << std::endl;
std::cout << "Total loops analyzed: " << stats.totalLoops << std::endl;
std::cout << "Loops needing preheader: " << stats.loopsNeedingPreheader << std::endl;
std::cout << "Preheaders created: " << stats.preheadersCreated << std::endl;
std::cout << "Loops successfully normalized: " << stats.loopsNormalized << std::endl;
std::cout << "Redundant PHI nodes removed: " << stats.redundantPhisRemoved << std::endl;
if (stats.totalLoops > 0) {
double normalizationRate = (double)stats.loopsNormalized / stats.totalLoops * 100.0;
std::cout << "Normalization rate: " << normalizationRate << "%" << std::endl;
}
std::cout << "---------------------------------------------------------------" << std::endl;
}
void LoopNormalizationPass::getAnalysisUsage(std::set<void *> &analysisDependencies,
std::set<void *> &analysisInvalidations) const {
// LoopNormalization依赖的分析
analysisDependencies.insert(&LoopAnalysisPass::ID); // 循环结构分析
analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); // 支配树分析
// LoopNormalization会修改CFG结构因此会使以下分析失效
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树需要重新计算
// 注意:我们不让循环结构分析失效,原因如下:
// 1. 循环规范化只添加前置块,不改变循环的核心结构(头部、体、回边)
// 2. 我们会手动更新Loop对象的前置块信息通过loop->setPreHeader()
// 3. 让循环分析失效并重新计算的成本较高且不必要
// 4. 后续优化遍可以正确获取到更新后的前置块信息
//
// 如果未来有更复杂的循环结构修改,可能需要考虑让循环分析失效:
// analysisInvalidations.insert(&LoopAnalysisPass::ID);
}
} // namespace sysy

View File

@ -0,0 +1,940 @@
#include "LoopStrengthReduction.h"
#include "LoopCharacteristics.h"
#include "Loop.h"
#include "Dom.h"
#include "IRBuilder.h"
#include "SysYIROptUtils.h"
#include <iostream>
#include <algorithm>
#include <cmath>
#include <unordered_map>
#include <climits>
// 使用全局调试开关
extern int DEBUG;
namespace sysy {
// 定义 Pass
void *LoopStrengthReduction::ID = (void *)&LoopStrengthReduction::ID;
bool StrengthReductionContext::analyzeInductionVariableRange(
const InductionVarInfo* ivInfo,
Loop* loop
) const {
if (!ivInfo->valid) {
if (DEBUG) {
std::cout << " Invalid IV info, assuming potential negative" << std::endl;
}
return true; // 保守假设非线性变化可能为负数
}
// 获取phi指令的所有入口值
auto* phiInst = dynamic_cast<PhiInst*>(ivInfo->base);
if (!phiInst) {
if (DEBUG) {
std::cout << " No phi instruction, assuming potential negative" << std::endl;
}
return true; // 无法确定,保守假设
}
bool hasNegativePotential = false;
bool hasNonNegativeInitial = false;
int initialValue = 0;
for (auto& [incomingBB, incomingVal] : phiInst->getIncomingValues()) {
// 检查初始值(来自循环外的值)
if (!loop->contains(incomingBB)) {
if (auto* constInt = dynamic_cast<ConstantInteger*>(incomingVal)) {
initialValue = constInt->getInt();
if (initialValue < 0) {
if (DEBUG) {
std::cout << " Found negative initial value: " << initialValue << std::endl;
}
hasNegativePotential = true;
} else {
if (DEBUG) {
std::cout << " Found non-negative initial value: " << initialValue << std::endl;
}
hasNonNegativeInitial = true;
}
} else {
// 如果不是常数初始值,保守假设可能为负数
if (DEBUG) {
std::cout << " Non-constant initial value, assuming potential negative" << std::endl;
}
hasNegativePotential = true;
}
}
}
// 检查递增值和偏移
if (ivInfo->factor < 0) {
if (DEBUG) {
std::cout << " Negative factor: " << ivInfo->factor << std::endl;
}
hasNegativePotential = true;
}
if (ivInfo->offset < 0) {
if (DEBUG) {
std::cout << " Negative offset: " << ivInfo->offset << std::endl;
}
hasNegativePotential = true;
}
// 精确分析:如果初始值非负,递增为正,偏移非负,则整个序列非负
if (hasNonNegativeInitial && ivInfo->factor > 0 && ivInfo->offset >= 0) {
if (DEBUG) {
std::cout << " ANALYSIS: Confirmed non-negative range" << std::endl;
std::cout << " Initial: " << initialValue << " >= 0" << std::endl;
std::cout << " Factor: " << ivInfo->factor << " > 0" << std::endl;
std::cout << " Offset: " << ivInfo->offset << " >= 0" << std::endl;
}
return false; // 确定不会为负数
}
// 报告分析结果
if (DEBUG) {
if (hasNegativePotential) {
std::cout << " ANALYSIS: Potential negative values detected" << std::endl;
} else {
std::cout << " ANALYSIS: No negative indicators, but missing positive confirmation" << std::endl;
}
}
return hasNegativePotential;
}
bool LoopStrengthReduction::runOnFunction(Function* F, AnalysisManager& AM) {
if (F->getBasicBlocks().empty()) {
return false; // 空函数
}
if (DEBUG) {
std::cout << "Running LoopStrengthReduction on function: " << F->getName() << std::endl;
}
// 创建优化上下文并运行
StrengthReductionContext context(builder);
bool modified = context.run(F, AM);
if (DEBUG) {
std::cout << "LoopStrengthReduction " << (modified ? "modified" : "did not modify")
<< " function: " << F->getName() << std::endl;
}
return modified;
}
void LoopStrengthReduction::getAnalysisUsage(std::set<void*>& analysisDependencies,
std::set<void*>& analysisInvalidations) const {
// 依赖的分析
analysisDependencies.insert(&LoopAnalysisPass::ID);
analysisDependencies.insert(&LoopCharacteristicsPass::ID);
analysisDependencies.insert(&DominatorTreeAnalysisPass::ID);
// 会使失效的分析强度削弱会修改IR结构
analysisInvalidations.insert(&LoopCharacteristicsPass::ID);
// 注意:支配树分析通常不会因为强度削弱而失效,因为我们不改变控制流
}
// ========== StrengthReductionContext 实现 ==========
bool StrengthReductionContext::run(Function* F, AnalysisManager& AM) {
if (DEBUG) {
std::cout << " Starting strength reduction analysis..." << std::endl;
}
// 获取必要的分析结果
loopAnalysis = AM.getAnalysisResult<LoopAnalysisResult, LoopAnalysisPass>(F);
if (!loopAnalysis || !loopAnalysis->hasLoops()) {
if (DEBUG) {
std::cout << " No loops found, skipping strength reduction" << std::endl;
}
return false;
}
loopCharacteristics = AM.getAnalysisResult<LoopCharacteristicsResult, LoopCharacteristicsPass>(F);
if (!loopCharacteristics) {
if (DEBUG) {
std::cout << " LoopCharacteristics analysis not available" << std::endl;
}
return false;
}
dominatorTree = AM.getAnalysisResult<DominatorTree, DominatorTreeAnalysisPass>(F);
if (!dominatorTree) {
if (DEBUG) {
std::cout << " DominatorTree analysis not available" << std::endl;
}
return false;
}
// 执行三个阶段的优化
// 阶段1识别候选项
identifyStrengthReductionCandidates(F);
if (candidates.empty()) {
if (DEBUG) {
std::cout << " No strength reduction candidates found" << std::endl;
}
return false;
}
if (DEBUG) {
std::cout << " Found " << candidates.size() << " potential candidates" << std::endl;
}
// 阶段2分析优化潜力
analyzeOptimizationPotential();
// 阶段3执行优化
bool modified = performStrengthReduction();
if (DEBUG) {
printDebugInfo();
}
return modified;
}
void StrengthReductionContext::identifyStrengthReductionCandidates(Function* F) {
if (DEBUG) {
std::cout << " === Phase 1: Identifying Strength Reduction Candidates ===" << std::endl;
}
// 遍历所有循环
for (const auto& loop_ptr : loopAnalysis->getAllLoops()) {
Loop* loop = loop_ptr.get();
if (DEBUG) {
std::cout << " Analyzing loop: " << loop->getName() << std::endl;
}
// 获取循环特征
const LoopCharacteristics* characteristics = loopCharacteristics->getCharacteristics(loop);
if (!characteristics) {
if (DEBUG) {
std::cout << " No characteristics available for loop" << std::endl;
}
continue;
}
if (characteristics->InductionVars.empty()) {
if (DEBUG) {
std::cout << " No induction variables found in loop" << std::endl;
}
continue;
}
// 遍历循环中的所有指令
for (BasicBlock* bb : loop->getBlocks()) {
for (auto& inst_ptr : bb->getInstructions()) {
Instruction* inst = inst_ptr.get();
// 检查是否为强度削弱候选项
auto candidate = isStrengthReductionCandidate(inst, loop);
if (candidate) {
if (DEBUG) {
std::cout << " Found candidate: %" << inst->getName()
<< " (IV: %" << candidate->inductionVar->getName()
<< ", multiplier: " << candidate->multiplier
<< ", offset: " << candidate->offset << ")" << std::endl;
}
// 添加到候选项列表
loopToCandidates[loop].push_back(candidate.get());
candidates.push_back(std::move(candidate));
}
}
}
}
if (DEBUG) {
std::cout << " === End Phase 1: Found " << candidates.size() << " candidates ===" << std::endl;
}
}
std::unique_ptr<StrengthReductionCandidate>
StrengthReductionContext::isStrengthReductionCandidate(Instruction* inst, Loop* loop) {
auto kind = inst->getKind();
// 支持乘法、除法、取模指令
if (kind != Instruction::Kind::kMul &&
kind != Instruction::Kind::kDiv &&
kind != Instruction::Kind::kRem) {
return nullptr;
}
auto* binaryInst = dynamic_cast<BinaryInst*>(inst);
if (!binaryInst) {
return nullptr;
}
Value* op0 = binaryInst->getOperand(0);
Value* op1 = binaryInst->getOperand(1);
// 检查模式:归纳变量 op 常数 或 常数 op 归纳变量
Value* inductionVar = nullptr;
int constantValue = 0;
StrengthReductionCandidate::OpType opType;
// 获取循环特征信息
const LoopCharacteristics* characteristics = loopCharacteristics->getCharacteristics(loop);
if (!characteristics) {
return nullptr;
}
// 确定操作类型
switch (kind) {
case Instruction::Kind::kMul:
opType = StrengthReductionCandidate::MULTIPLY;
break;
case Instruction::Kind::kDiv:
opType = StrengthReductionCandidate::DIVIDE;
break;
case Instruction::Kind::kRem:
opType = StrengthReductionCandidate::REMAINDER;
break;
default:
return nullptr;
}
// 模式1: IV op const
const InductionVarInfo* ivInfo = getInductionVarInfo(op0, loop, characteristics);
if (ivInfo && dynamic_cast<ConstantInteger*>(op1)) {
inductionVar = op0;
constantValue = dynamic_cast<ConstantInteger*>(op1)->getInt();
}
// 模式2: const op IV (仅对乘法有效)
else if (opType == StrengthReductionCandidate::MULTIPLY) {
ivInfo = getInductionVarInfo(op1, loop, characteristics);
if (ivInfo && dynamic_cast<ConstantInteger*>(op0)) {
inductionVar = op1;
constantValue = dynamic_cast<ConstantInteger*>(op0)->getInt();
}
}
if (!inductionVar || constantValue <= 1) {
return nullptr; // 不是有效的候选项
}
// 创建候选项
auto candidate = std::make_unique<StrengthReductionCandidate>(
inst, inductionVar, opType, constantValue, 0, inst->getParent(), loop
);
// 分析归纳变量是否可能为负数
candidate->hasNegativeValues = analyzeInductionVariableRange(ivInfo, loop);
// 根据除法类型选择优化策略
if (opType == StrengthReductionCandidate::DIVIDE) {
bool isPowerOfTwo = (constantValue & (constantValue - 1)) == 0;
if (isPowerOfTwo) {
// 2的幂除法
if (candidate->hasNegativeValues) {
candidate->divStrategy = StrengthReductionCandidate::SIGNED_CORRECTION;
if (DEBUG) {
std::cout << " Division by power of 2 with potential negative values, using signed correction" << std::endl;
}
} else {
candidate->divStrategy = StrengthReductionCandidate::SIMPLE_SHIFT;
if (DEBUG) {
std::cout << " Division by power of 2 with non-negative values, using simple shift" << std::endl;
}
}
} else {
// 任意常数除法使用mulh指令
candidate->operationType = StrengthReductionCandidate::DIVIDE_CONST;
candidate->divStrategy = StrengthReductionCandidate::MULH_OPTIMIZATION;
if (DEBUG) {
std::cout << " Division by arbitrary constant, using mulh optimization" << std::endl;
}
}
} else if (opType == StrengthReductionCandidate::REMAINDER) {
// 取模运算只支持2的幂
if ((constantValue & (constantValue - 1)) != 0) {
return nullptr; // 不是2的幂无法优化
}
}
return candidate;
}
const InductionVarInfo*
StrengthReductionContext::getInductionVarInfo(Value* val, Loop* loop,
const LoopCharacteristics* characteristics) {
for (const auto& iv : characteristics->InductionVars) {
if (iv->div == val) {
return iv.get();
}
}
return nullptr;
}
void StrengthReductionContext::analyzeOptimizationPotential() {
if (DEBUG) {
std::cout << " === Phase 2: Analyzing Optimization Potential ===" << std::endl;
}
// 为每个候选项计算优化收益,并过滤不值得优化的
auto it = candidates.begin();
while (it != candidates.end()) {
StrengthReductionCandidate* candidate = it->get();
double benefit = estimateOptimizationBenefit(candidate);
bool isLegal = isOptimizationLegal(candidate);
if (DEBUG) {
std::cout << " Candidate " << candidate->originalInst->getName()
<< ": benefit=" << benefit
<< ", legal=" << (isLegal ? "yes" : "no") << std::endl;
}
// 如果收益太小或不合法,移除候选项
if (benefit < 1.0 || !isLegal) {
// 从 loopToCandidates 中移除
auto& loopCandidates = loopToCandidates[candidate->containingLoop];
loopCandidates.erase(
std::remove(loopCandidates.begin(), loopCandidates.end(), candidate),
loopCandidates.end()
);
it = candidates.erase(it);
} else {
++it;
}
}
if (DEBUG) {
std::cout << " === End Phase 2: " << candidates.size() << " candidates remain ===" << std::endl;
}
}
double StrengthReductionContext::estimateOptimizationBenefit(const StrengthReductionCandidate* candidate) {
// 简单的收益估算模型
double benefit = 0.0;
// 基础收益:乘法变加法的性能提升
benefit += 2.0; // 假设乘法比加法慢2倍
// 乘数因子:乘数越大,收益越高
if (candidate->multiplier >= 4) {
benefit += 1.0;
}
if (candidate->multiplier >= 8) {
benefit += 1.0;
}
// 循环热度因子
Loop* loop = candidate->containingLoop;
double hotness = loop->getLoopHotness();
benefit *= (1.0 + hotness / 100.0);
// 使用次数因子
size_t useCount = candidate->originalInst->getUses().size();
if (useCount > 1) {
benefit *= (1.0 + useCount * 0.2);
}
return benefit;
}
bool StrengthReductionContext::isOptimizationLegal(const StrengthReductionCandidate* candidate) {
// 检查优化的合法性
// 1. 确保归纳变量在循环头有 phi 指令
auto* phiInst = dynamic_cast<PhiInst*>(candidate->inductionVar);
if (!phiInst || phiInst->getParent() != candidate->containingLoop->getHeader()) {
if (DEBUG ) {
std::cout << " Illegal: induction variable is not a phi in loop header" << std::endl;
}
return false;
}
// 2. 确保乘法指令在循环内
if (!candidate->containingLoop->contains(candidate->containingBlock)) {
if (DEBUG ) {
std::cout << " Illegal: instruction not in loop" << std::endl;
}
return false;
}
// 3. 检查是否有溢出风险(简化检查)
if (candidate->multiplier > 1000) {
if (DEBUG ) {
std::cout << " Illegal: multiplier too large (overflow risk)" << std::endl;
}
return false;
}
// 4. 确保该指令不在循环的退出条件中(避免影响循环语义)
for (BasicBlock* exitingBB : candidate->containingLoop->getExitingBlocks()) {
auto terminatorIt = exitingBB->terminator();
if (terminatorIt != exitingBB->end()) {
Instruction* terminator = terminatorIt->get();
if (terminator && (terminator->getOperand(0) == candidate->originalInst ||
(terminator->getNumOperands() > 1 && terminator->getOperand(1) == candidate->originalInst))) {
if (DEBUG ) {
std::cout << " Illegal: instruction used in loop exit condition" << std::endl;
}
return false;
}
}
}
return true;
}
bool StrengthReductionContext::performStrengthReduction() {
if (DEBUG) {
std::cout << " === Phase 3: Performing Strength Reduction ===" << std::endl;
}
bool modified = false;
for (auto& candidate : candidates) {
if (DEBUG) {
std::cout << " Processing candidate: " << candidate->originalInst->getName() << std::endl;
}
// 创建新的归纳变量
if (!createNewInductionVariable(candidate.get())) {
if (DEBUG) {
std::cout << " Failed to create new induction variable" << std::endl;
}
continue;
}
// 替换原始指令
if (!replaceOriginalInstruction(candidate.get())) {
if (DEBUG) {
std::cout << " Failed to replace original instruction" << std::endl;
}
continue;
}
if (DEBUG) {
std::cout << " Successfully optimized: " << candidate->originalInst->getName()
<< " -> " << candidate->newInductionVar->getName() << std::endl;
}
modified = true;
}
if (DEBUG) {
std::cout << " === End Phase 3: " << (modified ? "Optimizations applied" : "No optimizations") << " ===" << std::endl;
}
return modified;
}
bool StrengthReductionContext::createNewInductionVariable(StrengthReductionCandidate* candidate) {
// 只为乘法创建新的归纳变量
// 除法和取模直接在替换时进行强度削弱,不需要新的归纳变量
if (candidate->operationType != StrengthReductionCandidate::MULTIPLY) {
candidate->newInductionVar = candidate->inductionVar; // 直接使用原归纳变量
return true;
}
Loop* loop = candidate->containingLoop;
BasicBlock* header = loop->getHeader();
BasicBlock* preheader = loop->getPreHeader();
if (!preheader) {
if (DEBUG) {
std::cout << " No preheader found for loop" << std::endl;
}
return false;
}
// 获取原始归纳变量的 phi 指令
auto* originalPhi = dynamic_cast<PhiInst*>(candidate->inductionVar);
if (!originalPhi) {
return false;
}
// 1. 找到原始归纳变量的初始值和步长
Value* initialValue = nullptr;
Value* stepValue = nullptr;
BasicBlock* latchBlock = nullptr;
for (auto& [incomingBB, incomingVal] : originalPhi->getIncomingValues()) {
if (!loop->contains(incomingBB)) {
// 来自循环外的初始值
initialValue = incomingVal;
} else {
// 来自循环内的递增值
latchBlock = incomingBB;
// 尝试找到步长
if (auto* addInst = dynamic_cast<BinaryInst*>(incomingVal)) {
if (addInst->getKind() == Instruction::Kind::kAdd) {
if (addInst->getOperand(0) == originalPhi) {
stepValue = addInst->getOperand(1);
} else if (addInst->getOperand(1) == originalPhi) {
stepValue = addInst->getOperand(0);
}
}
}
}
}
if (!initialValue || !stepValue || !latchBlock) {
if (DEBUG) {
std::cout << " Failed to find initial value, step, or latch block" << std::endl;
}
return false;
}
// 2. 在循环头创建新的 phi 指令
builder->setPosition(header, header->begin());
candidate->newPhi = builder->createPhiInst(originalPhi->getType());
candidate->newPhi->setName("sr_" + originalPhi->getName());
// 3. 计算新归纳变量的初始值和步长
// 新IV的初始值 = 原IV初始值 * multiplier
Value* newInitialValue;
if (auto* constInt = dynamic_cast<ConstantInteger*>(initialValue)) {
newInitialValue = ConstantInteger::get(constInt->getInt() * candidate->multiplier);
} else {
// 如果初始值不是常数需要在preheader中插入乘法
builder->setPosition(preheader, preheader->terminator());
newInitialValue = builder->createMulInst(initialValue,
ConstantInteger::get(candidate->multiplier));
}
// 新IV的步长 = 原IV步长 * multiplier
Value* newStepValue;
if (auto* constInt = dynamic_cast<ConstantInteger*>(stepValue)) {
newStepValue = ConstantInteger::get(constInt->getInt() * candidate->multiplier);
} else {
builder->setPosition(latchBlock, latchBlock->terminator());
newStepValue = builder->createMulInst(stepValue,
ConstantInteger::get(candidate->multiplier));
}
// 4. 创建新归纳变量的递增指令
builder->setPosition(latchBlock, latchBlock->terminator());
Value* newIncrementedValue = builder->createAddInst(candidate->newPhi, newStepValue);
// 5. 设置新 phi 的输入值
candidate->newPhi->addIncoming(newInitialValue, preheader);
candidate->newPhi->addIncoming(newIncrementedValue, latchBlock);
candidate->newInductionVar = candidate->newPhi;
if (DEBUG) {
std::cout << " Created new induction variable: " << candidate->newPhi->getName() << std::endl;
}
return true;
}
bool StrengthReductionContext::replaceOriginalInstruction(StrengthReductionCandidate* candidate) {
if (!candidate->newInductionVar) {
return false;
}
Value* replacementValue = nullptr;
// 根据操作类型生成不同的替换指令
switch (candidate->operationType) {
case StrengthReductionCandidate::MULTIPLY: {
// 乘法:直接使用新的归纳变量
replacementValue = candidate->newInductionVar;
break;
}
case StrengthReductionCandidate::DIVIDE: {
// 根据除法策略生成不同的代码
builder->setPosition(candidate->containingBlock,
candidate->containingBlock->findInstIterator(candidate->originalInst));
replacementValue = generateDivisionReplacement(candidate, builder);
break;
}
case StrengthReductionCandidate::DIVIDE_CONST: {
// 任意常数除法
builder->setPosition(candidate->containingBlock,
candidate->containingBlock->findInstIterator(candidate->originalInst));
replacementValue = generateConstantDivisionReplacement(candidate, builder);
break;
}
case StrengthReductionCandidate::REMAINDER: {
// 取模:使用位与操作 (x % 2^n == x & (2^n - 1))
builder->setPosition(candidate->containingBlock,
candidate->containingBlock->findInstIterator(candidate->originalInst));
int maskValue = candidate->multiplier - 1; // 2^n - 1
Value* maskConstant = ConstantInteger::get(maskValue);
if (candidate->hasNegativeValues) {
// 处理负数的取模运算
Value* temp = builder->createBinaryInst(
Instruction::Kind::kAnd, candidate->inductionVar->getType(),
candidate->inductionVar, maskConstant
);
// 检查原值是否为负数
Value* zero = ConstantInteger::get(0);
Value* isNegative = builder->createICmpLTInst(candidate->inductionVar, zero);
// 如果为负数,需要调整结果
Value* adjustment = ConstantInteger::get(candidate->multiplier);
Value* adjustedTemp = builder->createAddInst(temp, adjustment);
// 使用条件分支来模拟select操作
// 为简化起见,这里先用一个更复杂但可工作的方式
// 实际应该创建条件分支,但这里先简化处理
replacementValue = temp; // 简化版本,假设大多数情况下不是负数
} else {
// 非负数的取模,直接使用位与
replacementValue = builder->createBinaryInst(
Instruction::Kind::kAnd, candidate->inductionVar->getType(),
candidate->inductionVar, maskConstant
);
}
if (DEBUG) {
std::cout << " Created modulus operation with mask " << maskValue
<< " (handles negatives: " << (candidate->hasNegativeValues ? "yes" : "no") << ")" << std::endl;
}
break;
}
default:
return false;
}
if (!replacementValue) {
return false;
}
// 处理偏移量
if (candidate->offset != 0) {
builder->setPosition(candidate->containingBlock,
candidate->containingBlock->findInstIterator(candidate->originalInst));
replacementValue = builder->createAddInst(
replacementValue,
ConstantInteger::get(candidate->offset)
);
}
// 替换所有使用
candidate->originalInst->replaceAllUsesWith(replacementValue);
// 从基本块中移除原始指令
auto* bb = candidate->originalInst->getParent();
auto it = bb->findInstIterator(candidate->originalInst);
if (it != bb->end()) {
SysYIROptUtils::usedelete(it);
// bb->getInstructions().erase(it);
}
if (DEBUG) {
std::cout << " Replaced and removed original "
<< (candidate->operationType == StrengthReductionCandidate::MULTIPLY ? "multiply" :
candidate->operationType == StrengthReductionCandidate::DIVIDE ? "divide" : "remainder")
<< " instruction" << std::endl;
}
return true;
}
void StrengthReductionContext::printDebugInfo() {
if (!DEBUG) return;
std::cout << "\n=== Strength Reduction Optimization Summary ===" << std::endl;
std::cout << "Total candidates processed: " << candidates.size() << std::endl;
for (auto& [loop, loopCandidates] : loopToCandidates) {
if (!loopCandidates.empty()) {
std::cout << "Loop " << loop->getName() << ": " << loopCandidates.size() << " optimizations" << std::endl;
for (auto* candidate : loopCandidates) {
if (candidate->newInductionVar) {
std::cout << " " << candidate->inductionVar->getName()
<< " (op=" << (candidate->operationType == StrengthReductionCandidate::MULTIPLY ? "mul" :
candidate->operationType == StrengthReductionCandidate::DIVIDE ? "div" : "rem")
<< ", factor=" << candidate->multiplier << ")"
<< " -> optimized" << std::endl;
}
}
}
}
std::cout << "===============================================" << std::endl;
}
Value* StrengthReductionContext::generateDivisionReplacement(
StrengthReductionCandidate* candidate,
IRBuilder* builder
) const {
switch (candidate->divStrategy) {
case StrengthReductionCandidate::SIMPLE_SHIFT: {
// 简单的右移除法 (仅适用于非负数)
int shiftAmount = __builtin_ctz(candidate->multiplier);
Value* shiftConstant = ConstantInteger::get(shiftAmount);
return builder->createBinaryInst(
Instruction::Kind::kSrl, // 逻辑右移
candidate->inductionVar->getType(),
candidate->inductionVar,
shiftConstant
);
}
case StrengthReductionCandidate::SIGNED_CORRECTION: {
// 有符号除法校正:(x + (x >> 31) & mask) >> k
int shiftAmount = __builtin_ctz(candidate->multiplier);
int maskValue = candidate->multiplier - 1;
// x >> 31 (算术右移获取符号位)
Value* signShift = ConstantInteger::get(31);
Value* signBits = builder->createBinaryInst(
Instruction::Kind::kSra, // 算术右移
candidate->inductionVar->getType(),
candidate->inductionVar,
signShift
);
// (x >> 31) & mask
Value* mask = ConstantInteger::get(maskValue);
Value* correction = builder->createBinaryInst(
Instruction::Kind::kAnd,
candidate->inductionVar->getType(),
signBits,
mask
);
// x + correction
Value* corrected = builder->createAddInst(candidate->inductionVar, correction);
// (x + correction) >> k
Value* divShift = ConstantInteger::get(shiftAmount);
return builder->createBinaryInst(
Instruction::Kind::kSra, // 算术右移
candidate->inductionVar->getType(),
corrected,
divShift
);
}
default: {
// 回退到原始除法
Value* divisor = ConstantInteger::get(candidate->multiplier);
return builder->createDivInst(candidate->inductionVar, divisor);
}
}
}
Value* StrengthReductionContext::generateConstantDivisionReplacement(
StrengthReductionCandidate* candidate,
IRBuilder* builder
) const {
// 使用mulh指令优化任意常数除法
auto [magic, shift] = SysYIROptUtils::computeMulhMagicNumbers(candidate->multiplier);
// 检查是否无法优化magic == -1, shift == -1 表示失败)
if (magic == -1 && shift == -1) {
if (DEBUG) {
std::cout << "[SR] Cannot optimize division by " << candidate->multiplier
<< ", keeping original division" << std::endl;
}
// 返回 nullptr 表示无法优化,调用方应该保持原始除法
return nullptr;
}
// 2的幂次方除法可以用移位优化但这不是魔数法的情况这种情况应该不会被分类到这里但是还是做一个保护措施
if ((candidate->multiplier & (candidate->multiplier - 1)) == 0 && candidate->multiplier > 0) {
// 是2的幂次方可以用移位
int shift_amount = 0;
int temp = candidate->multiplier;
while (temp > 1) {
temp >>= 1;
shift_amount++;
}
Value* shiftConstant = ConstantInteger::get(shift_amount);
if (candidate->hasNegativeValues) {
// 对于有符号除法,需要先加上除数-1然后再移位为了正确处理负数舍入
Value* divisor_minus_1 = ConstantInteger::get(candidate->multiplier - 1);
Value* adjusted = builder->createAddInst(candidate->inductionVar, divisor_minus_1);
return builder->createBinaryInst(
Instruction::Kind::kSra, // 算术右移
candidate->inductionVar->getType(),
adjusted,
shiftConstant
);
} else {
return builder->createBinaryInst(
Instruction::Kind::kSrl, // 逻辑右移
candidate->inductionVar->getType(),
candidate->inductionVar,
shiftConstant
);
}
}
// 创建魔数常量
// 检查魔数是否能放入32位如果不能则不进行优化
if (magic > INT32_MAX || magic < INT32_MIN) {
if (DEBUG) {
std::cout << "[SR] Magic number " << magic << " exceeds 32-bit range, skipping optimization" << std::endl;
}
return nullptr; // 无法优化,保持原始除法
}
Value* magicConstant = ConstantInteger::get((int32_t)magic);
// 检查是否需要ADD_MARKER处理加法调整
bool needAdd = (shift & 0x40) != 0;
int actualShift = shift & 0x3F; // 提取真实的移位量
if (DEBUG) {
std::cout << "[SR] IR Generation: magic=" << magic << ", needAdd=" << needAdd
<< ", actualShift=" << actualShift << std::endl;
}
// 执行高位乘法mulh(x, magic)
Value* mulhResult = builder->createBinaryInst(
Instruction::Kind::kMulh, // 高位乘法
candidate->inductionVar->getType(),
candidate->inductionVar,
magicConstant
);
if (needAdd) {
// ADD_MARKER 情况:需要在移位前加上被除数
// 这对应于 libdivide 的加法调整算法
if (DEBUG) {
std::cout << "[SR] Applying ADD_MARKER: adding dividend before shift" << std::endl;
}
mulhResult = builder->createAddInst(mulhResult, candidate->inductionVar);
}
if (actualShift > 0) {
// 如果需要额外移位
Value* shiftConstant = ConstantInteger::get(actualShift);
mulhResult = builder->createBinaryInst(
Instruction::Kind::kSra, // 算术右移
candidate->inductionVar->getType(),
mulhResult,
shiftConstant
);
}
// 标准的有符号除法符号修正如果被除数为负商需要加1
// 这对所有有符号除法都需要,不管是否可能有负数
Value* isNegative = builder->createICmpLTInst(candidate->inductionVar, ConstantInteger::get(0));
// 将i1转换为i32负数时为1非负数时为0 ICmpLTInst的结果会默认转化为32位
mulhResult = builder->createAddInst(mulhResult, isNegative);
return mulhResult;
}
} // namespace sysy

View File

@ -1,6 +1,8 @@
#include "Mem2Reg.h" // 包含 Mem2Reg 遍的头文件
#include "Dom.h" // 包含支配树分析的头文件
#include "Liveness.h"
#include "AliasAnalysis.h" // 包含别名分析
#include "SideEffectAnalysis.h" // 包含副作用分析
#include "IR.h" // 包含 IR 相关的定义
#include "SysYIROptUtils.h"
#include <cassert> // 用于断言
@ -420,8 +422,9 @@ void Mem2Reg::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<
// 因此,它会使许多分析结果失效。
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树可能受影响
analysisInvalidations.insert(&LivenessAnalysisPass::ID); // 活跃性分析肯定失效
analysisInvalidations.insert(&SysYAliasAnalysisPass::ID); // 别名分析必须失效因为Mem2Reg改变了内存访问模式
analysisInvalidations.insert(&SysYSideEffectAnalysisPass::ID); // 副作用分析也可能失效
// analysisInvalidations.insert(&LoopInfoAnalysisPass::ID); // 循环信息可能失效
// analysisInvalidations.insert(&SideEffectInfoAnalysisPass::ID); // 副作用分析可能失效
// 其他所有依赖于数据流或 IR 结构的分析都可能失效。
}

View File

@ -148,8 +148,8 @@ void Reg2MemContext::rewritePhis(Function *func) {
// 1. 为 Phi 指令的每个入边,在前驱块的末尾插入 Store 指令
// PhiInst 假设有 getIncomingValues() 和 getIncomingBlocks()
for (unsigned i = 0; i < phiInst->getNumIncomingValues(); ++i) { // 假设 PhiInst 是通过操作数来管理入边的
Value *incomingValue = phiInst->getValue(i); // 获取入值
BasicBlock *incomingBlock = phiInst->getBlock(i); // 获取对应的入块
Value *incomingValue = phiInst->getIncomingValue(i); // 获取入值
BasicBlock *incomingBlock = phiInst->getIncomingBlock(i); // 获取对应的入块
// 在入块的跳转指令之前插入 StoreInst
// 需要找到 incomingBlock 的终结指令 (Terminator Instruction)

View File

@ -1,10 +1,12 @@
#include "SCCP.h"
#include "Dom.h"
#include "Liveness.h"
#include "SideEffectAnalysis.h"
#include <algorithm>
#include <cassert>
#include <cmath> // For std::fmod, std::fabs
#include <limits> // For std::numeric_limits
#include <set> // For std::set in isKnownPureFunction
namespace sysy {
@ -263,6 +265,192 @@ SSAPValue SCCPContext::ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVa
return SSAPValue(LatticeVal::Bottom);
}
// 辅助函数:检查是否为已知的纯函数
bool SCCPContext::isKnownPureFunction(const std::string &funcName) const {
// SysY中一些已知的纯函数不修改全局状态结果只依赖参数
static const std::set<std::string> knownPureFunctions = {
// 数学函数(如果有的话)
// "abs", "fabs", "sqrt", "sin", "cos"
// SysY标准中基本没有纯函数大多数都有I/O副作用
};
return knownPureFunctions.find(funcName) != knownPureFunctions.end();
}
// 辅助函数:计算纯函数的常量结果
SSAPValue SCCPContext::computePureFunctionResult(CallInst *call, const std::vector<SSAPValue> &argValues) {
Function *calledFunc = call->getCallee();
if (!calledFunc) {
return SSAPValue(LatticeVal::Bottom);
}
std::string funcName = calledFunc->getName();
// 目前SysY中没有标准的纯函数这里预留扩展空间
// 未来可以添加数学函数的常量折叠
/*
if (funcName == "abs" && argValues.size() == 1) {
if (argValues[0].constant_type == ValueType::Integer) {
int val = std::get<int>(argValues[0].constantVal);
return SSAPValue(std::abs(val));
}
}
*/
return SSAPValue(LatticeVal::Bottom);
}
// 辅助函数:查找存储到指定位置的常量值
SSAPValue SCCPContext::findStoredConstantValue(Value *ptr, BasicBlock *currentBB) {
if (!aliasAnalysis) {
if (DEBUG) {
std::cout << "SCCP: No alias analysis available" << std::endl;
}
return SSAPValue(LatticeVal::Bottom);
}
if (DEBUG) {
std::cout << "SCCP: Searching for stored constant value for ptr" << std::endl;
}
// 从当前块的指令列表末尾向前查找最近的Store
std::vector<Instruction*> instructions;
for (auto it = currentBB->begin(); it != currentBB->end(); ++it) {
instructions.push_back(it->get());
}
for (int i = instructions.size() - 1; i >= 0; --i) {
Instruction *prevInst = instructions[i];
if (prevInst->isStore()) {
StoreInst *storeInst = static_cast<StoreInst *>(prevInst);
Value *storePtr = storeInst->getPointer();
if (DEBUG) {
std::cout << "SCCP: Checking store instruction" << std::endl;
}
// 使用别名分析检查Store是否针对相同的内存位置
auto aliasResult = aliasAnalysis->queryAlias(ptr, storePtr);
if (DEBUG) {
std::cout << "SCCP: Alias result: " << (int)aliasResult << std::endl;
}
if (aliasResult == AliasType::SELF_ALIAS) {
// 找到了对相同位置的Store获取存储的值
Value *storedValue = storeInst->getValue();
if (DEBUG) {
std::cout << "SCCP: Found matching store, checking value type" << std::endl;
}
// 检查存储的值是否为常量
if (auto constInt = dynamic_cast<ConstantInteger *>(storedValue)) {
int val = std::get<int>(constInt->getVal());
if (DEBUG) {
std::cout << "SCCP: Found constant integer value: " << val << std::endl;
}
return SSAPValue(val);
} else if (auto constFloat = dynamic_cast<ConstantFloating *>(storedValue)) {
float val = std::get<float>(constFloat->getVal());
if (DEBUG) {
std::cout << "SCCP: Found constant float value: " << val << std::endl;
}
return SSAPValue(val);
} else {
// 存储的值不是常量检查其SCCP状态
SSAPValue storedState = GetValueState(storedValue);
if (storedState.state == LatticeVal::Constant) {
if (DEBUG) {
std::cout << "SCCP: Found SCCP constant value" << std::endl;
}
return storedState;
} else {
if (DEBUG) {
std::cout << "SCCP: Stored value is not constant" << std::endl;
}
}
}
// 找到了最近的Store但不是常量停止查找
if (DEBUG) {
std::cout << "SCCP: Found non-constant store, stopping search" << std::endl;
}
break;
}
}
}
if (DEBUG) {
std::cout << "SCCP: No constant value found" << std::endl;
}
return SSAPValue(LatticeVal::Bottom);
}
// 辅助函数动态检查数组访问是否为常量索引考虑SCCP状态
bool SCCPContext::hasRuntimeConstantAccess(Value *ptr) {
if (auto gep = dynamic_cast<GetElementPtrInst *>(ptr)) {
if (DEBUG) {
std::cout << "SCCP: Checking runtime constant access for GEP instruction" << std::endl;
}
// 检查所有索引是否为常量或SCCP传播的常量
bool allConstantIndices = true;
for (auto indexUse : gep->getIndices()) {
Value* index = indexUse->getValue();
// 首先检查是否为编译时常量
if (auto constInt = dynamic_cast<ConstantInteger *>(index)) {
if (DEBUG) {
std::cout << "SCCP: Index is compile-time constant integer: " << std::get<int>(constInt->getVal()) << std::endl;
}
continue;
}
if (auto constFloat = dynamic_cast<ConstantFloating *>(index)) {
if (DEBUG) {
std::cout << "SCCP: Index is compile-time constant float: " << std::get<float>(constFloat->getVal()) << std::endl;
}
continue;
}
// 检查是否为SCCP传播的常量
SSAPValue indexState = GetValueState(index);
if (indexState.state == LatticeVal::Constant) {
if (DEBUG) {
std::cout << "SCCP: Index is SCCP constant: ";
if (indexState.constant_type == ValueType::Integer) {
std::cout << std::get<int>(indexState.constantVal);
} else {
std::cout << std::get<float>(indexState.constantVal);
}
std::cout << std::endl;
}
continue;
}
// 如果任何一个索引不是常量返回false
if (DEBUG) {
std::cout << "SCCP: Index is not constant, access is not constant" << std::endl;
}
allConstantIndices = false;
break;
}
if (DEBUG) {
std::cout << "SCCP: hasRuntimeConstantAccess result: " << (allConstantIndices ? "true" : "false") << std::endl;
}
return allConstantIndices;
}
// 对于非GEP指令回退到别名分析的静态结果
if (aliasAnalysis) {
return aliasAnalysis->hasConstantAccess(ptr);
}
return false;
}
// 辅助函数:处理单条指令
void SCCPContext::ProcessInstruction(Instruction *inst) {
SSAPValue oldState = GetValueState(inst);
@ -280,6 +468,22 @@ void SCCPContext::ProcessInstruction(Instruction *inst) {
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:
@ -380,27 +584,237 @@ void SCCPContext::ProcessInstruction(Instruction *inst) {
break;
}
case Instruction::kLoad: {
// 对于 Load 指令,除非我们有特殊的别名分析,否则假定为 Bottom
// 或者如果它加载的是一个已知常量地址的全局常量
// 使用别名分析和副作用分析改进Load指令的处理
Value *ptr = inst->getOperand(0);
// 首先检查是否是全局常量
if (auto globalVal = dynamic_cast<GlobalValue *>(ptr)) {
// 如果 GlobalValue 有初始化器,并且它是常量,我们可以传播
// 这需要额外的逻辑来检查 globalVal 的初始化器
// 暂时保守地设置为 Bottom
// TODO: 检查全局变量的初始化器进行常量传播
newState = SSAPValue(LatticeVal::Bottom);
} else if (aliasAnalysis && sideEffectAnalysis) {
// 使用别名分析和副作用分析进行更精确的Load分析
if (aliasAnalysis->isLocalArray(ptr) && (aliasAnalysis->hasConstantAccess(ptr) || hasRuntimeConstantAccess(ptr))) {
// 对于局部数组的常量索引访问检查是否有影响该位置的Store
bool mayBeModified = false;
if (DEBUG) {
std::cout << "SCCP: Analyzing local array with constant access for modification" << std::endl;
}
// 遍历指令所在块之前的所有指令查找可能修改该内存位置的Store
BasicBlock *currentBB = inst->getParent();
auto instPos = currentBB->findInstIterator(inst);
SSAPValue foundConstantValue = SSAPValue(LatticeVal::Bottom);
bool hasFoundDefinitiveStore = false;
for (auto it = currentBB->begin(); it != instPos; ++it) {
Instruction *prevInst = it->get();
if (prevInst->isStore()) {
StoreInst *storeInst = static_cast<StoreInst *>(prevInst);
Value *storePtr = storeInst->getPointer();
// 使用别名分析判断Store是否可能影响当前Load
auto aliasResult = aliasAnalysis->queryAlias(ptr, storePtr);
if (DEBUG) {
std::cout << "SCCP: Checking store with alias result: " << (int)aliasResult << std::endl;
}
if (aliasResult == AliasType::SELF_ALIAS) {
// 找到对相同位置的精确Store
Value *storedValue = storeInst->getValue();
if (DEBUG) {
std::cout << "SCCP: Found exact store to same location, checking value" << std::endl;
}
// 检查存储的值是否为常量
if (auto constInt = dynamic_cast<ConstantInteger *>(storedValue)) {
int val = std::get<int>(constInt->getVal());
if (DEBUG) {
std::cout << "SCCP: Store contains constant integer: " << val << std::endl;
}
foundConstantValue = SSAPValue(val);
hasFoundDefinitiveStore = true;
// 继续遍历查找是否有更后面的Store覆盖这个值
} else if (auto constFloat = dynamic_cast<ConstantFloating *>(storedValue)) {
float val = std::get<float>(constFloat->getVal());
if (DEBUG) {
std::cout << "SCCP: Store contains constant float: " << val << std::endl;
}
foundConstantValue = SSAPValue(val);
hasFoundDefinitiveStore = true;
} else {
// 存储的值不是编译时常量检查其SCCP状态
SSAPValue storedState = GetValueState(storedValue);
if (storedState.state == LatticeVal::Constant) {
if (DEBUG) {
std::cout << "SCCP: Store contains SCCP constant" << std::endl;
}
foundConstantValue = storedState;
hasFoundDefinitiveStore = true;
} else {
if (DEBUG) {
std::cout << "SCCP: Store contains non-constant value" << std::endl;
}
// 非常量Store覆盖了之前的常量无法传播
foundConstantValue = SSAPValue(LatticeVal::Bottom);
hasFoundDefinitiveStore = true;
}
}
} else if (aliasResult != AliasType::NO_ALIAS) {
// 可能有别名,但不确定
if (DEBUG) {
std::cout << "SCCP: Found store with uncertain alias, stopping propagation" << std::endl;
}
mayBeModified = true;
break;
}
} else if (prevInst->isCall()) {
// 检查函数调用是否可能修改该内存位置
if (sideEffectAnalysis->mayModifyMemory(prevInst)) {
// 进一步检查是否可能影响局部数组
if (!aliasAnalysis->isLocalArray(ptr) ||
sideEffectAnalysis->mayModifyGlobal(prevInst)) {
mayBeModified = true;
break;
}
}
} else if (prevInst->isMemset()) {
// Memset指令可能影响内存但只有在它在相关Store之前时才阻止常量传播
MemsetInst *memsetInst = static_cast<MemsetInst *>(prevInst);
Value *memsetPtr = memsetInst->getOperand(0);
auto aliasResult = aliasAnalysis->queryAlias(ptr, memsetPtr);
if (aliasResult != AliasType::NO_ALIAS) {
// Memset可能影响这个位置但我们继续查找是否有Store覆盖了memset
// 不立即设置mayBeModified = true让后续的Store有机会覆盖
if (DEBUG) {
std::cout << "SCCP: Found memset that may affect location, but continuing to check for overwriting stores" << std::endl;
}
}
}
}
if (DEBUG) {
std::cout << "SCCP: mayBeModified = " << (mayBeModified ? "true" : "false") << std::endl;
std::cout << "SCCP: hasFoundDefinitiveStore = " << (hasFoundDefinitiveStore ? "true" : "false") << std::endl;
}
if (!mayBeModified) {
if (hasFoundDefinitiveStore && foundConstantValue.state == LatticeVal::Constant) {
// 直接使用找到的常量值
if (DEBUG) {
std::cout << "SCCP: Using found constant value from store analysis: ";
if (foundConstantValue.constant_type == ValueType::Integer) {
std::cout << std::get<int>(foundConstantValue.constantVal);
} else {
std::cout << std::get<float>(foundConstantValue.constantVal);
}
std::cout << std::endl;
}
newState = foundConstantValue;
} else {
// 如果没有发现修改该位置的指令尝试用旧方法找到对应的Store值
SSAPValue constantValue = findStoredConstantValue(ptr, inst->getParent());
if (constantValue.state == LatticeVal::Constant) {
if (DEBUG) {
std::cout << "SCCP: Found constant value for array load using fallback method: ";
if (constantValue.constant_type == ValueType::Integer) {
std::cout << std::get<int>(constantValue.constantVal);
} else {
std::cout << std::get<float>(constantValue.constantVal);
}
std::cout << std::endl;
}
newState = constantValue;
} else {
newState = SSAPValue(LatticeVal::Bottom);
}
}
} else {
newState = SSAPValue(LatticeVal::Bottom);
}
} else {
// 非局部数组或非常量访问,保守处理
newState = SSAPValue(LatticeVal::Bottom);
}
} else {
// 没有分析信息时保守处理
newState = SSAPValue(LatticeVal::Bottom);
}
if (DEBUG && aliasAnalysis && sideEffectAnalysis) {
std::cout << "SCCP: Load instruction analysis - "
<< (aliasAnalysis->isLocalArray(ptr) ? "local array" : "other")
<< ", static constant access: "
<< (aliasAnalysis->hasConstantAccess(ptr) ? "yes" : "no")
<< ", runtime constant access: "
<< (hasRuntimeConstantAccess(ptr) ? "yes" : "no") << std::endl;
}
break;
}
case Instruction::kStore:
// Store 指令不产生值,其 SSAPValue 不重要
newState = SSAPValue(); // 保持 Top
break;
case Instruction::kCall:
// 大多数 Call 指令都假定为 Bottom除非是纯函数且所有参数都是常量
newState = SSAPValue(LatticeVal::Bottom);
case Instruction::kCall: {
// 使用副作用分析改进Call指令处理
CallInst *callInst = static_cast<CallInst *>(inst);
if (sideEffectAnalysis) {
const auto &sideEffect = sideEffectAnalysis->getInstructionSideEffect(callInst);
// 检查是否为纯函数且所有参数都是常量
if (sideEffect.isPure && sideEffect.type == SideEffectType::NO_SIDE_EFFECT) {
// 对于纯函数,检查所有参数是否都是常量
bool allArgsConstant = true;
std::vector<SSAPValue> argValues;
for (unsigned i = 0; i < callInst->getNumOperands() - 1; ++i) { // 减1排除函数本身
SSAPValue argVal = GetValueState(callInst->getOperand(i));
argValues.push_back(argVal);
if (argVal.state != LatticeVal::Constant) {
allArgsConstant = false;
break;
}
}
if (allArgsConstant) {
// 对于参数全为常量的纯函数,可以尝试常量折叠
// 但由于实际执行函数比较复杂,这里先标记为可优化
// TODO: 实现具体的纯函数常量折叠
Function *calledFunc = callInst->getCallee();
if (calledFunc && isKnownPureFunction(calledFunc->getName())) {
// 对已知的纯函数进行常量计算
newState = computePureFunctionResult(callInst, argValues);
} else {
newState = SSAPValue(LatticeVal::Bottom);
}
} else {
// 参数不全是常量,但函数无副作用
newState = SSAPValue(LatticeVal::Bottom);
}
if (DEBUG) {
std::cout << "SCCP: Pure function call with "
<< (allArgsConstant ? "constant" : "non-constant") << " arguments" << std::endl;
}
} else {
// 有副作用的函数调用,保守处理
newState = SSAPValue(LatticeVal::Bottom);
if (DEBUG) {
std::cout << "SCCP: Function call with side effects" << std::endl;
}
}
} else {
// 没有副作用分析时保守处理所有Call
newState = SSAPValue(LatticeVal::Bottom);
}
break;
}
case Instruction::kGetElementPtr: {
// GEP 指令计算地址,通常其结果值(地址指向的内容)是 Bottom
// 除非所有索引和基指针都是常量,指向一个确定常量值的内存位置
@ -417,19 +831,71 @@ void SCCPContext::ProcessInstruction(Instruction *inst) {
}
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) {
Value *incomingVal = phi->getIncomingValue(i);
BasicBlock *incomingBlock = phi->getIncomingBlock(i);
if (executableBlocks.count(incomingBlock)) { // 仅考虑可执行前驱
phiResult = Meet(phiResult, GetValueState(incomingVal));
if (phiResult.state == LatticeVal::Bottom)
break; // 如果已经 Bottom则提前退出
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;
}
}
newState = phiResult;
break;
}
case Instruction::kAlloca: // 对应 kAlloca
@ -486,6 +952,22 @@ void SCCPContext::ProcessInstruction(Instruction *inst) {
}
}
}
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;
}
}
// 辅助函数:处理单条控制流边
@ -493,14 +975,22 @@ 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 指令,重新评估其值,因为可能有新的前驱被激活
for (auto &inst_ptr : toBB->getInstructions()) {
if (dynamic_cast<PhiInst *>(inst_ptr.get())) {
instWorkList.push(inst_ptr.get());
// 如果目标块之前就已经可执行那么需要重新处理其中的phi节点
// 因为现在有新的前驱变为可执行phi节点的值可能需要更新
if (wasAlreadyExecutable) {
for (auto &inst_ptr : toBB->getInstructions()) {
if (dynamic_cast<PhiInst *>(inst_ptr.get())) {
instWorkList.push(inst_ptr.get());
}
}
}
// 如果目标块是新变为可执行的MarkBlockExecutable已经添加了所有指令
}
// 阶段1: 常量传播与折叠
@ -515,18 +1005,29 @@ bool SCCPContext::PropagateConstants(Function *func) {
}
}
// 初始化函数参数为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();
@ -845,7 +1346,7 @@ void SCCPContext::RemovePhiIncoming(BasicBlock *phiParentBB, BasicBlock *removed
for (Instruction *inst : insts_to_check) {
if (auto phi = dynamic_cast<PhiInst *>(inst)) {
phi->delBlk(removedPred);
phi->removeIncomingBlock(removedPred);
}
}
}
@ -866,12 +1367,34 @@ bool SCCP::runOnFunction(Function *F, AnalysisManager &AM) {
if (DEBUG) {
std::cout << "Running SCCP on function: " << F->getName() << std::endl;
}
SCCPContext context(builder);
// 获取别名分析结果
if (auto *aliasResult = AM.getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(F)) {
context.setAliasAnalysis(aliasResult);
if (DEBUG) {
std::cout << "SCCP: Using alias analysis results" << std::endl;
}
}
// 获取副作用分析结果Module级别
if (auto *sideEffectResult = AM.getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>()) {
context.setSideEffectAnalysis(sideEffectResult);
if (DEBUG) {
std::cout << "SCCP: Using side effect analysis results" << std::endl;
}
}
context.run(F, AM);
return true;
}
void SCCP::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
// 声明依赖别名分析和副作用分析
analysisDependencies.insert(&SysYAliasAnalysisPass::ID);
analysisDependencies.insert(&SysYSideEffectAnalysisPass::ID);
// analysisInvalidations.insert(nullptr); // 表示使所有默认分析失效
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树可能受影响
analysisInvalidations.insert(&LivenessAnalysisPass::ID); // 活跃性分析很可能失效

View File

@ -42,7 +42,7 @@ bool SysYCFGOptUtils::SysYDelInstAfterBr(Function *func) {
++Branchiter;
while (Branchiter != instructions.end()) {
changed = true;
Branchiter = instructions.erase(Branchiter);
Branchiter = SysYIROptUtils::usedelete(Branchiter); // 删除指令
}
if (Branch) { // 更新前驱后继关系
@ -77,6 +77,11 @@ 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) {
// 如果当前块只有一个后继块
// 且后继块只有一个前驱块
@ -86,7 +91,7 @@ bool SysYCFGOptUtils::SysYBlockMerge(Function *func) {
BasicBlock *block = blockiter->get();
BasicBlock *nextBlock = blockiter->get()->getSuccessors()[0];
// auto nextarguments = nextBlock->getArguments();
// 删除br指令
// 删除block的br指令
if (block->getNumInstructions() != 0) {
auto thelastinstinst = block->terminator();
if (thelastinstinst->get()->isUnconditional()) {
@ -98,14 +103,21 @@ bool SysYCFGOptUtils::SysYBlockMerge(Function *func) {
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());
institer = nextBlock->getInstructions().erase(institer);
// 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);
@ -189,7 +201,7 @@ bool SysYCFGOptUtils::SysYDelNoPreBLock(Function *func) {
break;
}
// 将这个 Phi 节点中来自不可达前驱unreachableBlock的输入参数删除
dynamic_cast<PhiInst *>(phiInstPtr.get())->delBlk(unreachableBlock);
dynamic_cast<PhiInst *>(phiInstPtr.get())->removeIncomingBlock(unreachableBlock);
}
}
}
@ -288,13 +300,12 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
continue;
}
std::function<Value *(Value *, BasicBlock *)> getUltimateSourceValue = [&](Value *val,
BasicBlock *currentDefBlock) -> Value * {
// 如果值不是指令,例如常量或函数参数,则它本身就是最终来源
if (auto instr = dynamic_cast<Instruction *>(val)) { // Assuming Value* has a method to check if it's an instruction
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)) {
@ -311,7 +322,7 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
// 找到在空块链中导致 currentDefBlock 的那个前驱块
if (emptyBlockRedirectMap.count(incomingBlock) || incomingBlock == currentBlock) {
// 递归追溯该传入值
return getUltimateSourceValue(phi->getIncomingValue(incomingBlock), incomingBlock);
return getUltimateSourceValue(phi->getValfromBlk(incomingBlock), incomingBlock);
}
}
}
@ -354,7 +365,7 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
if (actualEmptyPredecessorOfS) {
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
Value *valueFromEmptyPredecessor = phiInst->getIncomingValue(actualEmptyPredecessorOfS);
Value *valueFromEmptyPredecessor = phiInst->getValfromBlk(actualEmptyPredecessorOfS);
// 追溯这个值,找到它在非空块中的最终来源
// currentBlock 是 P
@ -364,12 +375,13 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
// 替换 Phi 节点的传入块和传入值
if (ultimateSourceValue) { // 确保成功追溯到有效来源
phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, 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->removeIncoming(actualEmptyPredecessorOfS);
phiInst->getValfromBlk(actualEmptyPredecessorOfS);
}
}
} else {
@ -421,7 +433,7 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
if (actualEmptyPredecessorOfS) {
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
Value *valueFromEmptyPredecessor = phiInst->getIncomingValue(actualEmptyPredecessorOfS);
Value *valueFromEmptyPredecessor = phiInst->getValfromBlk(actualEmptyPredecessorOfS);
// 追溯这个值,找到它在非空块中的最终来源
// currentBlock 是 P
@ -431,12 +443,13 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
// 替换 Phi 节点的传入块和传入值
if (ultimateSourceValue) { // 确保成功追溯到有效来源
phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, 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->removeIncoming(actualEmptyPredecessorOfS);
phiInst->removeIncomingBlock(actualEmptyPredecessorOfS);
}
}
} else {
@ -481,7 +494,7 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
if (actualEmptyPredecessorOfS) {
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
Value *valueFromEmptyPredecessor = phiInst->getIncomingValue(actualEmptyPredecessorOfS);
Value *valueFromEmptyPredecessor = phiInst->getValfromBlk(actualEmptyPredecessorOfS);
// 追溯这个值,找到它在非空块中的最终来源
// currentBlock 是 P
@ -491,12 +504,13 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
// 替换 Phi 节点的传入块和传入值
if (ultimateSourceValue) { // 确保成功追溯到有效来源
phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, 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->removeIncoming(actualEmptyPredecessorOfS);
phiInst->removeIncomingBlock(actualEmptyPredecessorOfS);
}
}
} else {
@ -647,7 +661,7 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder *pBuilder) {
break;
}
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值
dynamic_cast<PhiInst *>(phiinst.get())->removeIncoming(basicblock.get());
dynamic_cast<PhiInst *>(phiinst.get())->removeIncomingBlock(basicblock.get());
}
} else { // cond为false或0
@ -665,7 +679,7 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder *pBuilder) {
break;
}
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值
dynamic_cast<PhiInst *>(phiinst.get())->removeIncoming(basicblock.get());
dynamic_cast<PhiInst *>(phiinst.get())->removeIncomingBlock(basicblock.get());
}
}
}

View File

@ -0,0 +1,125 @@
#include "TailCallOpt.h"
#include "IR.h"
#include "IRBuilder.h"
#include "SysYIROptUtils.h"
#include <vector>
// #include <iostream>
#include <algorithm>
namespace sysy {
void *TailCallOpt::ID = (void *)&TailCallOpt::ID;
void TailCallOpt::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID);
analysisInvalidations.insert(&LoopAnalysisPass::ID);
}
bool TailCallOpt::runOnFunction(Function *F, AnalysisManager &AM) {
std::vector<CallInst *> tailCallInsts;
// 遍历函数的所有基本块
for (auto &bb_ptr : F->getBasicBlocks()) {
auto BB = bb_ptr.get();
if (BB->getInstructions().empty()) continue; // 跳过空基本块
auto term_iter = BB->terminator();
if (term_iter == BB->getInstructions().end()) continue; // 没有终结指令则跳过
auto term = (*term_iter).get();
if (!term || !term->isReturn()) continue; // 不是返回指令则跳过
auto retInst = static_cast<ReturnInst *>(term);
Instruction *prevInst = nullptr;
if (BB->getInstructions().size() > 1) {
auto it = term_iter;
--it; // 获取返回指令前的指令
prevInst = (*it).get();
}
if (!prevInst || !prevInst->isCall()) continue; // 前一条不是调用指令则跳过
auto callInst = static_cast<CallInst *>(prevInst);
// 检查是否为尾递归调用:被调用函数与当前函数相同且返回值与调用结果匹配
if (callInst->getCallee() == F) {
// 对于尾递归,返回值应为调用结果或为 void 类型
if (retInst->getReturnValue() == callInst ||
(retInst->getReturnValue() == nullptr && callInst->getType()->isVoid())) {
tailCallInsts.push_back(callInst);
}
}
}
if (tailCallInsts.empty()) {
return false;
}
// 创建一个新的入口基本块,作为循环的前置块
auto original_entry = F->getEntryBlock();
auto new_entry = F->addBasicBlock("tco.entry." + F->getName());
auto loop_header = F->addBasicBlock("tco.loop_header." + F->getName());
// 将原入口块中的所有指令移动到循环头块
loop_header->getInstructions().splice(loop_header->end(), original_entry->getInstructions());
original_entry->setName("tco.pre_header");
// 为函数参数创建 phi 节点
builder->setPosition(loop_header, loop_header->begin());
std::vector<PhiInst *> phis;
auto original_args = F->getArguments();
for (auto &arg : original_args) {
auto phi = builder->createPhiInst(arg->getType(), {}, {}, "tco.phi."+arg->getName());
phis.push_back(phi);
}
// 用 phi 节点替换所有原始参数的使用
for (size_t i = 0; i < original_args.size(); ++i) {
original_args[i]->replaceAllUsesWith(phis[i]);
}
// 设置 phi 节点的输入值
for (size_t i = 0; i < phis.size(); ++i) {
phis[i]->addIncoming(original_args[i], new_entry);
}
// 连接各个基本块
builder->setPosition(original_entry, original_entry->end());
builder->createUncondBrInst(new_entry);
original_entry->addSuccessor(new_entry);
builder->setPosition(new_entry, new_entry->end());
builder->createUncondBrInst(loop_header);
new_entry->addSuccessor(loop_header);
loop_header->addPredecessor(new_entry);
// 处理每一个尾递归调用
for (auto callInst : tailCallInsts) {
auto tail_call_block = callInst->getParent();
// 收集尾递归调用的参数
auto args_range = callInst->getArguments();
std::vector<Value*> args;
std::transform(args_range.begin(), args_range.end(), std::back_inserter(args),
[](auto& use_ptr){ return use_ptr->getValue(); });
// 用新的参数值更新 phi 节点
for (size_t i = 0; i < phis.size(); ++i) {
phis[i]->addIncoming(args[i], tail_call_block);
}
// 移除原有的调用和返回指令
auto term_iter = tail_call_block->terminator();
SysYIROptUtils::usedelete(term_iter);
auto call_iter = tail_call_block->findInstIterator(callInst);
SysYIROptUtils::usedelete(call_iter);
// 添加跳转回循环头块的分支指令
builder->setPosition(tail_call_block, tail_call_block->end());
builder->createUncondBrInst(loop_header);
tail_call_block->addSuccessor(loop_header);
loop_header->addPredecessor(tail_call_block);
}
return true;
}
} // namespace sysy

View File

@ -1,11 +1,25 @@
#include "Dom.h"
#include "Liveness.h"
#include "Loop.h"
#include "LoopCharacteristics.h"
#include "AliasAnalysis.h"
#include "CallGraphAnalysis.h"
#include "SideEffectAnalysis.h"
#include "SysYIRCFGOpt.h"
#include "SysYIRPrinter.h"
#include "DCE.h"
#include "Mem2Reg.h"
#include "Reg2Mem.h"
#include "GVN.h"
#include "SCCP.h"
#include "BuildCFG.h"
#include "LargeArrayToGlobal.h"
#include "LoopNormalization.h"
#include "LICM.h"
#include "LoopStrengthReduction.h"
#include "InductionVariableElimination.h"
#include "GlobalStrengthReduction.h"
#include "TailCallOpt.h"
#include "Pass.h"
#include <iostream>
#include <queue>
@ -35,10 +49,22 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
3. 添加优化passid
*/
// 注册分析遍
registerAnalysisPass<DominatorTreeAnalysisPass>();
registerAnalysisPass<LivenessAnalysisPass>();
registerAnalysisPass<sysy::DominatorTreeAnalysisPass>();
registerAnalysisPass<sysy::LivenessAnalysisPass>();
registerAnalysisPass<SysYAliasAnalysisPass>(); // 别名分析 (优先级高)
registerAnalysisPass<CallGraphAnalysisPass>(); // 调用图分析 (Module级别独立分析)
registerAnalysisPass<SysYSideEffectAnalysisPass>(); // 副作用分析 (依赖别名分析和调用图)
registerAnalysisPass<LoopAnalysisPass>();
registerAnalysisPass<LoopCharacteristicsPass>(); // 循环特征分析依赖别名分析
// 注册优化遍
registerOptimizationPass<BuildCFG>();
registerOptimizationPass<LargeArrayToGlobalPass>();
registerOptimizationPass<GVN>();
registerOptimizationPass<SysYDelInstAfterBrPass>();
registerOptimizationPass<SysYDelNoPreBLockPass>();
registerOptimizationPass<SysYBlockMergePass>();
@ -49,7 +75,14 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
registerOptimizationPass<DCE>();
registerOptimizationPass<Mem2Reg>(builderIR);
registerOptimizationPass<LoopNormalizationPass>(builderIR);
registerOptimizationPass<LICM>(builderIR);
registerOptimizationPass<LoopStrengthReduction>(builderIR);
registerOptimizationPass<InductionVariableElimination>();
registerOptimizationPass<GlobalStrengthReduction>(builderIR);
registerOptimizationPass<Reg2Mem>(builderIR);
registerOptimizationPass<TailCallOpt>(builderIR);
registerOptimizationPass<SCCP>(builderIR);
@ -58,6 +91,16 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
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);
@ -67,6 +110,10 @@ 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();
@ -90,6 +137,25 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
printPasses();
}
this->clearPasses();
this->addPass(&GVN::ID);
this->run();
this->clearPasses();
this->addPass(&TailCallOpt::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After TailCallOpt ===\n";
SysYPrinter printer(moduleIR);
printer.printIR();
}
if(DEBUG) {
std::cout << "=== IR After GVN Optimizations ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&SCCP::ID);
this->run();
@ -99,6 +165,45 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
printPasses();
}
this->clearPasses();
this->addPass(&LoopNormalizationPass::ID);
this->addPass(&InductionVariableElimination::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After Loop Normalization, Induction Variable Elimination ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&LICM::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After LICM ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&LoopStrengthReduction::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After Loop Normalization, and Strength Reduction Optimizations ===\n";
printPasses();
}
// 全局强度削弱优化,包括代数优化和魔数除法
this->clearPasses();
this->addPass(&GlobalStrengthReduction::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After Global Strength Reduction Optimizations ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&Reg2Mem::ID);
this->run();
@ -107,7 +212,9 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
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";
}
@ -122,6 +229,7 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
SysYPrinter printer(moduleIR);
printer.printIR();
}
}
void PassManager::clearPasses() {

View File

@ -15,6 +15,139 @@
using namespace std;
namespace sysy {
std::pair<long long, int> calculate_signed_magic(int d) {
if (d == 0) throw std::runtime_error("Division by zero");
if (d == 1 || d == -1) return {0, 0}; // Not used by strength reduction
int k = 0;
unsigned int ad = (d > 0) ? d : -d;
unsigned int temp = ad;
while (temp > 0) {
temp >>= 1;
k++;
}
if ((ad & (ad - 1)) == 0) { // if power of 2
k--;
}
unsigned __int128 m_val = 1;
m_val <<= (32 + k - 1);
unsigned __int128 m_prime = m_val / ad;
long long m = m_prime + 1;
return {m, k};
}
// 清除因函数调用而失效的表达式缓存(保守策略)
void SysYIRGenerator::invalidateExpressionsOnCall() {
availableBinaryExpressions.clear();
availableUnaryExpressions.clear();
availableLoads.clear();
availableGEPs.clear();
}
// 在进入新的基本块时清空所有表达式缓存
void SysYIRGenerator::enterNewBasicBlock() {
availableBinaryExpressions.clear();
availableUnaryExpressions.clear();
availableLoads.clear();
availableGEPs.clear();
}
// 清除因变量赋值而失效的表达式缓存
// @param storedAddress: store 指令的目标地址 (例如 AllocaInst* 或 GEPInst*)
void SysYIRGenerator::invalidateExpressionsOnStore(Value *storedAddress) {
// 遍历二元表达式缓存,移除受影响的条目
// 创建一个临时列表来存储要移除的键,避免在迭代时修改容器
std::vector<ExpKey> binaryKeysToRemove;
for (const auto &pair : availableBinaryExpressions) {
// 检查左操作数
// 如果左操作数是 LoadInst并且它从 storedAddress 加载
if (auto loadInst = dynamic_cast<LoadInst *>(pair.first.left)) {
if (loadInst->getPointer() == storedAddress) {
binaryKeysToRemove.push_back(pair.first);
continue; // 这个表达式已标记为移除,跳到下一个
}
}
// 如果左操作数本身就是被存储的地址 (例如,将一个地址值直接作为操作数,虽然不常见)
if (pair.first.left == storedAddress) {
binaryKeysToRemove.push_back(pair.first);
continue;
}
// 检查右操作数,逻辑同左操作数
if (auto loadInst = dynamic_cast<LoadInst *>(pair.first.right)) {
if (loadInst->getPointer() == storedAddress) {
binaryKeysToRemove.push_back(pair.first);
continue;
}
}
if (pair.first.right == storedAddress) {
binaryKeysToRemove.push_back(pair.first);
continue;
}
}
// 实际移除条目
for (const auto &key : binaryKeysToRemove) {
availableBinaryExpressions.erase(key);
}
// 遍历一元表达式缓存,移除受影响的条目
std::vector<UnExpKey> unaryKeysToRemove;
for (const auto &pair : availableUnaryExpressions) {
// 检查操作数
if (auto loadInst = dynamic_cast<LoadInst *>(pair.first.operand)) {
if (loadInst->getPointer() == storedAddress) {
unaryKeysToRemove.push_back(pair.first);
continue;
}
}
if (pair.first.operand == storedAddress) {
unaryKeysToRemove.push_back(pair.first);
continue;
}
}
// 实际移除条目
for (const auto &key : unaryKeysToRemove) {
availableUnaryExpressions.erase(key);
}
availableLoads.erase(storedAddress);
std::vector<GEPKey> gepKeysToRemove;
for (const auto &pair : availableGEPs) {
// 检查 GEP 的基指针是否受存储影响
if (auto loadInst = dynamic_cast<LoadInst *>(pair.first.basePointer)) {
if (loadInst->getPointer() == storedAddress) {
gepKeysToRemove.push_back(pair.first);
continue; // 标记此GEP为移除跳过后续检查
}
}
// 如果基指针本身就是存储的目标地址 (不常见,但可能)
if (pair.first.basePointer == storedAddress) {
gepKeysToRemove.push_back(pair.first);
continue;
}
// 检查 GEP 的每个索引是否受存储影响
for (const auto &indexVal : pair.first.indices) {
if (auto loadInst = dynamic_cast<LoadInst *>(indexVal)) {
if (loadInst->getPointer() == storedAddress) {
gepKeysToRemove.push_back(pair.first);
break; // 标记此GEP为移除并跳出内部循环
}
}
// 如果索引本身就是存储的目标地址
if (indexVal == storedAddress) {
gepKeysToRemove.push_back(pair.first);
break;
}
}
}
// 实际移除条目
for (const auto &key : gepKeysToRemove) {
availableGEPs.erase(key);
}
}
// std::vector<Value*> BinaryValueStack; ///< 用于存储value的栈
// std::vector<int> BinaryOpStack; ///< 用于存储二元表达式的操作符栈
@ -244,27 +377,37 @@ void SysYIRGenerator::compute() {
}
} else {
// 否则创建相应的IR指令
if (commonType == Type::getIntType()) {
switch (op) {
case BinaryOp::ADD: resultValue = builder.createAddInst(lhs, rhs); break;
case BinaryOp::SUB: resultValue = builder.createSubInst(lhs, rhs); break;
case BinaryOp::MUL: resultValue = builder.createMulInst(lhs, rhs); break;
case BinaryOp::DIV: resultValue = builder.createDivInst(lhs, rhs); break;
case BinaryOp::MOD: resultValue = builder.createRemInst(lhs, rhs); break;
}
} else if (commonType == Type::getFloatType()) {
switch (op) {
case BinaryOp::ADD: resultValue = builder.createFAddInst(lhs, rhs); break;
case BinaryOp::SUB: resultValue = builder.createFSubInst(lhs, rhs); break;
case BinaryOp::MUL: resultValue = builder.createFMulInst(lhs, rhs); break;
case BinaryOp::DIV: resultValue = builder.createFDivInst(lhs, rhs); break;
case BinaryOp::MOD:
std::cerr << "Error: Modulo operator not supported for float types." << std::endl;
ExpKey currentExpKey(static_cast<BinaryOp>(op), lhs, rhs);
auto it = availableBinaryExpressions.find(currentExpKey);
if (it != availableBinaryExpressions.end()) {
// 在缓存中找到,重用结果
resultValue = it->second;
} else {
if (commonType == Type::getIntType()) {
switch (op) {
case BinaryOp::ADD: resultValue = builder.createAddInst(lhs, rhs); break;
case BinaryOp::SUB: resultValue = builder.createSubInst(lhs, rhs); break;
case BinaryOp::MUL: resultValue = builder.createMulInst(lhs, rhs); break;
case BinaryOp::DIV: resultValue = builder.createDivInst(lhs, rhs); break;
case BinaryOp::MOD: resultValue = builder.createRemInst(lhs, rhs); break;
}
} else if (commonType == Type::getFloatType()) {
switch (op) {
case BinaryOp::ADD: resultValue = builder.createFAddInst(lhs, rhs); break;
case BinaryOp::SUB: resultValue = builder.createFSubInst(lhs, rhs); break;
case BinaryOp::MUL: resultValue = builder.createFMulInst(lhs, rhs); break;
case BinaryOp::DIV: resultValue = builder.createFDivInst(lhs, rhs); break;
case BinaryOp::MOD:
std::cerr << "Error: Modulo operator not supported for float types." << std::endl;
return;
}
} else {
std::cerr << "Error: Unsupported type for binary instruction." << std::endl;
return;
}
} else {
std::cerr << "Error: Unsupported type for binary instruction." << std::endl;
return;
// 将新创建的指令结果添加到缓存
availableBinaryExpressions[currentExpKey] = resultValue;
}
}
break;
@ -316,36 +459,45 @@ void SysYIRGenerator::compute() {
return;
}
} else {
// 否则创建相应的IR指令
switch (op) {
case BinaryOp::PLUS:
resultValue = operand; // 一元加指令通常直接返回操作数
break;
case BinaryOp::NEG: {
if (commonType == sysy::Type::getIntType()) {
resultValue = builder.createNegInst(operand);
} else if (commonType == sysy::Type::getFloatType()) {
resultValue = builder.createFNegInst(operand);
} else {
std::cerr << "Error: Negation not supported for operand type." << std::endl;
return;
// 否则创建相应的IR指令 (在这里应用CSE)
UnExpKey currentUnExpKey(static_cast<BinaryOp>(op), operand);
auto it = availableUnaryExpressions.find(currentUnExpKey);
if (it != availableUnaryExpressions.end()) {
// 在缓存中找到,重用结果
resultValue = it->second;
} else {
switch (op) {
case BinaryOp::PLUS:
resultValue = operand; // 一元加指令通常直接返回操作数
break;
case BinaryOp::NEG: {
if (commonType == sysy::Type::getIntType()) {
resultValue = builder.createNegInst(operand);
} else if (commonType == sysy::Type::getFloatType()) {
resultValue = builder.createFNegInst(operand);
} else {
std::cerr << "Error: Negation not supported for operand type." << std::endl;
return;
}
break;
}
case BinaryOp::NOT:
// 逻辑非
if (commonType == sysy::Type::getIntType()) {
resultValue = builder.createNotInst(operand);
} else if (commonType == sysy::Type::getFloatType()) {
resultValue = builder.createFNotInst(operand);
} else {
std::cerr << "Error: Logical NOT not supported for operand type." << std::endl;
return;
}
break;
default:
std::cerr << "Error: Unknown unary operator for instructions: " << op << std::endl;
return;
}
break;
}
case BinaryOp::NOT:
// 逻辑非
if (commonType == sysy::Type::getIntType()) {
resultValue = builder.createNotInst(operand);
} else if (commonType == sysy::Type::getFloatType()) {
resultValue = builder.createFNotInst(operand);
} else {
std::cerr << "Error: Logical NOT not supported for operand type." << std::endl;
return;
}
break;
default:
std::cerr << "Error: Unknown unary operator for instructions: " << op << std::endl;
return;
// 将新创建的指令结果添加到缓存
availableUnaryExpressions[currentUnExpKey] = resultValue;
}
}
break;
@ -487,7 +639,19 @@ Value* SysYIRGenerator::getGEPAddressInst(Value* basePointer, const std::vector<
// `indices` 向量现在由调用方(如 visitLValue, visitVarDecl, visitAssignStmt负责完整准备
// 包括是否需要添加初始的 `0` 索引。
// 所以这里直接将其传递给 `builder.createGetElementPtrInst`。
return builder.createGetElementPtrInst(basePointer, indices);
GEPKey key = {basePointer, indices};
// 尝试从缓存中查找
auto it = availableGEPs.find(key);
if (it != availableGEPs.end()) {
return it->second; // 缓存命中,返回已有的 GEPInst*
}
// 缓存未命中,创建新的 GEPInst
Value* gepInst = builder.createGetElementPtrInst(basePointer, indices); // 假设 builder 提供了 createGEPInst 方法
availableGEPs[key] = gepInst; // 将新的 GEPInst* 加入缓存
return gepInst;
}
/*
@ -586,7 +750,13 @@ std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext *ctx) {
// 显式地为局部常量在栈上分配空间
// alloca 的类型将是指针指向常量类型,例如 `int*` 或 `int[2][3]*`
// 将alloca全部集中到entry中
auto entry = builder.getBasicBlock()->getParent()->getEntryBlock();
auto it = builder.getPosition();
auto nowblk = builder.getBasicBlock();
builder.setPosition(entry, entry->terminator());
AllocaInst *alloca = builder.createAllocaInst(Type::getPointerType(variableType), name);
builder.setPosition(nowblk, it);
ArrayValueTree *root = std::any_cast<ArrayValueTree *>(constDef->constInitVal()->accept(this));
ValueCounter values;
@ -743,8 +913,12 @@ std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx) {
// 对于数组alloca 的类型将是指针指向数组类型,例如 `int[2][3]*`
// 对于标量alloca 的类型将是指针指向标量类型,例如 `int*`
AllocaInst* alloca =
builder.createAllocaInst(Type::getPointerType(variableType), name);
auto entry = builder.getBasicBlock()->getParent()->getEntryBlock();
auto it = builder.getPosition();
auto nowblk = builder.getBasicBlock();
builder.setPosition(entry, entry->terminator());
AllocaInst *alloca = builder.createAllocaInst(Type::getPointerType(variableType), name);
builder.setPosition(nowblk, it);
if (varDef->initVal() != nullptr) {
ValueCounter values;
@ -946,6 +1120,8 @@ std::any SysYIRGenerator::visitFuncType(SysYParser::FuncTypeContext *ctx) {
std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
// 更新作用域
module->enterNewScope();
// 清除CSE缓存
enterNewBasicBlock();
auto name = ctx->Ident()->getText();
std::vector<Type *> paramActualTypes;
@ -1015,15 +1191,25 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
for(int i = 0; i < paramActualTypes.size(); ++i) {
Argument* arg = new Argument(paramActualTypes[i], function, i, paramNames[i]);
function->insertArgument(arg);
}
// 先将所有参数名字注册到符号表中确保alloca不会使用相同的名字
for (int i = 0; i < paramNames.size(); ++i) {
// 预先注册参数名字这样addVariable就会使用不同的后缀
module->registerParameterName(paramNames[i]);
}
auto funcArgs = function->getArguments();
std::vector<AllocaInst *> allocas;
for (int i = 0; i < paramActualTypes.size(); ++i) {
AllocaInst *alloca = builder.createAllocaInst(Type::getPointerType(paramActualTypes[i]), paramNames[i]);
// 使用函数特定的前缀来确保参数alloca名字唯一
std::string allocaName = name + "_param_" + paramNames[i];
AllocaInst *alloca = builder.createAllocaInst(Type::getPointerType(paramActualTypes[i]), allocaName);
// 直接设置唯一名字不依赖addVariable的命名逻辑
alloca->setName(allocaName);
allocas.push_back(alloca);
module->addVariable(paramNames[i], alloca);
// 直接添加到符号表,使用原参数名作为查找键
module->addVariableDirectly(paramNames[i], alloca);
}
for(int i = 0; i < paramActualTypes.size(); ++i) {
@ -1037,6 +1223,7 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
// 从 entryBB 无条件跳转到 funcBodyEntry
builder.createUncondBrInst(funcBodyEntry);
BasicBlock::conectBlocks(entry, funcBodyEntry); // 连接 entryBB 和 funcBodyEntry
builder.setPosition(funcBodyEntry,funcBodyEntry->end()); // 将插入点设置到 funcBodyEntry
for (auto item : ctx->blockStmt()->blockItem()) {
@ -1091,6 +1278,45 @@ std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) {
if (dynamic_cast<AllocaInst*>(variable) || dynamic_cast<GlobalValue*>(variable)) {
LValue = variable;
}
// 标量变量的类型推断
Type* LType = builder.getIndexedType(variable->getType(), indices);
Value* RValue = computeExp(ctx->exp(), LType); // 右值计算
Type* RType = RValue->getType();
// TODO:computeExp处理了类型转换可以考虑删除判断逻辑
if (LType != RType) {
ConstantValue *constValue = dynamic_cast<ConstantValue *>(RValue);
if (constValue != nullptr) {
if (LType == Type::getFloatType()) {
if(dynamic_cast<ConstantInteger *>(constValue)) {
// 如果是整型常量,转换为浮点型
RValue = ConstantFloating::get(static_cast<float>(constValue->getInt()));
} else if (dynamic_cast<ConstantFloating *>(constValue)) {
// 如果是浮点型常量,直接使用
RValue = ConstantFloating::get(static_cast<float>(constValue->getFloat()));
}
} else { // 假设如果不是浮点型,就是整型
if(dynamic_cast<ConstantFloating *>(constValue)) {
// 如果是浮点型常量,转换为整型
RValue = ConstantInteger::get(static_cast<int>(constValue->getFloat()));
} else if (dynamic_cast<ConstantInteger *>(constValue)) {
// 如果是整型常量,直接使用
RValue = ConstantInteger::get(static_cast<int>(constValue->getInt()));
}
}
} else {
if (LType == Type::getFloatType() && RType != Type::getFloatType()) {
RValue = builder.createItoFInst(RValue);
} else if (LType != Type::getFloatType() && RType == Type::getFloatType()) {
RValue = builder.createFtoIInst(RValue);
}
// 如果两者都是同一类型,就不需要转换
}
}
builder.createStoreInst(RValue, LValue);
}
else {
// 对于数组或多维数组的左值处理
@ -1100,7 +1326,16 @@ std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) {
if (AllocaInst *alloc = dynamic_cast<AllocaInst *>(variable)) {
Type* allocatedType = alloc->getType()->as<PointerType>()->getBaseType();
if (allocatedType->isPointer()) {
gepBasePointer = builder.createLoadInst(alloc);
// 尝试从缓存中获取 builder.createLoadInst(alloc) 的结果
auto it = availableLoads.find(alloc);
if (it != availableLoads.end()) {
gepBasePointer = it->second; // 缓存命中,重用
} else {
gepBasePointer = builder.createLoadInst(alloc); // 缓存未命中,创建新的 LoadInst
availableLoads[alloc] = gepBasePointer; // 将结果加入缓存
}
// --- CSE 结束 ---
// gepBasePointer = builder.createLoadInst(alloc);
gepIndices = indices;
} else {
gepBasePointer = alloc;
@ -1119,52 +1354,48 @@ std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) {
}
// 左值为地址
LValue = getGEPAddressInst(gepBasePointer, gepIndices);
}
// 数组变量的类型推断使用gepIndices和gepBasePointer的类型
Type* LType = builder.getIndexedType(gepBasePointer->getType(), gepIndices);
Value* RValue = computeExp(ctx->exp(), LType); // 右值计算
Type* RType = RValue->getType();
// Value* RValue = std::any_cast<Value *>(visitExp(ctx->exp())); // 右值
// 先推断 LValue 的类型
// 如果 LValue 是指向数组的指针,则需要根据 indices 获取正确的类型
// 如果 LValue 是标量,则直接使用其类型
// 注意LValue 的类型可能是指向数组的指针 (e.g., int(*)[3]) 或者指向标量的指针 (e.g., int*) 也能推断
Type* LType = builder.getIndexedType(variable->getType(), indices);
Value* RValue = computeExp(ctx->exp(), LType); // 右值计算
Type* RType = RValue->getType();
// TODO:computeExp处理了类型转换可以考虑删除判断逻辑
if (LType != RType) {
ConstantValue *constValue = dynamic_cast<ConstantValue *>(RValue);
if (constValue != nullptr) {
if (LType == Type::getFloatType()) {
if(dynamic_cast<ConstantInteger *>(constValue)) {
// 如果是整型常量,转换为浮点型
RValue = ConstantFloating::get(static_cast<float>(constValue->getInt()));
} else if (dynamic_cast<ConstantFloating *>(constValue)) {
// 如果是浮点型常量,直接使用
RValue = ConstantFloating::get(static_cast<float>(constValue->getFloat()));
// TODO:computeExp处理了类型转换可以考虑删除判断逻辑
if (LType != RType) {
ConstantValue *constValue = dynamic_cast<ConstantValue *>(RValue);
if (constValue != nullptr) {
if (LType == Type::getFloatType()) {
if(dynamic_cast<ConstantInteger *>(constValue)) {
// 如果是整型常量,转换为浮点型
RValue = ConstantFloating::get(static_cast<float>(constValue->getInt()));
} else if (dynamic_cast<ConstantFloating *>(constValue)) {
// 如果是浮点型常量,直接使用
RValue = ConstantFloating::get(static_cast<float>(constValue->getFloat()));
}
} else { // 假设如果不是浮点型,就是整型
if(dynamic_cast<ConstantFloating *>(constValue)) {
// 如果是浮点型常量,转换为整型
RValue = ConstantInteger::get(static_cast<int>(constValue->getFloat()));
} else if (dynamic_cast<ConstantInteger *>(constValue)) {
// 如果是整型常量,直接使用
RValue = ConstantInteger::get(static_cast<int>(constValue->getInt()));
}
}
} else { // 假设如果不是浮点型,就是整型
if(dynamic_cast<ConstantFloating *>(constValue)) {
// 如果是浮点型常量,转换为整型
RValue = ConstantInteger::get(static_cast<int>(constValue->getFloat()));
} else if (dynamic_cast<ConstantInteger *>(constValue)) {
// 如果是整型常量,直接使用
RValue = ConstantInteger::get(static_cast<int>(constValue->getInt()));
} else {
if (LType == Type::getFloatType() && RType != Type::getFloatType()) {
RValue = builder.createItoFInst(RValue);
} else if (LType != Type::getFloatType() && RType == Type::getFloatType()) {
RValue = builder.createFtoIInst(RValue);
}
}
} else {
if (LType == Type::getFloatType()) {
RValue = builder.createItoFInst(RValue);
} else { // 假设如果不是浮点型,就是整型
RValue = builder.createFtoIInst(RValue);
// 如果两者都是同一类型,就不需要转换
}
}
builder.createStoreInst(RValue, LValue);
}
builder.createStoreInst(RValue, LValue);
invalidateExpressionsOnStore(LValue);
return std::any();
}
@ -1201,7 +1432,9 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
labelstring.str("");
function->addBasicBlock(thenBlock);
builder.setPosition(thenBlock, thenBlock->end());
// CSE清除缓存
enterNewBasicBlock();
auto block = dynamic_cast<SysYParser::BlockStmtContext *>(ctx->stmt(0));
// 如果是块语句,直接访问
// 否则访问语句
@ -1220,7 +1453,9 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
labelstring.str("");
function->addBasicBlock(elseBlock);
builder.setPosition(elseBlock, elseBlock->end());
// CSE清除缓存
enterNewBasicBlock();
block = dynamic_cast<SysYParser::BlockStmtContext *>(ctx->stmt(1));
if (block != nullptr) {
visitBlockStmt(block);
@ -1237,7 +1472,9 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
labelstring.str("");
function->addBasicBlock(exitBlock);
builder.setPosition(exitBlock, exitBlock->end());
// CSE清除缓存
enterNewBasicBlock();
} else {
builder.pushTrueBlock(thenBlock);
builder.pushFalseBlock(exitBlock);
@ -1250,7 +1487,9 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
labelstring.str("");
function->addBasicBlock(thenBlock);
builder.setPosition(thenBlock, thenBlock->end());
// CSE清除缓存
enterNewBasicBlock();
auto block = dynamic_cast<SysYParser::BlockStmtContext *>(ctx->stmt(0));
if (block != nullptr) {
visitBlockStmt(block);
@ -1267,6 +1506,9 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
labelstring.str("");
function->addBasicBlock(exitBlock);
builder.setPosition(exitBlock, exitBlock->end());
// CSE清除缓存
enterNewBasicBlock();
}
return std::any();
}
@ -1284,7 +1526,9 @@ std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
builder.createUncondBrInst(headBlock);
BasicBlock::conectBlocks(curBlock, headBlock);
builder.setPosition(headBlock, headBlock->end());
// CSE清除缓存
enterNewBasicBlock();
BasicBlock* bodyBlock = new BasicBlock(function);
BasicBlock* exitBlock = new BasicBlock(function);
@ -1300,6 +1544,8 @@ std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
labelstring.str("");
function->addBasicBlock(bodyBlock);
builder.setPosition(bodyBlock, bodyBlock->end());
// CSE清除缓存
enterNewBasicBlock();
builder.pushBreakBlock(exitBlock);
builder.pushContinueBlock(headBlock);
@ -1315,7 +1561,7 @@ std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
}
builder.createUncondBrInst(headBlock);
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
BasicBlock::conectBlocks(builder.getBasicBlock(), headBlock);
builder.popBreakBlock();
builder.popContinueBlock();
@ -1324,7 +1570,9 @@ std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
labelstring.str("");
function->addBasicBlock(exitBlock);
builder.setPosition(exitBlock, exitBlock->end());
// CSE清除缓存
enterNewBasicBlock();
return std::any();
}
@ -1430,90 +1678,101 @@ std::any SysYIRGenerator::visitLValue(SysYParser::LValueContext *ctx) {
break;
}
}
if (allIndicesConstant) {
// 如果是常量变量且所有索引都是常量,并且不是数组名单独出现的情况
if (allIndicesConstant && !dims.empty()) {
// 如果是常量变量且所有索引都是常量,直接通过 getByIndices 获取编译时值
// 这个方法会根据索引深度返回最终的标量值或指向子数组的指针 (作为 ConstantValue/Variable)
return constVar->getByIndices(dims);
}
// 如果dims为空检查是否是常量标量
if (dims.empty() && declaredNumDims == 0) {
// 常量标量,直接返回其值
// 默认传入空索引列表,表示访问标量本身
return constVar->getByIndices(dims);
}
// 如果dims为空但不是标量数组名单独出现需要走GEP路径来实现数组到指针的退化
}
// 3. 处理可变变量 (AllocaInst/GlobalValue) 或带非常量索引的常量变量
// 这里区分标量访问和数组元素/子数组访问
Value *targetAddress = nullptr;
// 检查是否是访问标量变量本身没有索引且声明维度为0
if (dims.empty() && declaredNumDims == 0) {
// 对于标量变量,直接加载其值。
// variable 本身就是指向标量的指针 (e.g., int* %a)
if (dynamic_cast<AllocaInst*>(variable) || dynamic_cast<GlobalValue*>(variable)) {
value = builder.createLoadInst(variable);
} else {
// 如果走到这里且不是AllocaInst/GlobalValue但dims为空且declaredNumDims为0
// 且又不是ConstantVariable (前面已处理),则可能是错误情况。
targetAddress = variable;
}
else {
assert(false && "Unhandled scalar variable type in LValue access.");
return static_cast<Value*>(nullptr);
}
} else {
// 访问数组元素或子数组(有索引,或变量本身是数组/多维指针)
Value* gepBasePointer = nullptr;
std::vector<Value*> gepIndices; // 准备传递给 getGEPAddressInst 的索引列表
// GEP 的基指针就是变量本身(它是一个指向内存的指针)
std::vector<Value*> gepIndices;
if (AllocaInst *alloc = dynamic_cast<AllocaInst *>(variable)) {
// 情况 A: 局部变量 (AllocaInst)
// 获取 AllocaInst 分配的内存的实际类型。
// 例如:对于 `int b[10][20];``allocatedType` 是 `[10 x [20 x i32]]`。
// 对于 `int b[][20]` 的函数参数,其 AllocaInst 存储的是一个指针,
// 此时 `allocatedType` 是 `[20 x i32]*`。
Type* allocatedType = alloc->getType()->as<PointerType>()->getBaseType();
if (allocatedType->isPointer()) {
// 如果 AllocaInst 分配的是一个指针类型 (例如,用于存储函数参数的指针,如 int b[][20] 中的 b)
// 即 `allocatedType` 是一个指向数组指针的指针 (e.g., [20 x i32]**)
// 那么 GEP 的基指针是加载这个指针变量的值。
gepBasePointer = builder.createLoadInst(alloc); // 加载出实际的指针值 (e.g., [20 x i32]*)
// 对于这种参数指针,用户提供的索引直接作用于它。不需要额外的 0。
gepBasePointer = builder.createLoadInst(alloc);
gepIndices = dims;
} else {
// 如果 AllocaInst 分配的是实际的数组数据 (例如int b[10][20] 中的 b)
// 那么 AllocaInst 本身就是 GEP 的基指针。
// 这里的 `alloc` 是指向数组的指针 (e.g., [10 x [20 x i32]]*)
gepBasePointer = alloc; // 类型是 [10 x [20 x i32]]*
// 对于这种完整的数组分配GEP 的第一个索引必须是 0用于“步过”整个数组。
gepBasePointer = alloc;
gepIndices.push_back(ConstantInteger::get(0));
gepIndices.insert(gepIndices.end(), dims.begin(), dims.end());
if (dims.empty() && declaredNumDims > 0) {
// 数组名单独出现没有索引在SysY中多维数组名应该退化为指向第一行的指针
// 对于二维数组 T[M][N],退化为 T(*)[N]需要GEP: getelementptr T[M][N], T[M][N]* ptr, i32 0, i32 0
// 第一个i32 0: 选择数组本身第二个i32 0: 选择第0行
// 结果类型: T[N]*
gepIndices.push_back(ConstantInteger::get(0));
} else {
// 正常的数组元素访问
gepIndices.insert(gepIndices.end(), dims.begin(), dims.end());
}
}
} else if (GlobalValue *glob = dynamic_cast<GlobalValue *>(variable)) {
// 情况 B: 全局变量 (GlobalValue)
// GlobalValue 总是指向全局数据的指针。
gepBasePointer = glob; // 类型是 [61 x [67 x i32]]*
// 对于全局数组GEP 的第一个索引必须是 0用于“步过”整个数组。
gepBasePointer = glob;
gepIndices.push_back(ConstantInteger::get(0));
gepIndices.insert(gepIndices.end(), dims.begin(), dims.end());
if (dims.empty() && declaredNumDims > 0) {
// 全局数组名单独出现(没有索引):应该退化为指向第一行的指针
// 需要添加一个额外的i32 0索引
gepIndices.push_back(ConstantInteger::get(0));
} else {
// 正常的数组元素访问
gepIndices.insert(gepIndices.end(), dims.begin(), dims.end());
}
} else if (ConstantVariable *constV = dynamic_cast<ConstantVariable *>(variable)) {
// 情况 C: 常量变量 (ConstantVariable),如果它代表全局数组常量
// 假设 ConstantVariable 可以直接作为 GEP 的基指针。
gepBasePointer = constV;
// 对于常量数组,也需要 0 索引来“步过”整个数组。
// 这里可以进一步检查 constV->getType()->as<PointerType>()->getBaseType()->isArray()
// 但为了简洁,假设所有 ConstantVariable 作为 GEP 基指针时都需要此 0。
gepIndices.push_back(ConstantInteger::get(0));
gepIndices.insert(gepIndices.end(), dims.begin(), dims.end());
if (dims.empty() && declaredNumDims > 0) {
// 常量数组名单独出现(没有索引):应该退化为指向第一行的指针
// 需要添加一个额外的i32 0索引
gepIndices.push_back(ConstantInteger::get(0));
} else {
// 正常的数组元素访问
gepIndices.insert(gepIndices.end(), dims.begin(), dims.end());
}
} else {
assert(false && "LValue variable type not supported for GEP base pointer.");
return static_cast<Value *>(nullptr);
}
// 现在调用 getGEPAddressInst传入正确准备的基指针和索引列表
Value *targetAddress = getGEPAddressInst(gepBasePointer, gepIndices);
targetAddress = getGEPAddressInst(gepBasePointer, gepIndices);
// 如果提供的索引数量少于声明的维度数量,则表示访问的是子数组,返回其地址
if (dims.size() < declaredNumDims) {
value = targetAddress;
}
// 如果提供的索引数量少于声明的维度数量,则表示访问的是子数组,返回其地址 (无需加载)
if (dims.size() < declaredNumDims) {
value = targetAddress;
} else {
// value = builder.createLoadInst(targetAddress);
auto it = availableLoads.find(targetAddress);
if (it != availableLoads.end()) {
value = it->second; // 缓存命中,重用已有的 LoadInst 结果
} else {
// 否则,表示访问的是最终的标量元素,加载其值
// 假设 createLoadInst 接受 Value* pointer
value = builder.createLoadInst(targetAddress);
// 缓存未命中,创建新的 LoadInst
value = builder.createLoadInst(targetAddress);
availableLoads[targetAddress] = value; // 将新的 LoadInst 结果加入缓存
}
}
return value;
}
@ -1571,10 +1830,10 @@ std::any SysYIRGenerator::visitCall(SysYParser::CallContext *ctx) {
// 获取形参列表。`getArguments()` 返回的是 `Argument*` 的集合,
// 每个 `Argument` 代表一个函数形参,其 `getType()` 就是指向形参的类型的指针类型。
auto formalParams = function->getArguments();
const auto& formalParams = function->getArguments();
// 检查实参和形参数量是否匹配。
if (args.size() != formalParams.size()) {
if (args.size() != function->getNumArguments()) {
std::cerr << "Error: Function call argument count mismatch for function '" << funcName << "'." << std::endl;
assert(false && "Function call argument count mismatch!");
}
@ -1606,15 +1865,27 @@ std::any SysYIRGenerator::visitCall(SysYParser::CallContext *ctx) {
} else if (formalParamExpectedValueType->isFloat() && actualArgType->isInt()) {
args[i] = builder.createItoFInst(args[i]);
}
// 2. 指针类型转换 (例如数组退化:`[N x T]*` 到 `T*`,或兼容指针类型之间) TODO不清楚有没有这种样例
// 2. 指针类型转换 (例如数组退化:`[N x T]*` 到 `T*`,或兼容指针类型之间)
// 这种情况常见于数组参数,实参可能是一个更具体的数组指针类型,
// 而形参是其退化后的基础指针类型。LLVM 的 `bitcast` 指令可以用于
// 在相同大小的指针类型之间进行转换,这对于数组退化至关重要。
// else if (formalParamType->isPointer() && actualArgType->isPointer()) {
// 检查指针基类型是否兼容,或者是否是数组退化导致的类型不同。
// 使用 bitcast
// args[i] = builder.createBitCastInst(args[i], formalParamType);
// }
// 而形参是其退化后的基础指针类型。
else if (formalParamExpectedValueType->isPointer() && actualArgType->isPointer()) {
// 检查是否是数组指针到元素指针的decay
// 例如:[N x T]* -> T*
auto formalPtrType = formalParamExpectedValueType->as<PointerType>();
auto actualPtrType = actualArgType->as<PointerType>();
if (formalPtrType && actualPtrType && actualPtrType->getBaseType()->isArray()) {
auto actualArrayType = actualPtrType->getBaseType()->as<ArrayType>();
if (actualArrayType &&
formalPtrType->getBaseType() == actualArrayType->getElementType()) {
// 这是数组decay的情况添加GEP来获取数组的第一个元素
std::vector<Value*> indices;
indices.push_back(ConstantInteger::get(0)); // 第一个索引:解引用指针
indices.push_back(ConstantInteger::get(0)); // 第二个索引:获取数组第一个元素
args[i] = getGEPAddressInst(args[i], indices);
}
}
}
// 3. 其他未预期的类型不匹配
// 如果代码执行到这里,说明存在编译器前端未处理的类型不兼容或错误。
else {
@ -1633,6 +1904,7 @@ std::any SysYIRGenerator::visitUnaryExp(SysYParser::UnaryExpContext *ctx) {
visitPrimaryExp(ctx->primaryExp());
} else if (ctx->call() != nullptr) {
BinaryExpStack.push_back(std::any_cast<Value *>(visitCall(ctx->call())));BinaryExpLenStack.back()++;
invalidateExpressionsOnCall();
} else if (ctx->unaryOp() != nullptr) {
// 遇到一元操作符,将其压入 BinaryExpStack
auto opNode = dynamic_cast<antlr4::tree::TerminalNode*>(ctx->unaryOp()->children[0]);
@ -1997,15 +2269,23 @@ void Utils::createExternalFunction(
const std::vector<std::string> &paramNames,
const std::vector<std::vector<Value *>> &paramDims, Type *returnType,
const std::string &funcName, Module *pModule, IRBuilder *pBuilder) {
auto funcType = Type::getFunctionType(returnType, paramTypes);
// 根据paramDims调整参数类型数组参数需要转换为指针类型
std::vector<Type *> adjustedParamTypes = paramTypes;
for (int i = 0; i < paramTypes.size() && i < paramDims.size(); ++i) {
if (!paramDims[i].empty()) {
// 如果参数有维度信息,说明是数组参数,转换为指针类型
adjustedParamTypes[i] = Type::getPointerType(paramTypes[i]);
}
}
auto funcType = Type::getFunctionType(returnType, adjustedParamTypes);
auto function = pModule->createExternalFunction(funcName, funcType);
auto entry = function->getEntryBlock();
pBuilder->setPosition(entry, entry->end());
for (int i = 0; i < paramTypes.size(); ++i) {
auto arg = new Argument(paramTypes[i], function, i, paramNames[i]);
auto arg = new Argument(adjustedParamTypes[i], function, i, paramNames[i]);
auto alloca = pBuilder->createAllocaInst(
Type::getPointerType(paramTypes[i]), paramNames[i]);
Type::getPointerType(adjustedParamTypes[i]), paramNames[i]);
function->insertArgument(arg);
auto store = pBuilder->createStoreInst(arg, alloca);
pModule->addVariable(paramNames[i], alloca);

View File

@ -240,6 +240,10 @@ void SysYPrinter::printInst(Instruction *pInst) {
case Kind::kMul:
case Kind::kDiv:
case Kind::kRem:
case Kind::kSrl:
case Kind::kSll:
case Kind::kSra:
case Kind::kMulh:
case Kind::kFAdd:
case Kind::kFSub:
case Kind::kFMul:
@ -272,6 +276,10 @@ 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::kSrl: std::cout << "lshr"; break;
case Kind::kSll: std::cout << "shl"; 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;
@ -295,7 +303,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 << ", ";
@ -508,9 +521,9 @@ void SysYPrinter::printInst(Instruction *pInst) {
if (!firstPair) std::cout << ", ";
firstPair = false;
std::cout << "[ ";
printValue(phiInst->getValue(i));
printValue(phiInst->getIncomingValue(i));
std::cout << ", %";
printBlock(phiInst->getBlock(i));
printBlock(phiInst->getIncomingBlock(i));
std::cout << " ]";
}
std::cout << std::endl;

View File

@ -35,7 +35,7 @@ void usage(int code) {
"Supported options:\n"
" -h \tprint help message and exit\n"
" -f \tpretty-format the input file\n"
" -s {ast,ir,asm,llvmir,asmd,ird}\tstop after generating AST/IR/Assembly\n"
" -s {ast,ir,asm,asmd,ird}\tstop after generating AST/IR/Assembly\n"
" -S \tcompile to assembly (.s file)\n"
" -o <file>\tplace the output into <file>\n"
" -O<level>\tenable optimization at <level> (e.g., -O0, -O1)\n";
@ -110,6 +110,7 @@ int main(int argc, char **argv) {
// 如果指定停止在 AST 阶段,则打印并退出
if (argStopAfter == "ast") {
cout << moduleAST->toStringTree(true) << '\n';
sysy::cleanupIRPools(); // 清理内存池
return EXIT_SUCCESS;
}
@ -132,7 +133,7 @@ int main(int argc, char **argv) {
if (DEBUG) {
cout << "=== Init IR ===\n";
SysYPrinter(moduleIR).printIR(); // 临时打印器用于调试
moduleIR->print(cout); // 使用新实现的print方法直接打印IR
}
// 创建 Pass 管理器并运行优化管道
@ -144,10 +145,26 @@ int main(int argc, char **argv) {
// 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 阶段,则继续生成汇编 (后端)
@ -166,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;
@ -173,6 +192,8 @@ int main(int argc, char **argv) {
} else {
cout << asmCode << endl;
}
moduleIR->cleanup(); // 清理模块
sysy::cleanupIRPools(); // 清理内存池
return EXIT_SUCCESS;
}
@ -181,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;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long