Compare commits
48 Commits
constPropa
...
backend-la
| Author | SHA1 | Date | |
|---|---|---|---|
| 6550c8a25b | |||
|
|
e4ad23a1a5 | ||
|
|
ec91a4e259 | ||
|
|
92c89f7616 | ||
|
|
66047dc6a3 | ||
|
|
22cf18a1d6 | ||
|
|
19a433c94f | ||
|
|
45dfbc8d59 | ||
|
|
f8e423f579 | ||
|
|
5b43f208ac | ||
|
|
845f969c2e | ||
| 9c5d9ea78c | |||
| 0ce742a86e | |||
| f312792fe9 | |||
|
|
32ea24df56 | ||
|
|
a1cf60c420 | ||
|
|
f879a0f521 | ||
|
|
004ef82488 | ||
|
|
8f1d592d4e | ||
|
|
537533ee43 | ||
|
|
bfe218be07 | ||
|
|
384f7c548b | ||
|
|
57fe17dc21 | ||
|
|
e48cddab9f | ||
|
|
aef10b48e8 | ||
|
|
373726b02f | ||
|
|
a0b69f20fb | ||
|
|
999f2c6615 | ||
|
|
1eedb55ca0 | ||
|
|
8fe9867f33 | ||
|
|
166d0fc372 | ||
|
|
873dbf64d0 | ||
|
|
f387aecc03 | ||
|
|
c268191826 | ||
|
|
03e88eee70 | ||
|
|
0f1fcc835d | ||
|
|
c5af4f1c49 | ||
|
|
9a53e1b917 | ||
|
|
ef09bc70d4 | ||
|
|
aed4577490 | ||
|
|
35b421b60b | ||
|
|
f3f603a032 | ||
|
|
de0f8422e9 | ||
|
|
35691ab7bc | ||
|
|
61768fa180 | ||
|
|
520ebd96f0 | ||
|
|
6868f638d7 | ||
|
|
206a0af424 |
218
Pass_ID_List.md
218
Pass_ID_List.md
@@ -14,10 +14,220 @@
|
|||||||
|
|
||||||
Mem2Reg 遍的主要目标是将那些不必要的、只用于局部标量变量的内存分配 (alloca 指令) 消除,并将这些变量的值转换为 SSA 形式。这有助于减少内存访问,提高代码效率,并为后续的优化创造更好的条件。
|
Mem2Reg 遍的主要目标是将那些不必要的、只用于局部标量变量的内存分配 (alloca 指令) 消除,并将这些变量的值转换为 SSA 形式。这有助于减少内存访问,提高代码效率,并为后续的优化创造更好的条件。
|
||||||
|
|
||||||
|
通过Mem2Reg理解删除指令时对use关系的维护:
|
||||||
|
|
||||||
|
在 `Mem2Reg` 优化遍中,当 `load` 和 `store` 指令被删除时,其 `use` 关系(即它们作为操作数与其他 `Value` 对象之间的连接)的正确消除是一个关键问题,尤其涉及到 `AllocaInst`。
|
||||||
|
|
||||||
|
结合您提供的 `Mem2RegContext::renameVariables` 代码和我们之前讨论的 `usedelete` 逻辑,下面是 `use` 关系如何被正确消除的详细过程:
|
||||||
|
|
||||||
|
### 问题回顾:`Use` 关系的双向性
|
||||||
|
|
||||||
|
在您的 IR 设计中,`Use` 对象扮演着连接 `User`(使用者,如 `LoadInst`)和 `Value`(被使用者,如 `AllocaInst`)的双向角色:
|
||||||
|
|
||||||
|
* 一个 `User` 持有对其操作数 `Value` 的 `Use` 对象(通过 `User::operands` 列表)。
|
||||||
|
* 一个 `Value` 持有所有使用它的 `User` 的 `Use` 对象(通过 `Value::uses` 列表)。
|
||||||
|
|
||||||
|
原始问题是:当一个 `LoadInst` 或 `StoreInst` 被删除时,如果不对其作为操作数与 `AllocaInst` 之间的 `Use` 关系进行明确清理,`AllocaInst` 的 `uses` 列表中就会留下指向已删除 `LoadInst` / `StoreInst` 的 `Use` 对象,导致内部的 `User*` 指针悬空,在后续访问时引发 `segmentation fault`。
|
||||||
|
|
||||||
|
### `Mem2Reg` 中 `load`/`store` 指令的删除行为
|
||||||
|
|
||||||
|
在 `Mem2RegContext::renameVariables` 函数中,`load` 和 `store` 指令被处理时,其行为如下:
|
||||||
|
|
||||||
|
1. **处理 `LoadInst`:**
|
||||||
|
当找到一个指向可提升 `AllocaInst` 的 `LoadInst` 时,其用途会被 `replaceAllUsesWith(allocaToValueStackMap[alloca].top())` 替换。这意味着任何原本使用 `LoadInst` 本身计算结果的指令,现在都直接使用 SSA 值栈顶部的 `Value`。
|
||||||
|
**重点:** 这一步处理的是 `LoadInst` 作为**被使用的值 (Value)** 时,其 `uses` 列表的清理。即,将 `LoadInst` 的所有使用者重定向到新的 SSA 值,并把这些 `Use` 对象从 `LoadInst` 的 `uses` 列表中移除。
|
||||||
|
|
||||||
|
2. **处理 `StoreInst`:**
|
||||||
|
当找到一个指向可提升 `AllocaInst` 的 `StoreInst` 时,`StoreInst` 存储的值会被压入值栈。`StoreInst` 本身并不产生可被其他指令直接使用的值(其类型是 `void`),所以它没有 `uses` 列表需要替换。
|
||||||
|
**重点:** `StoreInst` 的主要作用是更新内存状态,在 SSA 形式下,它被移除后需要清理它作为**使用者 (User)** 时的操作数关系。
|
||||||
|
|
||||||
|
在这两种情况下,一旦 `load` 或 `store` 指令的 SSA 转换完成,它们都会通过 `instIter = SysYIROptUtils::usedelete(instIter)` 被显式删除。
|
||||||
|
|
||||||
|
### `SysYIROptUtils::usedelete` 如何正确消除 `Use` 关系
|
||||||
|
|
||||||
|
关键在于对 `SysYIROptUtils::usedelete` 函数的修改,使其在删除指令时,同时处理该指令作为 `User` 和 `Value` 的两种 `Use` 关系:
|
||||||
|
|
||||||
|
1. **清理指令作为 `Value` 时的 `uses` 列表 (由 `replaceAllUsesWith` 完成):**
|
||||||
|
在 `usedelete` 函数中,`inst->replaceAllUsesWith(UndefinedValue::get(inst->getType()))` 的调用至关重要。这确保了:
|
||||||
|
* 如果被删除的 `Instruction`(例如 `LoadInst`)产生了结果值并被其他指令使用,所有这些使用者都会被重定向到 `UndefinedValue`(或者 `Mem2Reg` 中具体的 SSA 值)。
|
||||||
|
* 这个过程会遍历 `LoadInst` 的 `uses` 列表,并将这些 `Use` 对象从 `LoadInst` 的 `uses` 列表中移除。这意味着 `LoadInst` 自己不再被任何其他指令使用。
|
||||||
|
|
||||||
|
2. **清理指令作为 `User` 时其操作数的 `uses` 列表 (由 `RemoveUserOperandUses` 完成):**
|
||||||
|
这是您提出的、并已集成到 `usedelete` 中的关键改进点。对于一个被删除的 `Instruction`(它同时也是 `User`),我们需要清理它**自己使用的操作数**所维护的 `use` 关系。
|
||||||
|
* 例如,`LoadInst %op1` 使用了 `%op1`(一个 `AllocaInst`)。当 `LoadInst` 被删除时,`AllocaInst` 的 `uses` 列表中有一个 `Use` 对象指向这个 `LoadInst`。
|
||||||
|
* `RemoveUserOperandUses` 函数会遍历被删除 `User`(即 `LoadInst` 或 `StoreInst`)的 `operands` 列表。
|
||||||
|
* 对于 `operands` 列表中的每个 `std::shared_ptr<Use> use_ptr`,它会获取 `Use` 对象内部指向的 `Value`(例如 `AllocaInst*`),然后调用 `value->removeUse(use_ptr)`。
|
||||||
|
* 这个 `removeUse` 调用会负责将 `use_ptr` 从 `AllocaInst` 的 `uses` 列表中删除。
|
||||||
|
|
||||||
|
### 总结
|
||||||
|
|
||||||
|
通过在 `SysYIROptUtils::usedelete` 中同时执行这两个步骤:
|
||||||
|
|
||||||
|
* `replaceAllUsesWith`:处理被删除指令**作为结果被使用**时的 `use` 关系。
|
||||||
|
* `RemoveUserOperandUses`:处理被删除指令**作为使用者(User)时,其操作数**的 `use` 关系。
|
||||||
|
|
||||||
|
这就确保了当 `Mem2Reg` 遍历并删除 `load` 和 `store` 指令时,无论是它们作为 `Value` 的使用者,还是它们作为 `User` 的操作数,所有相关的 `Use` 对象都能被正确地从 `Value` 的 `uses` 列表中移除,从而避免了悬空指针和后续的 `segmentation fault`。
|
||||||
|
|
||||||
|
最后,当所有指向某个 `AllocaInst` 的 `load` 和 `store` 指令都被移除后,`AllocaInst` 的 `uses` 列表将变得干净(只包含 Phi 指令,如果它们在 SSA 转换中需要保留 Alloca 作为操作数),这时在 `Mem2RegContext::cleanup()` 阶段,`SysYIROptUtils::usedelete(alloca)` 就可以安全地删除 `AllocaInst` 本身了。
|
||||||
|
|
||||||
## Reg2Mem
|
## Reg2Mem
|
||||||
|
|
||||||
我们的Reg2Mem 遍的主要目标是作为 Mem2Reg 的一种逆操作,但更具体是解决后端无法识别 PhiInst 指令的问题。主要的速录是将函数参数和 PhiInst 指令的结果从 SSA 形式转换回内存形式,通过插入 alloca、load 和 store 指令来实现。其他非 Phi 的指令结果将保持 SSA 形式。
|
我们的Reg2Mem 遍的主要目标是作为 Mem2Reg 的一种逆操作,但更具体是解决后端无法识别 PhiInst 指令的问题。主要的速录是将函数参数和 PhiInst 指令的结果从 SSA 形式转换回内存形式,通过插入 alloca、load 和 store 指令来实现。其他非 Phi 的指令结果将保持 SSA 形式。
|
||||||
|
|
||||||
|
## SCCP
|
||||||
|
|
||||||
|
SCCP(稀疏条件常量传播)是一种编译器优化技术,它结合了常量传播和死代码消除。其核心思想是在程序执行过程中,尝试识别并替换那些在编译时就能确定其值的变量(常量),同时移除那些永远不会被执行到的代码块(不可达代码)。
|
||||||
|
|
||||||
|
以下是 SCCP 的实现思路:
|
||||||
|
|
||||||
|
1. 核心数据结构与工作列表:
|
||||||
|
|
||||||
|
Lattice 值(Lattice Value): SCCP 使用三值格(Three-Valued Lattice)来表示变量的状态:
|
||||||
|
|
||||||
|
Top (T): 初始状态,表示变量的值未知,但可能是一个常量。
|
||||||
|
|
||||||
|
Constant (C): 表示变量的值已经确定为一个具体的常量。
|
||||||
|
|
||||||
|
Bottom (⊥): 表示变量的值不确定或不是一个常量(例如,它可能在运行时有多个不同的值,或者从内存中加载)。一旦变量状态变为 Bottom,它就不能再变回 Constant 或 Top。
|
||||||
|
|
||||||
|
SSAPValue: 封装了 Lattice 值和常量具体值(如果状态是 Constant)。
|
||||||
|
|
||||||
|
*valState (map<Value, SSAPValue>):** 存储程序中每个 Value(变量、指令结果等)的当前 SCCP Lattice 状态。
|
||||||
|
|
||||||
|
*ExecutableBlocks (set<BasicBlock>):** 存储在分析过程中被确定为可执行的基本块。
|
||||||
|
|
||||||
|
工作列表 (Worklists):
|
||||||
|
|
||||||
|
cfgWorkList (queue<pair<BasicBlock, BasicBlock>>):** 存储待处理的控制流图(CFG)边。当一个块被标记为可执行时,它的后继边会被添加到这个列表。
|
||||||
|
|
||||||
|
*ssaWorkList (queue<Instruction>):** 存储待处理的 SSA (Static Single Assignment) 指令。当一个指令的任何操作数的状态发生变化时,该指令就会被添加到这个列表,需要重新评估。
|
||||||
|
|
||||||
|
2. 初始化:
|
||||||
|
|
||||||
|
所有 Value 的状态都被初始化为 Top。
|
||||||
|
|
||||||
|
所有基本块都被初始化为不可执行。
|
||||||
|
|
||||||
|
函数的入口基本块被标记为可执行,并且该块中的所有指令被添加到 ssaWorkList。
|
||||||
|
|
||||||
|
3. 迭代过程 (Fixed-Point Iteration):
|
||||||
|
|
||||||
|
SCCP 的核心是一个迭代过程,它交替处理 CFG 工作列表和 SSA 工作列表,直到达到一个不动点(即没有更多的状态变化)。
|
||||||
|
|
||||||
|
处理 cfgWorkList:
|
||||||
|
|
||||||
|
从 cfgWorkList 中取出一个边 (prev, next)。
|
||||||
|
|
||||||
|
如果 next 块之前是不可执行的,现在通过 prev 块可达,则将其标记为可执行 (markBlockExecutable)。
|
||||||
|
|
||||||
|
一旦 next 块变为可执行,其内部的所有指令(特别是 Phi 指令)都需要被重新评估,因此将它们添加到 ssaWorkList。
|
||||||
|
|
||||||
|
处理 ssaWorkList:
|
||||||
|
|
||||||
|
从 ssaWorkList 中取出一个指令 inst。
|
||||||
|
|
||||||
|
重要: 只有当 inst 所在的块是可执行的,才处理该指令。不可执行块中的指令不参与常量传播。
|
||||||
|
|
||||||
|
计算新的 Lattice 值 (computeLatticeValue): 根据指令类型和其操作数的当前 Lattice 状态,计算 inst 的新的 Lattice 状态。
|
||||||
|
|
||||||
|
常量折叠: 如果所有操作数都是常量,则可以直接执行运算并得到一个新的常量结果。
|
||||||
|
|
||||||
|
Bottom 传播: 如果任何操作数是 Bottom,或者运算规则导致不确定(例如除以零),则结果为 Bottom。
|
||||||
|
|
||||||
|
Phi 指令的特殊处理: Phi 指令的值取决于其所有可执行的前驱块传入的值。
|
||||||
|
|
||||||
|
如果所有可执行前驱都提供了相同的常量 C,则 Phi 结果为 C。
|
||||||
|
|
||||||
|
如果有任何可执行前驱提供了 Bottom,或者不同的可执行前驱提供了不同的常量,则 Phi 结果为 Bottom。
|
||||||
|
|
||||||
|
如果所有可执行前驱都提供了 Top,则 Phi 结果仍为 Top。
|
||||||
|
|
||||||
|
更新状态: 如果 inst 的新计算出的 Lattice 值与它当前存储的值不同,则更新 valState[inst]。
|
||||||
|
|
||||||
|
传播变化: 如果 inst 的状态发生变化,那么所有使用 inst 作为操作数的指令都可能受到影响,需要重新评估。因此,将 inst 的所有使用者添加到 ssaWorkList。
|
||||||
|
|
||||||
|
处理终结符指令 (BranchInst, ReturnInst):
|
||||||
|
|
||||||
|
对于条件分支 BranchInst,如果其条件操作数变为常量:
|
||||||
|
|
||||||
|
如果条件为真,则只有真分支的目标块是可达的,将该边添加到 cfgWorkList。
|
||||||
|
|
||||||
|
如果条件为假,则只有假分支的目标块是可达的,将该边添加到 cfgWorkList。
|
||||||
|
|
||||||
|
如果条件不是常量(Top 或 Bottom),则两个分支都可能被执行,将两边的边都添加到 cfgWorkList。
|
||||||
|
|
||||||
|
这会影响 CFG 的可达性分析,可能导致新的块被标记为可执行。
|
||||||
|
|
||||||
|
4. 应用优化 (Transformation):
|
||||||
|
|
||||||
|
当两个工作列表都为空,达到不动点后,程序代码开始进行实际的修改:
|
||||||
|
|
||||||
|
常量替换:
|
||||||
|
|
||||||
|
遍历所有指令。如果指令的 valState 为 Constant,则用相应的 ConstantValue 替换该指令的所有用途 (replaceAllUsesWith)。
|
||||||
|
|
||||||
|
将该指令标记为待删除。
|
||||||
|
|
||||||
|
对于指令的操作数,如果其 valState 为 Constant,则直接将操作数替换为对应的 ConstantValue(常量折叠)。
|
||||||
|
|
||||||
|
删除死指令: 遍历所有标记为待删除的指令,并从其父基本块中删除它们。
|
||||||
|
|
||||||
|
删除不可达基本块: 遍历函数中的所有基本块。如果一个基本块没有被标记为可执行 (ExecutableBlocks 中不存在),则将其从函数中删除。但入口块不能删除。
|
||||||
|
|
||||||
|
简化分支指令:
|
||||||
|
|
||||||
|
遍历所有可执行的基本块的终结符指令。
|
||||||
|
|
||||||
|
对于条件分支 BranchInst,如果其条件操作数在 valState 中是 Constant:
|
||||||
|
|
||||||
|
如果条件为真,则将该条件分支替换为一个无条件跳转到真分支目标块的指令。
|
||||||
|
|
||||||
|
如果条件为假,则将该条件分支替换为一个无条件跳转到假分支目标块的指令。
|
||||||
|
|
||||||
|
更新 CFG,移除不可达的分支边和其前驱信息。
|
||||||
|
|
||||||
|
computeLatticeValue 的具体逻辑:
|
||||||
|
|
||||||
|
这个函数是 SCCP 的核心逻辑,它定义了如何根据指令类型和操作数的当前 Lattice 状态来计算指令结果的 Lattice 状态。
|
||||||
|
|
||||||
|
二元运算 (Add, Sub, Mul, Div, Rem, ICmp, And, Or):
|
||||||
|
|
||||||
|
如果任何一个操作数是 Bottom,结果就是 Bottom。
|
||||||
|
|
||||||
|
如果任何一个操作数是 Top,结果就是 Top。
|
||||||
|
|
||||||
|
如果两个操作数都是 Constant,执行实际的常量运算,结果是一个新的 Constant。
|
||||||
|
|
||||||
|
一元运算 (Neg, Not):
|
||||||
|
|
||||||
|
如果操作数是 Bottom,结果就是 Bottom。
|
||||||
|
|
||||||
|
如果操作数是 Top,结果就是 Top。
|
||||||
|
|
||||||
|
如果操作数是 Constant,执行实际的常量运算,结果是一个新的 Constant。
|
||||||
|
|
||||||
|
Load 指令: 通常情况下,Load 的结果会被标记为 Bottom,因为内存内容通常在编译时无法确定。但如果加载的是已知的全局常量,可能可以确定。在提供的代码中,它通常返回 Bottom。
|
||||||
|
|
||||||
|
Store 指令: Store 不产生值,所以其 SSAPValue 保持 Top 或不关心。
|
||||||
|
|
||||||
|
Call 指令: 大多数 Call 指令(尤其是对外部或有副作用的函数)的结果都是 Bottom。对于纯函数,如果所有参数都是常量,理论上可以折叠,但这需要额外的分析。
|
||||||
|
|
||||||
|
GetElementPtr (GEP) 指令: GEP 计算内存地址。如果所有索引都是常量,地址本身是常量。但 SCCP 关注的是数据值,因此这里通常返回 Bottom,除非有特定的指针常量跟踪。
|
||||||
|
|
||||||
|
Phi 指令: 如上所述,基于所有可执行前驱的传入值进行聚合。
|
||||||
|
|
||||||
|
Alloc 指令: Alloc 分配内存,返回一个指针。其内容通常是 Bottom。
|
||||||
|
|
||||||
|
Branch 和 Return 指令: 这些是终结符指令,不产生一个可用于其他指令的值,通常 SSAPValue 保持 Top 或不关心。
|
||||||
|
|
||||||
|
类型转换 (ZExt, SExt, Trunc, FtoI, ItoF): 如果操作数是 Constant,则执行相应的类型转换,结果仍为 Constant。对于浮点数转换,由于 SSAPValue 的 constantVal 为 int 类型,所以对浮点数的操作会保守地返回 Bottom。
|
||||||
|
|
||||||
|
未处理的指令: 默认情况下,任何未明确处理的指令都被保守地假定为产生 Bottom 值。
|
||||||
|
|
||||||
|
浮点数处理的注意事项:
|
||||||
|
|
||||||
|
在提供的代码中,SSAPValue 的 constantVal 是 int 类型。这使得浮点数常量传播变得复杂。对于浮点数相关的指令(kFAdd, kFMul, kFCmp, kFNeg, kFNot, kItoF, kFtoI 等),如果不能将浮点值准确地存储在 int 中,或者不能可靠地执行浮点运算,那么通常会保守地将结果设置为 Bottom。一个更完善的 SCCP 实现会使用 std::variant<int, float> 或独立的浮点常量存储来处理浮点数。
|
||||||
|
|
||||||
|
|
||||||
# 后续优化可能涉及的改动
|
# 后续优化可能涉及的改动
|
||||||
|
|
||||||
@@ -26,3 +236,11 @@ Mem2Reg 遍的主要目标是将那些不必要的、只用于局部标量变量
|
|||||||
好处:优化友好性,方便mem2reg提升
|
好处:优化友好性,方便mem2reg提升
|
||||||
目前没有实现这个机制,如果想要实现首先解决同一函数不同域的同名变量命名区分
|
目前没有实现这个机制,如果想要实现首先解决同一函数不同域的同名变量命名区分
|
||||||
需要保证符号表能正确维护域中的局部变量
|
需要保证符号表能正确维护域中的局部变量
|
||||||
|
|
||||||
|
|
||||||
|
# 关于中端优化提升编译器性能的TODO
|
||||||
|
|
||||||
|
## usedelete_withinstdelte方法
|
||||||
|
|
||||||
|
这个方法删除了use关系并移除了指令,逻辑是根据Instruction* inst去find对应的迭代器并erase
|
||||||
|
有些情况下外部持有迭代器和inst,可以省略find过程
|
||||||
@@ -60,11 +60,7 @@ display_file_content() {
|
|||||||
# 清理临时文件的函数
|
# 清理临时文件的函数
|
||||||
clean_tmp() {
|
clean_tmp() {
|
||||||
echo "正在清理临时目录: ${TMP_DIR}"
|
echo "正在清理临时目录: ${TMP_DIR}"
|
||||||
rm -rf "${TMP_DIR}"/*.s \
|
rm -rf "${TMP_DIR}"/*
|
||||||
"${TMP_DIR}"/*_sysyc_riscv64 \
|
|
||||||
"${TMP_DIR}"/*_sysyc_riscv64.actual_out \
|
|
||||||
"${TMP_DIR}"/*_sysyc_riscv64.expected_stdout \
|
|
||||||
"${TMP_DIR}"/*_sysyc_riscv64.o
|
|
||||||
echo "清理完成。"
|
echo "清理完成。"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ QEMU_RISCV64="qemu-riscv64"
|
|||||||
# --- 初始化变量 ---
|
# --- 初始化变量 ---
|
||||||
EXECUTE_MODE=false
|
EXECUTE_MODE=false
|
||||||
CLEAN_MODE=false
|
CLEAN_MODE=false
|
||||||
|
OPTIMIZE_FLAG="" # 用于存储 -O1 标志
|
||||||
SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒)
|
SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒)
|
||||||
GCC_TIMEOUT=10 # gcc 编译超时 (秒)
|
GCC_TIMEOUT=10 # gcc 编译超时 (秒)
|
||||||
EXEC_TIMEOUT=5 # qemu 自动化执行超时 (秒)
|
EXEC_TIMEOUT=5 # qemu 自动化执行超时 (秒)
|
||||||
@@ -39,6 +40,7 @@ show_help() {
|
|||||||
echo "选项:"
|
echo "选项:"
|
||||||
echo " -e, --executable 编译为可执行文件并运行测试 (必须)。"
|
echo " -e, --executable 编译为可执行文件并运行测试 (必须)。"
|
||||||
echo " -c, --clean 清理 tmp 临时目录下的所有文件。"
|
echo " -c, --clean 清理 tmp 临时目录下的所有文件。"
|
||||||
|
echo " -O1 启用 sysyc 的 -O1 优化。"
|
||||||
echo " -sct N 设置 sysyc 编译超时为 N 秒 (默认: 10)。"
|
echo " -sct N 设置 sysyc 编译超时为 N 秒 (默认: 10)。"
|
||||||
echo " -gct N 设置 gcc 交叉编译超时为 N 秒 (默认: 10)。"
|
echo " -gct N 设置 gcc 交叉编译超时为 N 秒 (默认: 10)。"
|
||||||
echo " -et N 设置 qemu 自动化执行超时为 N 秒 (默认: 5)。"
|
echo " -et N 设置 qemu 自动化执行超时为 N 秒 (默认: 5)。"
|
||||||
@@ -68,7 +70,7 @@ display_file_content() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 本次修改点: 整个参数解析逻辑被重写 ---
|
# --- 参数解析 ---
|
||||||
# 使用标准的 while 循环来健壮地处理任意顺序的参数
|
# 使用标准的 while 循环来健壮地处理任意顺序的参数
|
||||||
while [[ "$#" -gt 0 ]]; do
|
while [[ "$#" -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
@@ -80,6 +82,10 @@ while [[ "$#" -gt 0 ]]; do
|
|||||||
CLEAN_MODE=true
|
CLEAN_MODE=true
|
||||||
shift # 消耗选项
|
shift # 消耗选项
|
||||||
;;
|
;;
|
||||||
|
-O1)
|
||||||
|
OPTIMIZE_FLAG="-O1"
|
||||||
|
shift # 消耗选项
|
||||||
|
;;
|
||||||
-sct)
|
-sct)
|
||||||
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then SYSYC_TIMEOUT="$2"; shift 2; else echo "错误: -sct 需要一个正整数参数。" >&2; exit 1; fi
|
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then SYSYC_TIMEOUT="$2"; shift 2; else echo "错误: -sct 需要一个正整数参数。" >&2; exit 1; fi
|
||||||
;;
|
;;
|
||||||
@@ -144,6 +150,7 @@ mkdir -p "${TMP_DIR}"
|
|||||||
TOTAL_CASES=${#SY_FILES[@]}
|
TOTAL_CASES=${#SY_FILES[@]}
|
||||||
|
|
||||||
echo "SysY 单例测试运行器启动..."
|
echo "SysY 单例测试运行器启动..."
|
||||||
|
if [ -n "$OPTIMIZE_FLAG" ]; then echo "优化等级: ${OPTIMIZE_FLAG}"; fi
|
||||||
echo "超时设置: sysyc=${SYSYC_TIMEOUT}s, gcc=${GCC_TIMEOUT}s, qemu=${EXEC_TIMEOUT}s"
|
echo "超时设置: sysyc=${SYSYC_TIMEOUT}s, gcc=${GCC_TIMEOUT}s, qemu=${EXEC_TIMEOUT}s"
|
||||||
echo "失败输出最大行数: ${MAX_OUTPUT_LINES}"
|
echo "失败输出最大行数: ${MAX_OUTPUT_LINES}"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -164,9 +171,21 @@ for sy_file in "${SY_FILES[@]}"; do
|
|||||||
echo "======================================================================"
|
echo "======================================================================"
|
||||||
echo "正在处理: ${sy_file}"
|
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
|
||||||
|
|
||||||
# 步骤 1: sysyc 编译
|
# 步骤 1: sysyc 编译
|
||||||
echo " 使用 sysyc 编译 (超时 ${SYSYC_TIMEOUT}s)..."
|
echo " 使用 sysyc 编译 (超时 ${SYSYC_TIMEOUT}s)..."
|
||||||
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s ir "${sy_file}" > "${ir_file}"
|
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -S "${sy_file}" ${OPTIMIZE_FLAG} -o "${assembly_file}"
|
||||||
|
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s ir "${sy_file}" ${OPTIMIZE_FLAG} > "${ir_file}"
|
||||||
|
# timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s asmd "${sy_file}" > "${assembly_debug_file}" 2>&1
|
||||||
SYSYC_STATUS=$?
|
SYSYC_STATUS=$?
|
||||||
if [ $SYSYC_STATUS -eq 124 ]; then
|
if [ $SYSYC_STATUS -eq 124 ]; then
|
||||||
echo -e "\e[31m错误: SysY 编译 ${sy_file} IR超时\e[0m"
|
echo -e "\e[31m错误: SysY 编译 ${sy_file} IR超时\e[0m"
|
||||||
@@ -175,12 +194,10 @@ for sy_file in "${SY_FILES[@]}"; do
|
|||||||
echo -e "\e[31m错误: SysY 编译 ${sy_file} IR失败,退出码: ${SYSYC_STATUS}\e[0m"
|
echo -e "\e[31m错误: SysY 编译 ${sy_file} IR失败,退出码: ${SYSYC_STATUS}\e[0m"
|
||||||
is_passed=0
|
is_passed=0
|
||||||
fi
|
fi
|
||||||
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -S "${sy_file}" -o "${assembly_file}"
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo -e "\e[31m错误: SysY 编译失败或超时。\e[0m"
|
echo -e "\e[31m错误: SysY 编译失败或超时。\e[0m"
|
||||||
is_passed=0
|
is_passed=0
|
||||||
fi
|
fi
|
||||||
# timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s asmd "${sy_file}" > "${assembly_debug_file}" 2>&1
|
|
||||||
|
|
||||||
# 步骤 2: GCC 编译
|
# 步骤 2: GCC 编译
|
||||||
if [ "$is_passed" -eq 1 ]; then
|
if [ "$is_passed" -eq 1 ]; then
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ SYSYC="${BUILD_BIN_DIR}/sysyc"
|
|||||||
GCC_RISCV64="riscv64-linux-gnu-gcc"
|
GCC_RISCV64="riscv64-linux-gnu-gcc"
|
||||||
QEMU_RISCV64="qemu-riscv64"
|
QEMU_RISCV64="qemu-riscv64"
|
||||||
|
|
||||||
# --- 新增功能: 初始化变量 ---
|
|
||||||
EXECUTE_MODE=false
|
EXECUTE_MODE=false
|
||||||
|
OPTIMIZE_FLAG="" # 用于存储 -O1 标志
|
||||||
SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒)
|
SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒)
|
||||||
GCC_TIMEOUT=10 # gcc 编译超时 (秒)
|
GCC_TIMEOUT=10 # gcc 编译超时 (秒)
|
||||||
EXEC_TIMEOUT=5 # qemu 执行超时 (秒)
|
EXEC_TIMEOUT=5 # qemu 执行超时 (秒)
|
||||||
@@ -35,6 +35,7 @@ show_help() {
|
|||||||
echo "选项:"
|
echo "选项:"
|
||||||
echo " -e, --executable 编译为可执行文件并运行测试。"
|
echo " -e, --executable 编译为可执行文件并运行测试。"
|
||||||
echo " -c, --clean 清理 'tmp' 目录下的所有生成文件。"
|
echo " -c, --clean 清理 'tmp' 目录下的所有生成文件。"
|
||||||
|
echo " -O1 启用 sysyc 的 -O1 优化。"
|
||||||
echo " -set [f|h|p|all]... 指定要运行的测试集 (functional, h_functional, performance)。可多选,默认为 all。"
|
echo " -set [f|h|p|all]... 指定要运行的测试集 (functional, h_functional, performance)。可多选,默认为 all。"
|
||||||
echo " -sct N 设置 sysyc 编译超时为 N 秒 (默认: 10)。"
|
echo " -sct N 设置 sysyc 编译超时为 N 秒 (默认: 10)。"
|
||||||
echo " -gct N 设置 gcc 交叉编译超时为 N 秒 (默认: 10)。"
|
echo " -gct N 设置 gcc 交叉编译超时为 N 秒 (默认: 10)。"
|
||||||
@@ -85,9 +86,12 @@ while [[ "$#" -gt 0 ]]; do
|
|||||||
clean_tmp
|
clean_tmp
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
|
-O1)
|
||||||
|
OPTIMIZE_FLAG="-O1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
-set)
|
-set)
|
||||||
shift # 移过 '-set'
|
shift # 移过 '-set'
|
||||||
# 消耗所有后续参数直到遇到下一个选项
|
|
||||||
while [[ "$#" -gt 0 && ! "$1" =~ ^- ]]; do
|
while [[ "$#" -gt 0 && ! "$1" =~ ^- ]]; do
|
||||||
TEST_SETS+=("$1")
|
TEST_SETS+=("$1")
|
||||||
shift
|
shift
|
||||||
@@ -125,7 +129,6 @@ SET_MAP[p]="performance"
|
|||||||
|
|
||||||
SEARCH_PATHS=()
|
SEARCH_PATHS=()
|
||||||
|
|
||||||
# 如果未指定测试集,或指定了 'all',则搜索所有目录
|
|
||||||
if [ ${#TEST_SETS[@]} -eq 0 ] || [[ " ${TEST_SETS[@]} " =~ " all " ]]; then
|
if [ ${#TEST_SETS[@]} -eq 0 ] || [[ " ${TEST_SETS[@]} " =~ " all " ]]; then
|
||||||
SEARCH_PATHS+=("${TESTDATA_DIR}")
|
SEARCH_PATHS+=("${TESTDATA_DIR}")
|
||||||
else
|
else
|
||||||
@@ -138,13 +141,13 @@ else
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 如果没有有效的搜索路径,则退出
|
|
||||||
if [ ${#SEARCH_PATHS[@]} -eq 0 ]; then
|
if [ ${#SEARCH_PATHS[@]} -eq 0 ]; then
|
||||||
echo -e "\e[31m错误: 没有找到有效的测试集目录,测试中止。\e[0m"
|
echo -e "\e[31m错误: 没有找到有效的测试集目录,测试中止。\e[0m"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "SysY 测试运行器启动..."
|
echo "SysY 测试运行器启动..."
|
||||||
|
if [ -n "$OPTIMIZE_FLAG" ]; then echo "优化等级: ${OPTIMIZE_FLAG}"; fi
|
||||||
echo "输入目录: ${SEARCH_PATHS[@]}"
|
echo "输入目录: ${SEARCH_PATHS[@]}"
|
||||||
echo "临时目录: ${TMP_DIR}"
|
echo "临时目录: ${TMP_DIR}"
|
||||||
echo "执行模式: ${EXECUTE_MODE}"
|
echo "执行模式: ${EXECUTE_MODE}"
|
||||||
@@ -154,7 +157,6 @@ if ${EXECUTE_MODE}; then
|
|||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# 使用构建好的路径查找 .sy 文件并排序
|
|
||||||
sy_files=$(find "${SEARCH_PATHS[@]}" -name "*.sy" | sort -V)
|
sy_files=$(find "${SEARCH_PATHS[@]}" -name "*.sy" | sort -V)
|
||||||
if [ -z "$sy_files" ]; then
|
if [ -z "$sy_files" ]; then
|
||||||
echo "在指定目录中未找到任何 .sy 文件。"
|
echo "在指定目录中未找到任何 .sy 文件。"
|
||||||
@@ -162,7 +164,6 @@ if [ -z "$sy_files" ]; then
|
|||||||
fi
|
fi
|
||||||
TOTAL_CASES=$(echo "$sy_files" | wc -w)
|
TOTAL_CASES=$(echo "$sy_files" | wc -w)
|
||||||
|
|
||||||
# --- 修复: 使用 here-string (<<<) 代替管道 (|) 来避免子 shell 问题 ---
|
|
||||||
while IFS= read -r sy_file; do
|
while IFS= read -r sy_file; do
|
||||||
is_passed=1 # 1 表示通过, 0 表示失败
|
is_passed=1 # 1 表示通过, 0 表示失败
|
||||||
|
|
||||||
@@ -176,10 +177,8 @@ while IFS= read -r sy_file; do
|
|||||||
output_actual_file="${TMP_DIR}/${output_base_name}_sysyc_riscv64.actual_out"
|
output_actual_file="${TMP_DIR}/${output_base_name}_sysyc_riscv64.actual_out"
|
||||||
|
|
||||||
echo "正在处理: $(basename "$sy_file") (路径: ${relative_path_no_ext}.sy)"
|
echo "正在处理: $(basename "$sy_file") (路径: ${relative_path_no_ext}.sy)"
|
||||||
|
|
||||||
# 步骤 1: 使用 sysyc 编译 .sy 到 .s
|
|
||||||
echo " 使用 sysyc 编译 (超时 ${SYSYC_TIMEOUT}s)..."
|
echo " 使用 sysyc 编译 (超时 ${SYSYC_TIMEOUT}s)..."
|
||||||
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -S "${sy_file}" -o "${assembly_file}"
|
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -S "${sy_file}" -o "${assembly_file}" ${OPTIMIZE_FLAG}
|
||||||
SYSYC_STATUS=$?
|
SYSYC_STATUS=$?
|
||||||
if [ $SYSYC_STATUS -eq 124 ]; then
|
if [ $SYSYC_STATUS -eq 124 ]; then
|
||||||
echo -e "\e[31m错误: SysY 编译 ${sy_file} 超时\e[0m"
|
echo -e "\e[31m错误: SysY 编译 ${sy_file} 超时\e[0m"
|
||||||
@@ -189,9 +188,7 @@ while IFS= read -r sy_file; do
|
|||||||
is_passed=0
|
is_passed=0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 只有当 EXECUTE_MODE 为 true 且上一步成功时才继续
|
|
||||||
if ${EXECUTE_MODE} && [ "$is_passed" -eq 1 ]; then
|
if ${EXECUTE_MODE} && [ "$is_passed" -eq 1 ]; then
|
||||||
# 步骤 2: 使用 riscv64-linux-gnu-gcc 编译 .s 到可执行文件
|
|
||||||
echo " 使用 gcc 编译 (超时 ${GCC_TIMEOUT}s)..."
|
echo " 使用 gcc 编译 (超时 ${GCC_TIMEOUT}s)..."
|
||||||
timeout -s KILL ${GCC_TIMEOUT} "${GCC_RISCV64}" "${assembly_file}" -o "${executable_file}" -L"${LIB_DIR}" -lsysy_riscv -static
|
timeout -s KILL ${GCC_TIMEOUT} "${GCC_RISCV64}" "${assembly_file}" -o "${executable_file}" -L"${LIB_DIR}" -lsysy_riscv -static
|
||||||
GCC_STATUS=$?
|
GCC_STATUS=$?
|
||||||
@@ -213,7 +210,6 @@ while IFS= read -r sy_file; do
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 步骤 3, 4, 5: 只有当编译都成功时才执行
|
|
||||||
if [ "$is_passed" -eq 1 ]; then
|
if [ "$is_passed" -eq 1 ]; then
|
||||||
echo " 正在执行 (超时 ${EXEC_TIMEOUT}s)..."
|
echo " 正在执行 (超时 ${EXEC_TIMEOUT}s)..."
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ add_library(riscv64_backend_lib STATIC
|
|||||||
Handler/CalleeSavedHandler.cpp
|
Handler/CalleeSavedHandler.cpp
|
||||||
Handler/LegalizeImmediates.cpp
|
Handler/LegalizeImmediates.cpp
|
||||||
Handler/PrologueEpilogueInsertion.cpp
|
Handler/PrologueEpilogueInsertion.cpp
|
||||||
|
Handler/EliminateFrameIndices.cpp
|
||||||
Optimize/Peephole.cpp
|
Optimize/Peephole.cpp
|
||||||
Optimize/PostRA_Scheduler.cpp
|
Optimize/PostRA_Scheduler.cpp
|
||||||
Optimize/PreRA_Scheduler.cpp
|
Optimize/PreRA_Scheduler.cpp
|
||||||
|
Optimize/DivStrengthReduction.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# 包含后端模块所需的头文件路径
|
# 包含后端模块所需的头文件路径
|
||||||
|
|||||||
@@ -8,11 +8,6 @@ namespace sysy {
|
|||||||
|
|
||||||
char CalleeSavedHandler::ID = 0;
|
char CalleeSavedHandler::ID = 0;
|
||||||
|
|
||||||
// 辅助函数,用于判断一个物理寄存器是否为浮点寄存器
|
|
||||||
static bool is_fp_reg(PhysicalReg reg) {
|
|
||||||
return reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CalleeSavedHandler::runOnFunction(Function *F, AnalysisManager& AM) {
|
bool CalleeSavedHandler::runOnFunction(Function *F, AnalysisManager& AM) {
|
||||||
// This pass works on MachineFunction level, not IR level
|
// This pass works on MachineFunction level, not IR level
|
||||||
return false;
|
return false;
|
||||||
@@ -20,114 +15,37 @@ bool CalleeSavedHandler::runOnFunction(Function *F, AnalysisManager& AM) {
|
|||||||
|
|
||||||
void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
|
void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
|
||||||
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
||||||
|
const std::set<PhysicalReg>& used_callee_saved = frame_info.used_callee_saved_regs;
|
||||||
std::set<PhysicalReg> used_callee_saved;
|
|
||||||
|
|
||||||
// 1. 扫描所有指令,找出被使用的callee-saved寄存器
|
|
||||||
// 这个Pass在RegAlloc之后运行,所以可以访问到物理寄存器
|
|
||||||
for (auto& mbb : mfunc->getBlocks()) {
|
|
||||||
for (auto& instr : mbb->getInstructions()) {
|
|
||||||
for (auto& op : instr->getOperands()) {
|
|
||||||
|
|
||||||
auto check_and_insert_reg = [&](RegOperand* reg_op) {
|
|
||||||
if (reg_op && !reg_op->isVirtual()) {
|
|
||||||
PhysicalReg preg = reg_op->getPReg();
|
|
||||||
|
|
||||||
// 检查整数 s1-s11
|
|
||||||
if (preg >= PhysicalReg::S1 && preg <= PhysicalReg::S11) {
|
|
||||||
used_callee_saved.insert(preg);
|
|
||||||
}
|
|
||||||
// 检查浮点 fs0-fs11 (f8,f9,f18-f27)
|
|
||||||
else if ((preg >= PhysicalReg::F8 && preg <= PhysicalReg::F9) || (preg >= PhysicalReg::F18 && preg <= PhysicalReg::F27)) {
|
|
||||||
used_callee_saved.insert(preg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (op->getKind() == MachineOperand::KIND_REG) {
|
|
||||||
check_and_insert_reg(static_cast<RegOperand*>(op.get()));
|
|
||||||
} else if (op->getKind() == MachineOperand::KIND_MEM) {
|
|
||||||
check_and_insert_reg(static_cast<MemOperand*>(op.get())->getBase());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (used_callee_saved.empty()) {
|
if (used_callee_saved.empty()) {
|
||||||
frame_info.callee_saved_size = 0;
|
frame_info.callee_saved_size = 0;
|
||||||
|
frame_info.callee_saved_regs_to_store.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 计算并更新 frame_info
|
// 1. 计算被调用者保存寄存器所需的总空间大小
|
||||||
frame_info.callee_saved_size = used_callee_saved.size() * 8;
|
// s0 总是由 PEI Pass 单独处理,这里不计入大小,但要确保它在列表中
|
||||||
|
int size = 0;
|
||||||
// 为了布局确定性和恢复顺序一致,对寄存器排序
|
std::set<PhysicalReg> regs_to_save = used_callee_saved;
|
||||||
std::vector<PhysicalReg> sorted_regs(used_callee_saved.begin(), used_callee_saved.end());
|
if (regs_to_save.count(PhysicalReg::S0)) {
|
||||||
std::sort(sorted_regs.begin(), sorted_regs.end());
|
regs_to_save.erase(PhysicalReg::S0);
|
||||||
|
|
||||||
// 3. 在函数序言中插入保存指令
|
|
||||||
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
|
|
||||||
auto& entry_instrs = entry_block->getInstructions();
|
|
||||||
// 插入点在函数入口标签之后,或者就是最开始
|
|
||||||
auto insert_pos = entry_instrs.begin();
|
|
||||||
if (!entry_instrs.empty() && entry_instrs.front()->getOpcode() == RVOpcodes::LABEL) {
|
|
||||||
insert_pos = std::next(insert_pos);
|
|
||||||
}
|
}
|
||||||
|
size = regs_to_save.size() * 8; // 每个寄存器占8字节 (64-bit)
|
||||||
|
frame_info.callee_saved_size = size;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<MachineInstr>> save_instrs;
|
// 2. 创建一个有序的、需要保存的寄存器列表,以便后续 Pass 确定地生成代码
|
||||||
// [关键] 从局部变量区域之后开始分配空间
|
// s0 不应包含在此列表中,因为它由 PEI Pass 特殊处理
|
||||||
int current_offset = - (16 + frame_info.locals_size);
|
std::vector<PhysicalReg> sorted_regs(regs_to_save.begin(), regs_to_save.end());
|
||||||
|
std::sort(sorted_regs.begin(), sorted_regs.end(), [](PhysicalReg a, PhysicalReg b){
|
||||||
|
return static_cast<int>(a) < static_cast<int>(b);
|
||||||
|
});
|
||||||
|
frame_info.callee_saved_regs_to_store = sorted_regs;
|
||||||
|
|
||||||
for (PhysicalReg reg : sorted_regs) {
|
// 3. 更新栈帧总大小。
|
||||||
current_offset -= 8;
|
// 这是初步计算,PEI Pass 会进行最终的对齐。
|
||||||
RVOpcodes save_op = is_fp_reg(reg) ? RVOpcodes::FSD : RVOpcodes::SD;
|
frame_info.total_size = frame_info.locals_size +
|
||||||
|
frame_info.spill_size +
|
||||||
auto save_instr = std::make_unique<MachineInstr>(save_op);
|
frame_info.callee_saved_size;
|
||||||
save_instr->addOperand(std::make_unique<RegOperand>(reg));
|
|
||||||
save_instr->addOperand(std::make_unique<MemOperand>(
|
|
||||||
std::make_unique<RegOperand>(PhysicalReg::S0), // 基址为帧指针 s0
|
|
||||||
std::make_unique<ImmOperand>(current_offset)
|
|
||||||
));
|
|
||||||
save_instrs.push_back(std::move(save_instr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!save_instrs.empty()) {
|
|
||||||
entry_instrs.insert(insert_pos,
|
|
||||||
std::make_move_iterator(save_instrs.begin()),
|
|
||||||
std::make_move_iterator(save_instrs.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 在函数结尾(ret之前)插入恢复指令
|
|
||||||
for (auto& mbb : mfunc->getBlocks()) {
|
|
||||||
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
|
|
||||||
if ((*it)->getOpcode() == RVOpcodes::RET) {
|
|
||||||
std::vector<std::unique_ptr<MachineInstr>> restore_instrs;
|
|
||||||
// [关键] 使用与保存时完全相同的逻辑来计算偏移量
|
|
||||||
current_offset = - (16 + frame_info.locals_size);
|
|
||||||
|
|
||||||
for (PhysicalReg reg : sorted_regs) {
|
|
||||||
current_offset -= 8;
|
|
||||||
RVOpcodes restore_op = is_fp_reg(reg) ? RVOpcodes::FLD : RVOpcodes::LD;
|
|
||||||
|
|
||||||
auto restore_instr = std::make_unique<MachineInstr>(restore_op);
|
|
||||||
restore_instr->addOperand(std::make_unique<RegOperand>(reg));
|
|
||||||
restore_instr->addOperand(std::make_unique<MemOperand>(
|
|
||||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
|
||||||
std::make_unique<ImmOperand>(current_offset)
|
|
||||||
));
|
|
||||||
restore_instrs.push_back(std::move(restore_instr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!restore_instrs.empty()) {
|
|
||||||
mbb->getInstructions().insert(it,
|
|
||||||
std::make_move_iterator(restore_instrs.begin()),
|
|
||||||
std::make_move_iterator(restore_instrs.end()));
|
|
||||||
}
|
|
||||||
goto next_block_label;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
next_block_label:;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sysy
|
} // namespace sysy
|
||||||
235
src/backend/RISCv64/Handler/EliminateFrameIndices.cpp
Normal file
235
src/backend/RISCv64/Handler/EliminateFrameIndices.cpp
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
#include "EliminateFrameIndices.h"
|
||||||
|
#include "RISCv64ISel.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace sysy {
|
||||||
|
|
||||||
|
// getTypeSizeInBytes 是一个通用辅助函数,保持不变
|
||||||
|
unsigned EliminateFrameIndicesPass::getTypeSizeInBytes(Type* type) {
|
||||||
|
if (!type) {
|
||||||
|
assert(false && "Cannot get size of a null type.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type->getKind()) {
|
||||||
|
case Type::kInt:
|
||||||
|
case Type::kFloat:
|
||||||
|
return 4;
|
||||||
|
case Type::kPointer:
|
||||||
|
return 8;
|
||||||
|
case Type::kArray: {
|
||||||
|
auto arrayType = type->as<ArrayType>();
|
||||||
|
return arrayType->getNumElements() * getTypeSizeInBytes(arrayType->getElementType());
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assert(false && "Unsupported type for size calculation.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) {
|
||||||
|
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
||||||
|
Function* F = mfunc->getFunc();
|
||||||
|
RISCv64ISel* isel = mfunc->getISel();
|
||||||
|
|
||||||
|
// 在这里处理栈传递的参数,以便在寄存器分配前就将数据流显式化,修复溢出逻辑的BUG。
|
||||||
|
|
||||||
|
// 2. 只为局部变量(AllocaInst)分配栈空间和计算偏移量
|
||||||
|
// 局部变量从 s0 下方(负偏移量)开始分配,紧接着为 ra 和 s0 预留的16字节之后
|
||||||
|
int local_var_offset = 16;
|
||||||
|
|
||||||
|
if(F) { // 确保函数指针有效
|
||||||
|
for (auto& bb : F->getBasicBlocks()) {
|
||||||
|
for (auto& inst : bb->getInstructions()) {
|
||||||
|
if (auto alloca = dynamic_cast<AllocaInst*>(inst.get())) {
|
||||||
|
Type* allocated_type = alloca->getType()->as<PointerType>()->getBaseType();
|
||||||
|
int size = getTypeSizeInBytes(allocated_type);
|
||||||
|
|
||||||
|
// 优化栈帧大小:对于大数组使用4字节对齐,小对象使用8字节对齐
|
||||||
|
if (size >= 256) { // 大数组优化
|
||||||
|
size = (size + 3) & ~3; // 4字节对齐
|
||||||
|
} else {
|
||||||
|
size = (size + 7) & ~7; // 8字节对齐
|
||||||
|
}
|
||||||
|
if (size == 0) size = 4; // 最小4字节
|
||||||
|
|
||||||
|
local_var_offset += size;
|
||||||
|
unsigned alloca_vreg = isel->getVReg(alloca);
|
||||||
|
// 局部变量使用相对于s0的负向偏移
|
||||||
|
frame_info.alloca_offsets[alloca_vreg] = -local_var_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录仅由AllocaInst分配的局部变量的总大小
|
||||||
|
frame_info.locals_size = local_var_offset - 16;
|
||||||
|
// 记录局部变量区域分配结束的最终偏移量
|
||||||
|
frame_info.locals_end_offset = -local_var_offset;
|
||||||
|
|
||||||
|
// 在函数入口为所有栈传递的参数插入load指令
|
||||||
|
// 这个步骤至关重要:它在寄存器分配之前,为这些参数的vreg创建了明确的“定义(def)”指令。
|
||||||
|
// 这解决了在高寄存器压力下,当这些vreg被溢出时,`rewriteProgram`找不到其定义点而崩溃的问题。
|
||||||
|
if (F && isel && !mfunc->getBlocks().empty()) {
|
||||||
|
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
|
||||||
|
std::vector<std::unique_ptr<MachineInstr>> arg_load_instrs;
|
||||||
|
|
||||||
|
// 步骤 3.1: 生成所有加载栈参数的指令,暂存起来
|
||||||
|
int arg_idx = 0;
|
||||||
|
for (Argument* arg : F->getArguments()) {
|
||||||
|
// 根据ABI,前8个整型/指针参数通过寄存器传递,这里只处理超出部分。
|
||||||
|
if (arg_idx >= 8) {
|
||||||
|
// 计算参数在调用者栈帧中的位置,该位置相对于被调用者的帧指针s0是正向偏移。
|
||||||
|
// 第9个参数(arg_idx=8)位于 0(s0),第10个(arg_idx=9)位于 8(s0),以此类推。
|
||||||
|
int offset = (arg_idx - 8) * 8;
|
||||||
|
unsigned arg_vreg = isel->getVReg(arg);
|
||||||
|
Type* arg_type = arg->getType();
|
||||||
|
|
||||||
|
// 根据参数类型选择正确的加载指令
|
||||||
|
RVOpcodes load_op;
|
||||||
|
if (arg_type->isFloat()) {
|
||||||
|
load_op = RVOpcodes::FLW; // 单精度浮点
|
||||||
|
} else if (arg_type->isPointer()) {
|
||||||
|
load_op = RVOpcodes::LD; // 64位指针
|
||||||
|
} else {
|
||||||
|
load_op = RVOpcodes::LW; // 32位整数
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建加载指令: lw/ld/flw vreg, offset(s0)
|
||||||
|
auto load_instr = std::make_unique<MachineInstr>(load_op);
|
||||||
|
load_instr->addOperand(std::make_unique<RegOperand>(arg_vreg));
|
||||||
|
load_instr->addOperand(std::make_unique<MemOperand>(
|
||||||
|
std::make_unique<RegOperand>(PhysicalReg::S0), // 基址为帧指针
|
||||||
|
std::make_unique<ImmOperand>(offset)
|
||||||
|
));
|
||||||
|
arg_load_instrs.push_back(std::move(load_instr));
|
||||||
|
}
|
||||||
|
arg_idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//仅当有需要加载的栈参数时,才执行插入逻辑
|
||||||
|
if (!arg_load_instrs.empty()) {
|
||||||
|
auto& entry_instrs = entry_block->getInstructions();
|
||||||
|
auto insertion_point = entry_instrs.begin(); // 默认插入点为块的开头
|
||||||
|
auto last_arg_save_it = entry_instrs.end();
|
||||||
|
|
||||||
|
// 步骤 3.2: 寻找一个安全的插入点。
|
||||||
|
// 遍历入口块的指令,找到最后一条保存“寄存器传递参数”的伪指令。
|
||||||
|
// 这样可以确保我们在所有 a0-a7 参数被保存之后,才执行可能覆盖它们的加载指令。
|
||||||
|
for (auto it = entry_instrs.begin(); it != entry_instrs.end(); ++it) {
|
||||||
|
MachineInstr* instr = it->get();
|
||||||
|
// 寻找代表保存参数到栈的伪指令
|
||||||
|
if (instr->getOpcode() == RVOpcodes::FRAME_STORE_W ||
|
||||||
|
instr->getOpcode() == RVOpcodes::FRAME_STORE_D ||
|
||||||
|
instr->getOpcode() == RVOpcodes::FRAME_STORE_F) {
|
||||||
|
|
||||||
|
// 检查被保存的值是否是寄存器参数 (arg_no < 8)
|
||||||
|
auto& operands = instr->getOperands();
|
||||||
|
if (operands.empty() || operands[0]->getKind() != MachineOperand::KIND_REG) continue;
|
||||||
|
|
||||||
|
unsigned src_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
|
||||||
|
Value* ir_value = isel->getVRegValueMap().count(src_vreg) ? isel->getVRegValueMap().at(src_vreg) : nullptr;
|
||||||
|
|
||||||
|
if (auto ir_arg = dynamic_cast<Argument*>(ir_value)) {
|
||||||
|
if (ir_arg->getIndex() < 8) {
|
||||||
|
last_arg_save_it = it; // 找到了一个保存寄存器参数的指令,更新位置
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果找到了这样的保存指令,我们的插入点就在它之后
|
||||||
|
if (last_arg_save_it != entry_instrs.end()) {
|
||||||
|
insertion_point = std::next(last_arg_save_it);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 步骤 3.3: 在计算出的安全位置,一次性插入所有新创建的参数加载指令
|
||||||
|
entry_instrs.insert(insertion_point,
|
||||||
|
std::make_move_iterator(arg_load_instrs.begin()),
|
||||||
|
std::make_move_iterator(arg_load_instrs.end()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 遍历所有机器指令,将访问局部变量的伪指令展开为真实指令
|
||||||
|
for (auto& mbb : mfunc->getBlocks()) {
|
||||||
|
std::vector<std::unique_ptr<MachineInstr>> new_instructions;
|
||||||
|
for (auto& instr_ptr : mbb->getInstructions()) {
|
||||||
|
RVOpcodes opcode = instr_ptr->getOpcode();
|
||||||
|
|
||||||
|
if (opcode == RVOpcodes::FRAME_LOAD_W || opcode == RVOpcodes::FRAME_LOAD_D || opcode == RVOpcodes::FRAME_LOAD_F) {
|
||||||
|
RVOpcodes real_load_op;
|
||||||
|
if (opcode == RVOpcodes::FRAME_LOAD_W) real_load_op = RVOpcodes::LW;
|
||||||
|
else if (opcode == RVOpcodes::FRAME_LOAD_D) real_load_op = RVOpcodes::LD;
|
||||||
|
else real_load_op = RVOpcodes::FLW;
|
||||||
|
|
||||||
|
auto& operands = instr_ptr->getOperands();
|
||||||
|
unsigned dest_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
|
||||||
|
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
|
||||||
|
int offset = frame_info.alloca_offsets.at(alloca_vreg);
|
||||||
|
auto addr_vreg = isel->getNewVReg(Type::getPointerType(Type::getIntType()));
|
||||||
|
|
||||||
|
// 展开为: addi addr_vreg, s0, offset
|
||||||
|
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||||
|
addi->addOperand(std::make_unique<RegOperand>(addr_vreg));
|
||||||
|
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||||
|
addi->addOperand(std::make_unique<ImmOperand>(offset));
|
||||||
|
new_instructions.push_back(std::move(addi));
|
||||||
|
|
||||||
|
// 展开为: lw/ld/flw dest_vreg, 0(addr_vreg)
|
||||||
|
auto load_instr = std::make_unique<MachineInstr>(real_load_op);
|
||||||
|
load_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||||
|
load_instr->addOperand(std::make_unique<MemOperand>(
|
||||||
|
std::make_unique<RegOperand>(addr_vreg),
|
||||||
|
std::make_unique<ImmOperand>(0)));
|
||||||
|
new_instructions.push_back(std::move(load_instr));
|
||||||
|
|
||||||
|
} else if (opcode == RVOpcodes::FRAME_STORE_W || opcode == RVOpcodes::FRAME_STORE_D || opcode == RVOpcodes::FRAME_STORE_F) {
|
||||||
|
RVOpcodes real_store_op;
|
||||||
|
if (opcode == RVOpcodes::FRAME_STORE_W) real_store_op = RVOpcodes::SW;
|
||||||
|
else if (opcode == RVOpcodes::FRAME_STORE_D) real_store_op = RVOpcodes::SD;
|
||||||
|
else real_store_op = RVOpcodes::FSW;
|
||||||
|
|
||||||
|
auto& operands = instr_ptr->getOperands();
|
||||||
|
unsigned src_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
|
||||||
|
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
|
||||||
|
int offset = frame_info.alloca_offsets.at(alloca_vreg);
|
||||||
|
auto addr_vreg = isel->getNewVReg(Type::getPointerType(Type::getIntType()));
|
||||||
|
|
||||||
|
// 展开为: addi addr_vreg, s0, offset
|
||||||
|
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||||
|
addi->addOperand(std::make_unique<RegOperand>(addr_vreg));
|
||||||
|
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||||
|
addi->addOperand(std::make_unique<ImmOperand>(offset));
|
||||||
|
new_instructions.push_back(std::move(addi));
|
||||||
|
|
||||||
|
// 展开为: sw/sd/fsw src_vreg, 0(addr_vreg)
|
||||||
|
auto store_instr = std::make_unique<MachineInstr>(real_store_op);
|
||||||
|
store_instr->addOperand(std::make_unique<RegOperand>(src_vreg));
|
||||||
|
store_instr->addOperand(std::make_unique<MemOperand>(
|
||||||
|
std::make_unique<RegOperand>(addr_vreg),
|
||||||
|
std::make_unique<ImmOperand>(0)));
|
||||||
|
new_instructions.push_back(std::move(store_instr));
|
||||||
|
|
||||||
|
} else if (instr_ptr->getOpcode() == RVOpcodes::FRAME_ADDR) {
|
||||||
|
auto& operands = instr_ptr->getOperands();
|
||||||
|
unsigned dest_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
|
||||||
|
unsigned alloca_vreg = static_cast<RegOperand*>(operands[1].get())->getVRegNum();
|
||||||
|
int offset = frame_info.alloca_offsets.at(alloca_vreg);
|
||||||
|
|
||||||
|
// 将 `frame_addr rd, rs` 展开为 `addi rd, s0, offset`
|
||||||
|
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||||
|
addi->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||||
|
addi->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||||
|
addi->addOperand(std::make_unique<ImmOperand>(offset));
|
||||||
|
new_instructions.push_back(std::move(addi));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
new_instructions.push_back(std::move(instr_ptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mbb->getInstructions() = std::move(new_instructions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sysy
|
||||||
@@ -1,17 +1,22 @@
|
|||||||
#include "PrologueEpilogueInsertion.h"
|
#include "PrologueEpilogueInsertion.h"
|
||||||
|
#include "RISCv64LLIR.h" // 假设包含了 PhysicalReg, RVOpcodes 等定义
|
||||||
#include "RISCv64ISel.h"
|
#include "RISCv64ISel.h"
|
||||||
#include "RISCv64RegAlloc.h" // 需要访问RegAlloc的结果
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
char PrologueEpilogueInsertionPass::ID = 0;
|
char PrologueEpilogueInsertionPass::ID = 0;
|
||||||
|
|
||||||
void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) {
|
void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) {
|
||||||
|
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
||||||
|
Function* F = mfunc->getFunc();
|
||||||
|
RISCv64ISel* isel = mfunc->getISel();
|
||||||
|
|
||||||
|
// 1. 清理 KEEPALIVE 伪指令
|
||||||
for (auto& mbb : mfunc->getBlocks()) {
|
for (auto& mbb : mfunc->getBlocks()) {
|
||||||
auto& instrs = mbb->getInstructions();
|
auto& instrs = mbb->getInstructions();
|
||||||
|
|
||||||
// 使用标准的 Erase-Remove Idiom 来删除满足条件的元素
|
|
||||||
instrs.erase(
|
instrs.erase(
|
||||||
std::remove_if(instrs.begin(), instrs.end(),
|
std::remove_if(instrs.begin(), instrs.end(),
|
||||||
[](const std::unique_ptr<MachineInstr>& instr) {
|
[](const std::unique_ptr<MachineInstr>& instr) {
|
||||||
@@ -22,39 +27,59 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
// 2. 确定需要保存的被调用者保存寄存器 (callee-saved)
|
||||||
Function* F = mfunc->getFunc();
|
|
||||||
RISCv64ISel* isel = mfunc->getISel();
|
|
||||||
|
|
||||||
// [关键] 获取寄存器分配的结果 (vreg -> preg 的映射)
|
|
||||||
// RegAlloc Pass 必须已经运行过
|
|
||||||
auto& vreg_to_preg_map = frame_info.vreg_to_preg_map;
|
auto& vreg_to_preg_map = frame_info.vreg_to_preg_map;
|
||||||
|
std::set<PhysicalReg> used_callee_saved_regs_set;
|
||||||
|
const auto& callee_saved_int = getCalleeSavedIntRegs();
|
||||||
|
const auto& callee_saved_fp = getCalleeSavedFpRegs();
|
||||||
|
|
||||||
// 完全遵循 AsmPrinter 中的计算逻辑
|
for (const auto& pair : vreg_to_preg_map) {
|
||||||
|
PhysicalReg preg = pair.second;
|
||||||
|
bool is_int_cs = std::find(callee_saved_int.begin(), callee_saved_int.end(), preg) != callee_saved_int.end();
|
||||||
|
bool is_fp_cs = std::find(callee_saved_fp.begin(), callee_saved_fp.end(), preg) != callee_saved_fp.end();
|
||||||
|
if ((is_int_cs && preg != PhysicalReg::S0) || is_fp_cs) {
|
||||||
|
used_callee_saved_regs_set.insert(preg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frame_info.callee_saved_regs_to_store.assign(
|
||||||
|
used_callee_saved_regs_set.begin(), used_callee_saved_regs_set.end()
|
||||||
|
);
|
||||||
|
std::sort(frame_info.callee_saved_regs_to_store.begin(), frame_info.callee_saved_regs_to_store.end());
|
||||||
|
frame_info.callee_saved_size = frame_info.callee_saved_regs_to_store.size() * 8;
|
||||||
|
|
||||||
|
// 3. 计算最终的栈帧总大小,包含栈溢出保护
|
||||||
int total_stack_size = frame_info.locals_size +
|
int total_stack_size = frame_info.locals_size +
|
||||||
frame_info.spill_size +
|
frame_info.spill_size +
|
||||||
frame_info.callee_saved_size +
|
frame_info.callee_saved_size +
|
||||||
16; // 为 ra 和 s0 固定的16字节
|
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;
|
int aligned_stack_size = (total_stack_size + 15) & ~15;
|
||||||
frame_info.total_size = aligned_stack_size;
|
frame_info.total_size = aligned_stack_size;
|
||||||
|
|
||||||
// 只有在需要分配栈空间时才生成指令
|
|
||||||
if (aligned_stack_size > 0) {
|
if (aligned_stack_size > 0) {
|
||||||
// --- 1. 插入序言 ---
|
// --- 4. 插入完整的序言 ---
|
||||||
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
|
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
|
||||||
auto& entry_instrs = entry_block->getInstructions();
|
auto& entry_instrs = entry_block->getInstructions();
|
||||||
|
|
||||||
std::vector<std::unique_ptr<MachineInstr>> prologue_instrs;
|
std::vector<std::unique_ptr<MachineInstr>> prologue_instrs;
|
||||||
|
|
||||||
// 1. addi sp, sp, -aligned_stack_size
|
// 4.1. 分配栈帧
|
||||||
auto alloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
auto alloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||||
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||||
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||||
alloc_stack->addOperand(std::make_unique<ImmOperand>(-aligned_stack_size));
|
alloc_stack->addOperand(std::make_unique<ImmOperand>(-aligned_stack_size));
|
||||||
prologue_instrs.push_back(std::move(alloc_stack));
|
prologue_instrs.push_back(std::move(alloc_stack));
|
||||||
|
|
||||||
// 2. sd ra, (aligned_stack_size - 8)(sp)
|
// 4.2. 保存 ra 和 s0
|
||||||
auto save_ra = std::make_unique<MachineInstr>(RVOpcodes::SD);
|
auto save_ra = std::make_unique<MachineInstr>(RVOpcodes::SD);
|
||||||
save_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
|
save_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
|
||||||
save_ra->addOperand(std::make_unique<MemOperand>(
|
save_ra->addOperand(std::make_unique<MemOperand>(
|
||||||
@@ -62,8 +87,6 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
|||||||
std::make_unique<ImmOperand>(aligned_stack_size - 8)
|
std::make_unique<ImmOperand>(aligned_stack_size - 8)
|
||||||
));
|
));
|
||||||
prologue_instrs.push_back(std::move(save_ra));
|
prologue_instrs.push_back(std::move(save_ra));
|
||||||
|
|
||||||
// 3. sd s0, (aligned_stack_size - 16)(sp)
|
|
||||||
auto save_fp = std::make_unique<MachineInstr>(RVOpcodes::SD);
|
auto save_fp = std::make_unique<MachineInstr>(RVOpcodes::SD);
|
||||||
save_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
save_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||||
save_fp->addOperand(std::make_unique<MemOperand>(
|
save_fp->addOperand(std::make_unique<MemOperand>(
|
||||||
@@ -72,66 +95,54 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
|||||||
));
|
));
|
||||||
prologue_instrs.push_back(std::move(save_fp));
|
prologue_instrs.push_back(std::move(save_fp));
|
||||||
|
|
||||||
// 4. addi s0, sp, aligned_stack_size
|
// 4.3. 设置新的帧指针 s0
|
||||||
auto set_fp = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
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::S0));
|
||||||
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||||
set_fp->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
|
set_fp->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
|
||||||
prologue_instrs.push_back(std::move(set_fp));
|
prologue_instrs.push_back(std::move(set_fp));
|
||||||
|
|
||||||
// --- 在s0设置完毕后,使用物理寄存器加载栈参数 ---
|
// 4.4. 保存所有使用到的被调用者保存寄存器
|
||||||
if (F && isel) {
|
int next_available_offset = -(16 + frame_info.locals_size + frame_info.spill_size);
|
||||||
int arg_idx = 0;
|
for (const auto& reg : frame_info.callee_saved_regs_to_store) {
|
||||||
for (Argument* arg : F->getArguments()) {
|
// 采用“先使用,后更新”逻辑
|
||||||
if (arg_idx >= 8) {
|
RVOpcodes store_op = isFPR(reg) ? RVOpcodes::FSD : RVOpcodes::SD;
|
||||||
unsigned vreg = isel->getVReg(arg);
|
auto save_cs_reg = std::make_unique<MachineInstr>(store_op);
|
||||||
|
save_cs_reg->addOperand(std::make_unique<RegOperand>(reg));
|
||||||
if (frame_info.alloca_offsets.count(vreg) && vreg_to_preg_map.count(vreg)) {
|
save_cs_reg->addOperand(std::make_unique<MemOperand>(
|
||||||
int offset = frame_info.alloca_offsets.at(vreg);
|
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||||
PhysicalReg dest_preg = vreg_to_preg_map.at(vreg);
|
std::make_unique<ImmOperand>(next_available_offset) // 使用当前偏移
|
||||||
Type* arg_type = arg->getType();
|
));
|
||||||
|
prologue_instrs.push_back(std::move(save_cs_reg));
|
||||||
if (arg_type->isFloat()) {
|
next_available_offset -= 8; // 为下一个寄存器准备偏移
|
||||||
auto load_arg = std::make_unique<MachineInstr>(RVOpcodes::FLW);
|
|
||||||
load_arg->addOperand(std::make_unique<RegOperand>(dest_preg));
|
|
||||||
load_arg->addOperand(std::make_unique<MemOperand>(
|
|
||||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
|
||||||
std::make_unique<ImmOperand>(offset)
|
|
||||||
));
|
|
||||||
prologue_instrs.push_back(std::move(load_arg));
|
|
||||||
} else {
|
|
||||||
RVOpcodes load_op = arg_type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW;
|
|
||||||
auto load_arg = std::make_unique<MachineInstr>(load_op);
|
|
||||||
load_arg->addOperand(std::make_unique<RegOperand>(dest_preg));
|
|
||||||
load_arg->addOperand(std::make_unique<MemOperand>(
|
|
||||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
|
||||||
std::make_unique<ImmOperand>(offset)
|
|
||||||
));
|
|
||||||
prologue_instrs.push_back(std::move(load_arg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arg_idx++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确定插入点
|
// 4.5. 将所有生成的序言指令一次性插入到函数入口
|
||||||
auto insert_pos = entry_instrs.begin();
|
entry_instrs.insert(entry_instrs.begin(),
|
||||||
|
std::make_move_iterator(prologue_instrs.begin()),
|
||||||
|
std::make_move_iterator(prologue_instrs.end()));
|
||||||
|
|
||||||
// 一次性将所有序言指令插入
|
// --- 5. 插入完整的尾声 ---
|
||||||
if (!prologue_instrs.empty()) {
|
|
||||||
entry_instrs.insert(insert_pos,
|
|
||||||
std::make_move_iterator(prologue_instrs.begin()),
|
|
||||||
std::make_move_iterator(prologue_instrs.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 2. 插入尾声 (此部分逻辑保持不变) ---
|
|
||||||
for (auto& mbb : mfunc->getBlocks()) {
|
for (auto& mbb : mfunc->getBlocks()) {
|
||||||
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
|
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
|
||||||
if ((*it)->getOpcode() == RVOpcodes::RET) {
|
if ((*it)->getOpcode() == RVOpcodes::RET) {
|
||||||
std::vector<std::unique_ptr<MachineInstr>> epilogue_instrs;
|
std::vector<std::unique_ptr<MachineInstr>> epilogue_instrs;
|
||||||
|
|
||||||
// 1. ld ra
|
// 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) {
|
||||||
|
RVOpcodes load_op = isFPR(reg) ? RVOpcodes::FLD : RVOpcodes::LD;
|
||||||
|
auto restore_cs_reg = std::make_unique<MachineInstr>(load_op);
|
||||||
|
restore_cs_reg->addOperand(std::make_unique<RegOperand>(reg));
|
||||||
|
restore_cs_reg->addOperand(std::make_unique<MemOperand>(
|
||||||
|
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||||
|
std::make_unique<ImmOperand>(next_available_offset_restore) // 使用当前偏移
|
||||||
|
));
|
||||||
|
epilogue_instrs.push_back(std::move(restore_cs_reg));
|
||||||
|
next_available_offset_restore -= 8; // 为下一个寄存器准备偏移
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5.2. 恢复 ra 和 s0
|
||||||
auto restore_ra = std::make_unique<MachineInstr>(RVOpcodes::LD);
|
auto restore_ra = std::make_unique<MachineInstr>(RVOpcodes::LD);
|
||||||
restore_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
|
restore_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
|
||||||
restore_ra->addOperand(std::make_unique<MemOperand>(
|
restore_ra->addOperand(std::make_unique<MemOperand>(
|
||||||
@@ -139,8 +150,6 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
|||||||
std::make_unique<ImmOperand>(aligned_stack_size - 8)
|
std::make_unique<ImmOperand>(aligned_stack_size - 8)
|
||||||
));
|
));
|
||||||
epilogue_instrs.push_back(std::move(restore_ra));
|
epilogue_instrs.push_back(std::move(restore_ra));
|
||||||
|
|
||||||
// 2. ld s0
|
|
||||||
auto restore_fp = std::make_unique<MachineInstr>(RVOpcodes::LD);
|
auto restore_fp = std::make_unique<MachineInstr>(RVOpcodes::LD);
|
||||||
restore_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
restore_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
|
||||||
restore_fp->addOperand(std::make_unique<MemOperand>(
|
restore_fp->addOperand(std::make_unique<MemOperand>(
|
||||||
@@ -149,18 +158,18 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
|||||||
));
|
));
|
||||||
epilogue_instrs.push_back(std::move(restore_fp));
|
epilogue_instrs.push_back(std::move(restore_fp));
|
||||||
|
|
||||||
// 3. addi sp, sp, aligned_stack_size
|
// 5.3. 释放栈帧
|
||||||
auto dealloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
auto dealloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||||
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||||
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||||
dealloc_stack->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
|
dealloc_stack->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
|
||||||
epilogue_instrs.push_back(std::move(dealloc_stack));
|
epilogue_instrs.push_back(std::move(dealloc_stack));
|
||||||
|
|
||||||
if (!epilogue_instrs.empty()) {
|
// 将尾声指令插入到 RET 指令之前
|
||||||
mbb->getInstructions().insert(it,
|
mbb->getInstructions().insert(it,
|
||||||
std::make_move_iterator(epilogue_instrs.begin()),
|
std::make_move_iterator(epilogue_instrs.begin()),
|
||||||
std::make_move_iterator(epilogue_instrs.end()));
|
std::make_move_iterator(epilogue_instrs.end()));
|
||||||
}
|
|
||||||
goto next_block;
|
goto next_block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
282
src/backend/RISCv64/Optimize/DivStrengthReduction.cpp
Normal file
282
src/backend/RISCv64/Optimize/DivStrengthReduction.cpp
Normal 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
|
||||||
@@ -60,7 +60,7 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
|
|||||||
case RVOpcodes::ADD: *OS << "add "; break; case RVOpcodes::ADDI: *OS << "addi "; break;
|
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::ADDW: *OS << "addw "; break; case RVOpcodes::ADDIW: *OS << "addiw "; break;
|
||||||
case RVOpcodes::SUB: *OS << "sub "; break; case RVOpcodes::SUBW: *OS << "subw "; 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::DIV: *OS << "div "; break; case RVOpcodes::DIVW: *OS << "divw "; break;
|
||||||
case RVOpcodes::REM: *OS << "rem "; break; case RVOpcodes::REMW: *OS << "remw "; 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;
|
case RVOpcodes::XOR: *OS << "xor "; break; case RVOpcodes::XORI: *OS << "xori "; break;
|
||||||
@@ -104,7 +104,7 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
|
|||||||
case RVOpcodes::FMV_S: *OS << "fmv.s "; break;
|
case RVOpcodes::FMV_S: *OS << "fmv.s "; break;
|
||||||
case RVOpcodes::FMV_W_X: *OS << "fmv.w.x "; break;
|
case RVOpcodes::FMV_W_X: *OS << "fmv.w.x "; break;
|
||||||
case RVOpcodes::FMV_X_W: *OS << "fmv.x.w "; break;
|
case RVOpcodes::FMV_X_W: *OS << "fmv.x.w "; break;
|
||||||
case RVOpcodes::CALL: { // [核心修改] 为CALL指令添加特殊处理逻辑
|
case RVOpcodes::CALL: { // 为CALL指令添加特殊处理逻辑
|
||||||
*OS << "call ";
|
*OS << "call ";
|
||||||
// 遍历所有操作数,只寻找并打印函数名标签
|
// 遍历所有操作数,只寻找并打印函数名标签
|
||||||
for (const auto& op : instr->getOperands()) {
|
for (const auto& op : instr->getOperands()) {
|
||||||
|
|||||||
@@ -12,6 +12,39 @@ std::string RISCv64CodeGen::code_gen() {
|
|||||||
return module_gen();
|
return module_gen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned RISCv64CodeGen::getTypeSizeInBytes(Type* type) {
|
||||||
|
if (!type) {
|
||||||
|
assert(false && "Cannot get size of a null type.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type->getKind()) {
|
||||||
|
// 对于SysY语言,基本类型int和float都占用4字节
|
||||||
|
case Type::kInt:
|
||||||
|
case Type::kFloat:
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
// 指针类型在RISC-V 64位架构下占用8字节
|
||||||
|
// 虽然SysY没有'int*'语法,但数组变量在IR层面本身就是指针类型
|
||||||
|
case Type::kPointer:
|
||||||
|
return 8;
|
||||||
|
|
||||||
|
// 数组类型的总大小 = 元素数量 * 单个元素的大小
|
||||||
|
case Type::kArray: {
|
||||||
|
auto arrayType = type->as<ArrayType>();
|
||||||
|
// 递归调用以计算元素大小
|
||||||
|
return arrayType->getNumElements() * getTypeSizeInBytes(arrayType->getElementType());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他类型,如Void, Label等不占用栈空间,或者不应该出现在这里
|
||||||
|
default:
|
||||||
|
// 如果遇到未处理的类型,触发断言,方便调试
|
||||||
|
// assert(false && "Unsupported type for size calculation.");
|
||||||
|
return 0; // 对于像Label或Void这样的类型,返回0是合理的
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void printInitializer(std::stringstream& ss, const ValueCounter& init_values) {
|
void printInitializer(std::stringstream& ss, const ValueCounter& init_values) {
|
||||||
for (size_t i = 0; i < init_values.getValues().size(); ++i) {
|
for (size_t i = 0; i < init_values.getValues().size(); ++i) {
|
||||||
auto val = init_values.getValues()[i];
|
auto val = init_values.getValues()[i];
|
||||||
@@ -39,18 +72,36 @@ std::string RISCv64CodeGen::module_gen() {
|
|||||||
|
|
||||||
for (const auto& global_ptr : module->getGlobals()) {
|
for (const auto& global_ptr : module->getGlobals()) {
|
||||||
GlobalValue* global = global_ptr.get();
|
GlobalValue* global = global_ptr.get();
|
||||||
|
|
||||||
|
// 使用更健壮的逻辑来判断是否为大型零初始化数组
|
||||||
|
bool is_all_zeros = true;
|
||||||
const auto& init_values = global->getInitValues();
|
const auto& init_values = global->getInitValues();
|
||||||
|
|
||||||
// 判断是否为大型零初始化数组,以便放入.bss段
|
// 检查初始化值是否全部为0
|
||||||
bool is_large_zero_array = false;
|
if (init_values.getValues().empty()) {
|
||||||
if (init_values.getValues().size() == 1) {
|
// 如果 ValueCounter 为空,GlobalValue 的构造函数会确保它是零初始化的
|
||||||
if (auto const_val = dynamic_cast<ConstantValue*>(init_values.getValues()[0])) {
|
is_all_zeros = true;
|
||||||
if (const_val->isInt() && const_val->getInt() == 0 && init_values.getNumbers()[0] > 16) {
|
} else {
|
||||||
is_large_zero_array = true;
|
for (auto val : init_values.getValues()) {
|
||||||
|
if (auto const_val = dynamic_cast<ConstantValue*>(val)) {
|
||||||
|
if (!const_val->isZero()) {
|
||||||
|
is_all_zeros = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果初始值包含非常量(例如,另一个全局变量的地址),则不认为是纯零初始化
|
||||||
|
is_all_zeros = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 使用 getTypeSizeInBytes 检查总大小是否超过阈值 (16个整数 = 64字节)
|
||||||
|
Type* allocated_type = global->getType()->as<PointerType>()->getBaseType();
|
||||||
|
unsigned total_size = getTypeSizeInBytes(allocated_type);
|
||||||
|
|
||||||
|
bool is_large_zero_array = is_all_zeros && (total_size > 64);
|
||||||
|
|
||||||
if (is_large_zero_array) {
|
if (is_large_zero_array) {
|
||||||
bss_globals.push_back(global);
|
bss_globals.push_back(global);
|
||||||
} else {
|
} else {
|
||||||
@@ -58,12 +109,12 @@ std::string RISCv64CodeGen::module_gen() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- 步骤2:生成 .bss 段的代码 (这部分不变) ---
|
// --- 步骤2:生成 .bss 段的代码 ---
|
||||||
if (!bss_globals.empty()) {
|
if (!bss_globals.empty()) {
|
||||||
ss << ".bss\n";
|
ss << ".bss\n";
|
||||||
for (GlobalValue* global : bss_globals) {
|
for (GlobalValue* global : bss_globals) {
|
||||||
unsigned count = global->getInitValues().getNumbers()[0];
|
Type* allocated_type = global->getType()->as<PointerType>()->getBaseType();
|
||||||
unsigned total_size = count * 4; // 假设元素都是4字节
|
unsigned total_size = getTypeSizeInBytes(allocated_type);
|
||||||
|
|
||||||
ss << " .align 3\n";
|
ss << " .align 3\n";
|
||||||
ss << ".globl " << global->getName() << "\n";
|
ss << ".globl " << global->getName() << "\n";
|
||||||
@@ -74,33 +125,45 @@ std::string RISCv64CodeGen::module_gen() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- [修改] 步骤3:生成 .data 段的代码 ---
|
// --- 步骤3:生成 .data 段的代码 ---
|
||||||
// 我们需要检查 data_globals 和 常量列表是否都为空
|
|
||||||
if (!data_globals.empty() || !module->getConsts().empty()) {
|
if (!data_globals.empty() || !module->getConsts().empty()) {
|
||||||
ss << ".data\n";
|
ss << ".data\n";
|
||||||
|
|
||||||
// a. 先处理普通的全局变量 (GlobalValue)
|
// a. 处理普通的全局变量 (GlobalValue)
|
||||||
for (GlobalValue* global : data_globals) {
|
for (GlobalValue* global : data_globals) {
|
||||||
|
Type* allocated_type = global->getType()->as<PointerType>()->getBaseType();
|
||||||
|
unsigned total_size = getTypeSizeInBytes(allocated_type);
|
||||||
|
|
||||||
|
ss << " .align 3\n";
|
||||||
ss << ".globl " << global->getName() << "\n";
|
ss << ".globl " << global->getName() << "\n";
|
||||||
|
ss << ".type " << global->getName() << ", @object\n";
|
||||||
|
ss << ".size " << global->getName() << ", " << total_size << "\n";
|
||||||
ss << global->getName() << ":\n";
|
ss << global->getName() << ":\n";
|
||||||
printInitializer(ss, global->getInitValues());
|
printInitializer(ss, global->getInitValues());
|
||||||
}
|
}
|
||||||
|
|
||||||
// b. [新增] 再处理全局常量 (ConstantVariable)
|
// b. 处理全局常量 (ConstantVariable)
|
||||||
for (const auto& const_ptr : module->getConsts()) {
|
for (const auto& const_ptr : module->getConsts()) {
|
||||||
ConstantVariable* cnst = const_ptr.get();
|
ConstantVariable* cnst = const_ptr.get();
|
||||||
|
Type* allocated_type = cnst->getType()->as<PointerType>()->getBaseType();
|
||||||
|
unsigned total_size = getTypeSizeInBytes(allocated_type);
|
||||||
|
|
||||||
|
ss << " .align 3\n";
|
||||||
ss << ".globl " << cnst->getName() << "\n";
|
ss << ".globl " << cnst->getName() << "\n";
|
||||||
|
ss << ".type " << cnst->getName() << ", @object\n";
|
||||||
|
ss << ".size " << cnst->getName() << ", " << total_size << "\n";
|
||||||
ss << cnst->getName() << ":\n";
|
ss << cnst->getName() << ":\n";
|
||||||
printInitializer(ss, cnst->getInitValues());
|
printInitializer(ss, cnst->getInitValues());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- 处理函数 (.text段) 的逻辑保持不变 ---
|
// --- 步骤4:处理函数 (.text段) 的逻辑 ---
|
||||||
if (!module->getFunctions().empty()) {
|
if (!module->getFunctions().empty()) {
|
||||||
ss << ".text\n";
|
ss << ".text\n";
|
||||||
for (const auto& func_pair : module->getFunctions()) {
|
for (const auto& func_pair : module->getFunctions()) {
|
||||||
if (func_pair.second.get()) {
|
if (func_pair.second.get() && !func_pair.second->getBasicBlocks().empty()) {
|
||||||
ss << function_gen(func_pair.second.get());
|
ss << function_gen(func_pair.second.get());
|
||||||
|
if (DEBUG) std::cerr << "Function: " << func_pair.first << " generated.\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,15 +174,43 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
|
|||||||
// === 完整的后端处理流水线 ===
|
// === 完整的后端处理流水线 ===
|
||||||
|
|
||||||
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
|
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
|
||||||
|
DEBUG = 0;
|
||||||
|
DEEPDEBUG = 0;
|
||||||
|
|
||||||
RISCv64ISel isel;
|
RISCv64ISel isel;
|
||||||
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
|
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
|
||||||
|
|
||||||
// 第一次调试打印输出
|
// 第一次调试打印输出
|
||||||
std::stringstream ss1;
|
std::stringstream ss_after_isel;
|
||||||
RISCv64AsmPrinter printer1(mfunc.get());
|
RISCv64AsmPrinter printer_isel(mfunc.get());
|
||||||
printer1.run(ss1, true);
|
printer_isel.run(ss_after_isel, true);
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << ss_after_isel.str();
|
||||||
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
|
||||||
|
<< ss_after_isel.str();
|
||||||
|
}
|
||||||
|
|
||||||
// 阶段 2: 指令调度 (Instruction Scheduling)
|
// 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
|
||||||
|
// 这个Pass必须在寄存器分配之前运行
|
||||||
|
EliminateFrameIndicesPass efi_pass;
|
||||||
|
efi_pass.runOnMachineFunction(mfunc.get());
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cerr << "====== stack info after eliminate frame indices ======\n";
|
||||||
|
mfunc->dumpStackFrameInfo(std::cerr);
|
||||||
|
std::stringstream ss_after_eli;
|
||||||
|
printer_isel.run(ss_after_eli, true);
|
||||||
|
std::cerr << "====== LLIR after eliminate frame indices ======\n"
|
||||||
|
<< ss_after_eli.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 阶段 2: 除法强度削弱优化 (Division Strength Reduction)
|
||||||
|
DivStrengthReduction div_strength_reduction;
|
||||||
|
div_strength_reduction.runOnMachineFunction(mfunc.get());
|
||||||
|
|
||||||
|
// 阶段 2.1: 指令调度 (Instruction Scheduling)
|
||||||
PreRA_Scheduler scheduler;
|
PreRA_Scheduler scheduler;
|
||||||
scheduler.runOnMachineFunction(mfunc.get());
|
scheduler.runOnMachineFunction(mfunc.get());
|
||||||
|
|
||||||
@@ -127,10 +218,20 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
|
|||||||
RISCv64RegAlloc reg_alloc(mfunc.get());
|
RISCv64RegAlloc reg_alloc(mfunc.get());
|
||||||
reg_alloc.run();
|
reg_alloc.run();
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cerr << "====== stack info after reg alloc ======\n";
|
||||||
|
mfunc->dumpStackFrameInfo(std::cerr);
|
||||||
|
}
|
||||||
|
|
||||||
// 阶段 3.1: 处理被调用者保存寄存器
|
// 阶段 3.1: 处理被调用者保存寄存器
|
||||||
CalleeSavedHandler callee_handler;
|
CalleeSavedHandler callee_handler;
|
||||||
callee_handler.runOnMachineFunction(mfunc.get());
|
callee_handler.runOnMachineFunction(mfunc.get());
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cerr << "====== stack info after callee handler ======\n";
|
||||||
|
mfunc->dumpStackFrameInfo(std::cerr);
|
||||||
|
}
|
||||||
|
|
||||||
// 阶段 4: 窥孔优化 (Peephole Optimization)
|
// 阶段 4: 窥孔优化 (Peephole Optimization)
|
||||||
PeepholeOptimizer peephole;
|
PeepholeOptimizer peephole;
|
||||||
peephole.runOnMachineFunction(mfunc.get());
|
peephole.runOnMachineFunction(mfunc.get());
|
||||||
@@ -143,7 +244,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
|
|||||||
PrologueEpilogueInsertionPass pei_pass;
|
PrologueEpilogueInsertionPass pei_pass;
|
||||||
pei_pass.runOnMachineFunction(mfunc.get());
|
pei_pass.runOnMachineFunction(mfunc.get());
|
||||||
|
|
||||||
// 阶段 3.3: 清理产生的大立即数
|
// 阶段 3.3: 大立即数合法化
|
||||||
LegalizeImmediatesPass legalizer;
|
LegalizeImmediatesPass legalizer;
|
||||||
legalizer.runOnMachineFunction(mfunc.get());
|
legalizer.runOnMachineFunction(mfunc.get());
|
||||||
|
|
||||||
@@ -151,8 +252,9 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
|
|||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
RISCv64AsmPrinter printer(mfunc.get());
|
RISCv64AsmPrinter printer(mfunc.get());
|
||||||
printer.run(ss);
|
printer.run(ss);
|
||||||
if (DEBUG) ss << "\n" << ss1.str(); // 将指令选择阶段的结果也包含在最终输出中
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sysy
|
} // namespace sysy
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <cmath> // For std::fabs
|
#include <cmath>
|
||||||
#include <limits> // For std::numeric_limits
|
#include <limits>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
@@ -402,7 +402,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
Value* base = nullptr;
|
Value* base = nullptr;
|
||||||
Value* offset = nullptr;
|
Value* offset = nullptr;
|
||||||
|
|
||||||
// [修改] 扩展基地址的判断,使其可以识别 AllocaInst 或 GlobalValue
|
// 扩展基地址的判断,使其可以识别 AllocaInst 或 GlobalValue
|
||||||
if (dynamic_cast<AllocaInst*>(lhs) || dynamic_cast<GlobalValue*>(lhs)) {
|
if (dynamic_cast<AllocaInst*>(lhs) || dynamic_cast<GlobalValue*>(lhs)) {
|
||||||
base = lhs;
|
base = lhs;
|
||||||
offset = rhs;
|
offset = rhs;
|
||||||
@@ -421,7 +421,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
CurMBB->addInstruction(std::move(li));
|
CurMBB->addInstruction(std::move(li));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. [修改] 根据基地址的类型,生成不同的指令来获取基地址
|
// 2. 根据基地址的类型,生成不同的指令来获取基地址
|
||||||
auto base_addr_vreg = getNewVReg(Type::getIntType()); // 创建一个新的临时vreg来存放基地址
|
auto base_addr_vreg = getNewVReg(Type::getIntType()); // 创建一个新的临时vreg来存放基地址
|
||||||
|
|
||||||
// 情况一:基地址是局部栈变量
|
// 情况一:基地址是局部栈变量
|
||||||
@@ -452,7 +452,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// [V2优点] 在BINARY节点内部按需加载常量操作数。
|
// 在BINARY节点内部按需加载常量操作数。
|
||||||
auto load_val_if_const = [&](Value* val) {
|
auto load_val_if_const = [&](Value* val) {
|
||||||
if (auto c = dynamic_cast<ConstantValue*>(val)) {
|
if (auto c = dynamic_cast<ConstantValue*>(val)) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
@@ -483,7 +483,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
auto dest_vreg = getVReg(bin);
|
auto dest_vreg = getVReg(bin);
|
||||||
auto lhs_vreg = getVReg(lhs);
|
auto lhs_vreg = getVReg(lhs);
|
||||||
|
|
||||||
// [V2优点] 融合 ADDIW 优化。
|
// 融合 ADDIW 优化。
|
||||||
if (rhs_is_imm_opt) {
|
if (rhs_is_imm_opt) {
|
||||||
auto rhs_const = dynamic_cast<ConstantValue*>(rhs);
|
auto rhs_const = dynamic_cast<ConstantValue*>(rhs);
|
||||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::ADDIW);
|
auto instr = std::make_unique<MachineInstr>(RVOpcodes::ADDIW);
|
||||||
@@ -539,6 +539,15 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
CurMBB->addInstruction(std::move(instr));
|
CurMBB->addInstruction(std::move(instr));
|
||||||
break;
|
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)
|
case BinaryInst::kICmpEQ: { // 等于 (a == b) -> (subw; seqz)
|
||||||
auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
|
auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
|
||||||
sub->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
sub->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||||
@@ -943,7 +952,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
|
|
||||||
// --- 步骤 3: 生成CALL指令 ---
|
// --- 步骤 3: 生成CALL指令 ---
|
||||||
auto call_instr = std::make_unique<MachineInstr>(RVOpcodes::CALL);
|
auto call_instr = std::make_unique<MachineInstr>(RVOpcodes::CALL);
|
||||||
// [协议] 如果函数有返回值,将它的目标虚拟寄存器作为第一个操作数
|
// 如果函数有返回值,将它的目标虚拟寄存器作为第一个操作数
|
||||||
if (!call->getType()->isVoid()) {
|
if (!call->getType()->isVoid()) {
|
||||||
unsigned dest_vreg = getVReg(call);
|
unsigned dest_vreg = getVReg(call);
|
||||||
call_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
call_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||||
@@ -1020,7 +1029,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
} else {
|
} else {
|
||||||
// --- 处理整数/指针返回值 ---
|
// --- 处理整数/指针返回值 ---
|
||||||
// 返回值需要被放入 a0
|
// 返回值需要被放入 a0
|
||||||
// [V2优点] 在RETURN节点内加载常量返回值
|
// 在RETURN节点内加载常量返回值
|
||||||
if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) {
|
if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) {
|
||||||
auto li_instr = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
auto li_instr = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
||||||
li_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
|
li_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
|
||||||
@@ -1034,7 +1043,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// [V1设计保留] 函数尾声(epilogue)不由RETURN节点生成,
|
// 函数尾声(epilogue)不由RETURN节点生成,
|
||||||
// 而是由后续的AsmPrinter或其它Pass统一处理,这是一种常见且有效的模块化设计。
|
// 而是由后续的AsmPrinter或其它Pass统一处理,这是一种常见且有效的模块化设计。
|
||||||
auto ret_mi = std::make_unique<MachineInstr>(RVOpcodes::RET);
|
auto ret_mi = std::make_unique<MachineInstr>(RVOpcodes::RET);
|
||||||
CurMBB->addInstruction(std::move(ret_mi));
|
CurMBB->addInstruction(std::move(ret_mi));
|
||||||
@@ -1048,7 +1057,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
auto then_bb_name = cond_br->getThenBlock()->getName();
|
auto then_bb_name = cond_br->getThenBlock()->getName();
|
||||||
auto else_bb_name = cond_br->getElseBlock()->getName();
|
auto else_bb_name = cond_br->getElseBlock()->getName();
|
||||||
|
|
||||||
// [优化] 检查分支条件是否为编译期常量
|
// 检查分支条件是否为编译期常量
|
||||||
if (auto const_cond = dynamic_cast<ConstantValue*>(condition)) {
|
if (auto const_cond = dynamic_cast<ConstantValue*>(condition)) {
|
||||||
// 如果条件是常量,直接生成一个无条件跳转J,而不是BNE
|
// 如果条件是常量,直接生成一个无条件跳转J,而不是BNE
|
||||||
if (const_cond->getInt() != 0) { // 条件为 true
|
if (const_cond->getInt() != 0) { // 条件为 true
|
||||||
@@ -1063,7 +1072,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
}
|
}
|
||||||
// 如果条件不是常量,则执行标准流程
|
// 如果条件不是常量,则执行标准流程
|
||||||
else {
|
else {
|
||||||
// [修复] 为条件变量生成加载指令(如果它是常量的话,尽管上面已经处理了)
|
// 为条件变量生成加载指令(如果它是常量的话,尽管上面已经处理了)
|
||||||
// 这一步是为了逻辑完整,以防有其他类型的常量没有被捕获
|
// 这一步是为了逻辑完整,以防有其他类型的常量没有被捕获
|
||||||
if (auto const_val = dynamic_cast<ConstantValue*>(condition)) {
|
if (auto const_val = dynamic_cast<ConstantValue*>(condition)) {
|
||||||
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
||||||
@@ -1097,7 +1106,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case DAGNode::MEMSET: {
|
case DAGNode::MEMSET: {
|
||||||
// [V1设计保留] Memset的核心展开逻辑在虚拟寄存器层面是正确的,无需修改。
|
// Memset的核心展开逻辑在虚拟寄存器层面是正确的,无需修改。
|
||||||
// 之前的bug是由于其输入(地址、值、大小)的虚拟寄存器未被正确初始化。
|
// 之前的bug是由于其输入(地址、值、大小)的虚拟寄存器未被正确初始化。
|
||||||
// 在修复了CONSTANT/ALLOCA_ADDR的加载问题后,此处的逻辑现在可以正常工作。
|
// 在修复了CONSTANT/ALLOCA_ADDR的加载问题后,此处的逻辑现在可以正常工作。
|
||||||
|
|
||||||
@@ -1280,14 +1289,19 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
if (stride != 0) {
|
if (stride != 0) {
|
||||||
// --- 为当前索引和步长生成偏移计算指令 ---
|
// --- 为当前索引和步长生成偏移计算指令 ---
|
||||||
auto offset_vreg = getNewVReg();
|
auto offset_vreg = getNewVReg();
|
||||||
auto index_vreg = getVReg(indexValue);
|
|
||||||
|
|
||||||
// 如果索引是常量,先用 LI 指令加载到虚拟寄存器
|
// 处理索引 - 区分常量与动态值
|
||||||
|
unsigned index_vreg;
|
||||||
if (auto const_index = dynamic_cast<ConstantValue*>(indexValue)) {
|
if (auto const_index = dynamic_cast<ConstantValue*>(indexValue)) {
|
||||||
|
// 对于常量索引,直接创建新的虚拟寄存器
|
||||||
|
index_vreg = getNewVReg();
|
||||||
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
||||||
li->addOperand(std::make_unique<RegOperand>(index_vreg));
|
li->addOperand(std::make_unique<RegOperand>(index_vreg));
|
||||||
li->addOperand(std::make_unique<ImmOperand>(const_index->getInt()));
|
li->addOperand(std::make_unique<ImmOperand>(const_index->getInt()));
|
||||||
CurMBB->addInstruction(std::move(li));
|
CurMBB->addInstruction(std::move(li));
|
||||||
|
} else {
|
||||||
|
// 对于动态索引,使用已存在的虚拟寄存器
|
||||||
|
index_vreg = getVReg(indexValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 优化:如果步长是1,可以直接移动(MV)作为偏移量,无需乘法
|
// 优化:如果步长是1,可以直接移动(MV)作为偏移量,无需乘法
|
||||||
@@ -1445,7 +1459,7 @@ std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicB
|
|||||||
|
|
||||||
// 依次添加所有索引作为后续的操作数
|
// 依次添加所有索引作为后续的操作数
|
||||||
for (auto index : gep->getIndices()) {
|
for (auto index : gep->getIndices()) {
|
||||||
// [修复] 从 Use 对象中获取真正的 Value*
|
// 从 Use 对象中获取真正的 Value*
|
||||||
gep_node->operands.push_back(get_operand_node(index->getValue(), value_to_node, nodes_storage));
|
gep_node->operands.push_back(get_operand_node(index->getValue(), value_to_node, nodes_storage));
|
||||||
}
|
}
|
||||||
} else if (auto load = dynamic_cast<LoadInst*>(inst)) {
|
} else if (auto load = dynamic_cast<LoadInst*>(inst)) {
|
||||||
@@ -1473,7 +1487,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);
|
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->getLhs(), value_to_node, nodes_storage));
|
||||||
fbin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
|
fbin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
|
||||||
@@ -1549,7 +1563,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) {
|
void RISCv64ISel::print_dag(const std::vector<std::unique_ptr<DAGNode>>& dag, const std::string& bb_name) {
|
||||||
// 检查是否有DEBUG宏或者全局变量,避免在非调试模式下打印
|
// 检查是否有DEBUG宏或者全局变量,避免在非调试模式下打印
|
||||||
// if (!DEBUG) return;
|
// if (!DEBUG) return;
|
||||||
|
|||||||
@@ -1,6 +1,122 @@
|
|||||||
#include "RISCv64LLIR.h"
|
#include "RISCv64LLIR.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <iostream> // 用于 std::ostream 和 std::cerr
|
||||||
|
#include <string> // 用于 std::string
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
|
// 辅助函数:将 PhysicalReg 枚举转换为可读的字符串
|
||||||
|
std::string regToString(PhysicalReg reg) {
|
||||||
|
switch (reg) {
|
||||||
|
case PhysicalReg::ZERO: return "x0"; case PhysicalReg::RA: return "ra";
|
||||||
|
case PhysicalReg::SP: return "sp"; case PhysicalReg::GP: return "gp";
|
||||||
|
case PhysicalReg::TP: return "tp"; case PhysicalReg::T0: return "t0";
|
||||||
|
case PhysicalReg::T1: return "t1"; case PhysicalReg::T2: return "t2";
|
||||||
|
case PhysicalReg::S0: return "s0"; case PhysicalReg::S1: return "s1";
|
||||||
|
case PhysicalReg::A0: return "a0"; case PhysicalReg::A1: return "a1";
|
||||||
|
case PhysicalReg::A2: return "a2"; case PhysicalReg::A3: return "a3";
|
||||||
|
case PhysicalReg::A4: return "a4"; case PhysicalReg::A5: return "a5";
|
||||||
|
case PhysicalReg::A6: return "a6"; case PhysicalReg::A7: return "a7";
|
||||||
|
case PhysicalReg::S2: return "s2"; case PhysicalReg::S3: return "s3";
|
||||||
|
case PhysicalReg::S4: return "s4"; case PhysicalReg::S5: return "s5";
|
||||||
|
case PhysicalReg::S6: return "s6"; case PhysicalReg::S7: return "s7";
|
||||||
|
case PhysicalReg::S8: return "s8"; case PhysicalReg::S9: return "s9";
|
||||||
|
case PhysicalReg::S10: return "s10"; case PhysicalReg::S11: return "s11";
|
||||||
|
case PhysicalReg::T3: return "t3"; case PhysicalReg::T4: return "t4";
|
||||||
|
case PhysicalReg::T5: return "t5"; case PhysicalReg::T6: return "t6";
|
||||||
|
case PhysicalReg::F0: return "f0"; case PhysicalReg::F1: return "f1";
|
||||||
|
case PhysicalReg::F2: return "f2"; case PhysicalReg::F3: return "f3";
|
||||||
|
case PhysicalReg::F4: return "f4"; case PhysicalReg::F5: return "f5";
|
||||||
|
case PhysicalReg::F6: return "f6"; case PhysicalReg::F7: return "f7";
|
||||||
|
case PhysicalReg::F8: return "f8"; case PhysicalReg::F9: return "f9";
|
||||||
|
case PhysicalReg::F10: return "f10"; case PhysicalReg::F11: return "f11";
|
||||||
|
case PhysicalReg::F12: return "f12"; case PhysicalReg::F13: return "f13";
|
||||||
|
case PhysicalReg::F14: return "f14"; case PhysicalReg::F15: return "f15";
|
||||||
|
case PhysicalReg::F16: return "f16"; case PhysicalReg::F17: return "f17";
|
||||||
|
case PhysicalReg::F18: return "f18"; case PhysicalReg::F19: return "f19";
|
||||||
|
case PhysicalReg::F20: return "f20"; case PhysicalReg::F21: return "f21";
|
||||||
|
case PhysicalReg::F22: return "f22"; case PhysicalReg::F23: return "f23";
|
||||||
|
case PhysicalReg::F24: return "f24"; case PhysicalReg::F25: return "f25";
|
||||||
|
case PhysicalReg::F26: return "f26"; case PhysicalReg::F27: return "f27";
|
||||||
|
case PhysicalReg::F28: return "f28"; case PhysicalReg::F29: return "f29";
|
||||||
|
case PhysicalReg::F30: return "f30"; case PhysicalReg::F31: return "f31";
|
||||||
|
default: return "UNKNOWN_REG";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打印栈帧信息的完整实现
|
||||||
|
void MachineFunction::dumpStackFrameInfo(std::ostream& os) const {
|
||||||
|
const StackFrameInfo& info = frame_info;
|
||||||
|
|
||||||
|
os << "--- Stack Frame Info for function '" << getName() << "' ---\n";
|
||||||
|
|
||||||
|
// 打印尺寸信息
|
||||||
|
os << " Sizes:\n";
|
||||||
|
os << " Total Size: " << info.total_size << " bytes\n";
|
||||||
|
os << " Locals Size: " << info.locals_size << " bytes\n";
|
||||||
|
os << " Spill Size: " << info.spill_size << " bytes\n";
|
||||||
|
os << " Callee-Saved Size: " << info.callee_saved_size << " bytes\n";
|
||||||
|
os << "\n";
|
||||||
|
|
||||||
|
// 打印 Alloca 变量的偏移量
|
||||||
|
os << " Alloca Offsets (vreg -> offset from FP):\n";
|
||||||
|
if (info.alloca_offsets.empty()) {
|
||||||
|
os << " (None)\n";
|
||||||
|
} else {
|
||||||
|
for (const auto& pair : info.alloca_offsets) {
|
||||||
|
os << " %vreg" << pair.first << " -> " << pair.second << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os << "\n";
|
||||||
|
|
||||||
|
// 打印溢出变量的偏移量
|
||||||
|
os << " Spill Offsets (vreg -> offset from FP):\n";
|
||||||
|
if (info.spill_offsets.empty()) {
|
||||||
|
os << " (None)\n";
|
||||||
|
} else {
|
||||||
|
for (const auto& pair : info.spill_offsets) {
|
||||||
|
os << " %vreg" << pair.first << " -> " << pair.second << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os << "\n";
|
||||||
|
|
||||||
|
// 打印使用的被调用者保存寄存器
|
||||||
|
os << " Used Callee-Saved Registers:\n";
|
||||||
|
if (info.used_callee_saved_regs.empty()) {
|
||||||
|
os << " (None)\n";
|
||||||
|
} else {
|
||||||
|
os << " { ";
|
||||||
|
for (const auto& reg : info.used_callee_saved_regs) {
|
||||||
|
os << regToString(reg) << " ";
|
||||||
|
}
|
||||||
|
os << "}\n";
|
||||||
|
}
|
||||||
|
os << "\n";
|
||||||
|
|
||||||
|
// 打印需要保存/恢复的被调用者保存寄存器 (有序)
|
||||||
|
os << " Callee-Saved Registers to Store/Restore:\n";
|
||||||
|
if (info.callee_saved_regs_to_store.empty()) {
|
||||||
|
os << " (None)\n";
|
||||||
|
} else {
|
||||||
|
os << " [ ";
|
||||||
|
for (const auto& reg : info.callee_saved_regs_to_store) {
|
||||||
|
os << regToString(reg) << " ";
|
||||||
|
}
|
||||||
|
os << "]\n";
|
||||||
|
}
|
||||||
|
os << "\n";
|
||||||
|
|
||||||
|
// 打印最终的寄存器分配结果
|
||||||
|
os << " Final Register Allocation Map (vreg -> preg):\n";
|
||||||
|
if (info.vreg_to_preg_map.empty()) {
|
||||||
|
os << " (None)\n";
|
||||||
|
} else {
|
||||||
|
for (const auto& pair : info.vreg_to_preg_map) {
|
||||||
|
os << " %vreg" << pair.first << " -> " << regToString(pair.second) << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
os << "---------------------------------------------------\n";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
20
src/include/backend/RISCv64/Handler/EliminateFrameIndices.h
Normal file
20
src/include/backend/RISCv64/Handler/EliminateFrameIndices.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef ELIMINATE_FRAME_INDICES_H
|
||||||
|
#define ELIMINATE_FRAME_INDICES_H
|
||||||
|
|
||||||
|
#include "RISCv64LLIR.h"
|
||||||
|
|
||||||
|
namespace sysy {
|
||||||
|
|
||||||
|
class EliminateFrameIndicesPass {
|
||||||
|
public:
|
||||||
|
// Pass 的主入口函数
|
||||||
|
void runOnMachineFunction(MachineFunction* mfunc);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// 帮助计算类型大小的辅助函数,从原RegAlloc中移出
|
||||||
|
unsigned getTypeSizeInBytes(Type* type);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sysy
|
||||||
|
|
||||||
|
#endif // ELIMINATE_FRAME_INDICES_H
|
||||||
30
src/include/backend/RISCv64/Optimize/DivStrengthReduction.h
Normal file
30
src/include/backend/RISCv64/Optimize/DivStrengthReduction.h
Normal 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
|
||||||
@@ -22,6 +22,9 @@ private:
|
|||||||
// 函数级代码生成 (实现新的流水线)
|
// 函数级代码生成 (实现新的流水线)
|
||||||
std::string function_gen(Function* func);
|
std::string function_gen(Function* func);
|
||||||
|
|
||||||
|
// 私有辅助函数,用于根据类型计算其占用的字节数。
|
||||||
|
unsigned getTypeSizeInBytes(Type* type);
|
||||||
|
|
||||||
Module* module;
|
Module* module;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "IR.h" // 确保包含了您自己的IR头文件
|
#include "IR.h" // 确保包含了您自己的IR头文件
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -38,14 +39,14 @@ enum class PhysicalReg {
|
|||||||
|
|
||||||
// 用于内部表示物理寄存器在干扰图中的节点ID(一个简单的特殊ID,确保不与vreg_counter冲突)
|
// 用于内部表示物理寄存器在干扰图中的节点ID(一个简单的特殊ID,确保不与vreg_counter冲突)
|
||||||
// 假设 vreg_counter 不会达到这么大的值
|
// 假设 vreg_counter 不会达到这么大的值
|
||||||
PHYS_REG_START_ID = 100000,
|
PHYS_REG_START_ID = 1000000,
|
||||||
PHYS_REG_END_ID = PHYS_REG_START_ID + 320, // 预留足够的空间
|
PHYS_REG_END_ID = PHYS_REG_START_ID + 320, // 预留足够的空间
|
||||||
};
|
};
|
||||||
|
|
||||||
// RISC-V 指令操作码枚举
|
// RISC-V 指令操作码枚举
|
||||||
enum class RVOpcodes {
|
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,
|
XOR, XORI, OR, ORI, AND, ANDI,
|
||||||
// 移位指令
|
// 移位指令
|
||||||
@@ -195,6 +196,11 @@ public:
|
|||||||
preg = new_preg;
|
preg = new_preg;
|
||||||
is_virtual = false;
|
is_virtual = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setVRegNum(unsigned new_vreg_num) {
|
||||||
|
vreg_num = new_vreg_num;
|
||||||
|
is_virtual = true; // 确保设置vreg时,操作数状态正确
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
unsigned vreg_num = 0;
|
unsigned vreg_num = 0;
|
||||||
PhysicalReg preg = PhysicalReg::ZERO;
|
PhysicalReg preg = PhysicalReg::ZERO;
|
||||||
@@ -274,14 +280,15 @@ private:
|
|||||||
// 栈帧信息
|
// 栈帧信息
|
||||||
struct StackFrameInfo {
|
struct StackFrameInfo {
|
||||||
int locals_size = 0; // 仅为AllocaInst分配的大小
|
int locals_size = 0; // 仅为AllocaInst分配的大小
|
||||||
|
int locals_end_offset = 0; // 记录局部变量分配结束后的偏移量(相对于s0,为负)
|
||||||
int spill_size = 0; // 仅为溢出分配的大小
|
int spill_size = 0; // 仅为溢出分配的大小
|
||||||
int total_size = 0; // 总大小
|
int total_size = 0; // 总大小
|
||||||
int callee_saved_size = 0; // 保存寄存器的大小
|
int callee_saved_size = 0; // 保存寄存器的大小
|
||||||
std::map<unsigned, int> alloca_offsets; // <AllocaInst的vreg, 栈偏移>
|
std::map<unsigned, int> alloca_offsets; // <AllocaInst的vreg, 栈偏移>
|
||||||
std::map<unsigned, int> spill_offsets; // <溢出vreg, 栈偏移>
|
std::map<unsigned, int> spill_offsets; // <溢出vreg, 栈偏移>
|
||||||
std::set<PhysicalReg> used_callee_saved_regs; // 使用的保存寄存器
|
std::set<PhysicalReg> used_callee_saved_regs; // 使用的保存寄存器
|
||||||
std::map<unsigned, PhysicalReg> vreg_to_preg_map;
|
std::map<unsigned, PhysicalReg> vreg_to_preg_map; // RegAlloc最终的分配结果
|
||||||
std::vector<PhysicalReg> callee_saved_regs; // 用于存储需要保存的被调用者保存寄存器列表
|
std::vector<PhysicalReg> callee_saved_regs_to_store; // 已排序的、需要存取的被调用者保存寄存器
|
||||||
};
|
};
|
||||||
|
|
||||||
// 机器函数
|
// 机器函数
|
||||||
@@ -295,7 +302,7 @@ public:
|
|||||||
StackFrameInfo& getFrameInfo() { return frame_info; }
|
StackFrameInfo& getFrameInfo() { return frame_info; }
|
||||||
const std::vector<std::unique_ptr<MachineBasicBlock>>& getBlocks() const { return blocks; }
|
const std::vector<std::unique_ptr<MachineBasicBlock>>& getBlocks() const { return blocks; }
|
||||||
std::vector<std::unique_ptr<MachineBasicBlock>>& getBlocks() { return blocks; }
|
std::vector<std::unique_ptr<MachineBasicBlock>>& getBlocks() { return blocks; }
|
||||||
|
void dumpStackFrameInfo(std::ostream& os = std::cerr) const;
|
||||||
void addBlock(std::unique_ptr<MachineBasicBlock> block) {
|
void addBlock(std::unique_ptr<MachineBasicBlock> block) {
|
||||||
blocks.push_back(std::move(block));
|
blocks.push_back(std::move(block));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,10 @@
|
|||||||
#include "CalleeSavedHandler.h"
|
#include "CalleeSavedHandler.h"
|
||||||
#include "LegalizeImmediates.h"
|
#include "LegalizeImmediates.h"
|
||||||
#include "PrologueEpilogueInsertion.h"
|
#include "PrologueEpilogueInsertion.h"
|
||||||
|
#include "EliminateFrameIndices.h"
|
||||||
#include "Pass.h"
|
#include "Pass.h"
|
||||||
|
#include "DivStrengthReduction.h"
|
||||||
|
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,15 @@
|
|||||||
|
|
||||||
#include "RISCv64LLIR.h"
|
#include "RISCv64LLIR.h"
|
||||||
#include "RISCv64ISel.h" // 包含 RISCv64ISel.h 以访问 ISel 和 Value 类型
|
#include "RISCv64ISel.h" // 包含 RISCv64ISel.h 以访问 ISel 和 Value 类型
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
extern int DEBUG;
|
extern int DEBUG;
|
||||||
extern int DEEPDEBUG;
|
extern int DEEPDEBUG;
|
||||||
|
extern int DEBUGLENGTH; // 用于限制调试输出的长度
|
||||||
|
extern int DEEPERDEBUG; // 用于更深层次的调试输出
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
@@ -17,58 +23,98 @@ public:
|
|||||||
void run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using LiveSet = std::set<unsigned>; // 活跃虚拟寄存器集合
|
// 类型定义,与Python版本对应
|
||||||
using InterferenceGraph = std::map<unsigned, std::set<unsigned>>;
|
using VRegSet = std::set<unsigned>;
|
||||||
|
using InterferenceGraph = std::map<unsigned, VRegSet>;
|
||||||
|
using VRegStack = std::vector<unsigned>; // 使用vector模拟栈,方便遍历
|
||||||
|
using MoveList = std::map<unsigned, std::set<const MachineInstr*>>;
|
||||||
|
using AliasMap = std::map<unsigned, unsigned>;
|
||||||
|
using ColorMap = std::map<unsigned, PhysicalReg>;
|
||||||
|
using VRegMoveSet = std::set<const MachineInstr*>;
|
||||||
|
|
||||||
// 栈帧管理
|
// --- 核心算法流程 ---
|
||||||
void eliminateFrameIndices();
|
void initialize();
|
||||||
|
void build();
|
||||||
|
void makeWorklist();
|
||||||
|
void simplify();
|
||||||
|
void coalesce();
|
||||||
|
void freeze();
|
||||||
|
void selectSpill();
|
||||||
|
void assignColors();
|
||||||
|
void rewriteProgram();
|
||||||
|
bool doAllocation();
|
||||||
|
void applyColoring();
|
||||||
|
|
||||||
// 活跃性分析
|
void dumpState(const std::string &stage);
|
||||||
|
|
||||||
|
void precolorByCallingConvention();
|
||||||
|
|
||||||
|
// --- 辅助函数 ---
|
||||||
|
void getInstrUseDef(const MachineInstr* instr, VRegSet& use, VRegSet& def);
|
||||||
|
void getInstrUseDef_Liveness(const MachineInstr *instr, VRegSet &use, VRegSet &def);
|
||||||
|
void addEdge(unsigned u, unsigned v);
|
||||||
|
VRegSet adjacent(unsigned n);
|
||||||
|
VRegMoveSet nodeMoves(unsigned n);
|
||||||
|
bool moveRelated(unsigned n);
|
||||||
|
void decrementDegree(unsigned m);
|
||||||
|
void enableMoves(const VRegSet& nodes);
|
||||||
|
unsigned getAlias(unsigned n);
|
||||||
|
void addWorklist(unsigned u);
|
||||||
|
bool briggsHeuristic(unsigned u, unsigned v);
|
||||||
|
bool georgeHeuristic(unsigned u, unsigned v);
|
||||||
|
void combine(unsigned u, unsigned v);
|
||||||
|
void freezeMoves(unsigned u);
|
||||||
|
void collectUsedCalleeSavedRegs();
|
||||||
|
bool isFPVReg(unsigned vreg) const;
|
||||||
|
std::string regToString(PhysicalReg reg);
|
||||||
|
std::string regIdToString(unsigned id);
|
||||||
|
|
||||||
|
// --- 活跃性分析 ---
|
||||||
void analyzeLiveness();
|
void analyzeLiveness();
|
||||||
|
|
||||||
// 构建干扰图
|
|
||||||
void buildInterferenceGraph();
|
|
||||||
|
|
||||||
// 图着色分配寄存器
|
|
||||||
void colorGraph();
|
|
||||||
|
|
||||||
// 重写函数,替换vreg并插入溢出代码
|
|
||||||
void rewriteFunction();
|
|
||||||
|
|
||||||
// 辅助函数,获取指令的Use/Def集合
|
|
||||||
void getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet& def);
|
|
||||||
|
|
||||||
// 辅助函数,处理调用约定
|
|
||||||
void handleCallingConvention();
|
|
||||||
|
|
||||||
MachineFunction* MFunc;
|
MachineFunction* MFunc;
|
||||||
|
RISCv64ISel* ISel;
|
||||||
|
|
||||||
// 活跃性分析结果
|
// --- 算法数据结构 ---
|
||||||
std::map<const MachineInstr*, LiveSet> live_in_map;
|
// 寄存器池
|
||||||
std::map<const MachineInstr*, LiveSet> live_out_map;
|
|
||||||
|
|
||||||
// 干扰图
|
|
||||||
InterferenceGraph interference_graph;
|
|
||||||
|
|
||||||
// 图着色结果
|
|
||||||
std::map<unsigned, PhysicalReg> color_map; // vreg -> preg
|
|
||||||
std::set<unsigned> spilled_vregs; // 被溢出的vreg集合
|
|
||||||
|
|
||||||
// 可用的物理寄存器池
|
|
||||||
std::vector<PhysicalReg> allocable_int_regs;
|
std::vector<PhysicalReg> allocable_int_regs;
|
||||||
std::vector<PhysicalReg> allocable_fp_regs;
|
std::vector<PhysicalReg> allocable_fp_regs;
|
||||||
|
int K_int; // 整数寄存器数量
|
||||||
|
int K_fp; // 浮点寄存器数量
|
||||||
|
|
||||||
// 存储vreg到IR Value*的反向映射
|
// 节点集合
|
||||||
// 这个map将在run()函数开始时被填充,并在rewriteFunction()中使用。
|
VRegSet precolored; // 预着色的节点 (物理寄存器)
|
||||||
std::map<unsigned, Value*> vreg_to_value_map;
|
VRegSet initial; // 初始的、所有待处理的虚拟寄存器节点
|
||||||
std::map<PhysicalReg, unsigned> preg_to_vreg_id_map; // 物理寄存器到特殊vreg ID的映射
|
VRegSet simplifyWorklist;
|
||||||
|
VRegSet freezeWorklist;
|
||||||
|
VRegSet spillWorklist;
|
||||||
|
VRegSet spilledNodes;
|
||||||
|
VRegSet coalescedNodes;
|
||||||
|
VRegSet coloredNodes;
|
||||||
|
VRegStack selectStack;
|
||||||
|
|
||||||
// 用于计算类型大小的辅助函数
|
// Move指令相关
|
||||||
unsigned getTypeSizeInBytes(Type* type);
|
std::set<const MachineInstr*> coalescedMoves;
|
||||||
|
std::set<const MachineInstr*> constrainedMoves;
|
||||||
|
std::set<const MachineInstr*> frozenMoves;
|
||||||
|
std::set<const MachineInstr*> worklistMoves;
|
||||||
|
std::set<const MachineInstr*> activeMoves;
|
||||||
|
|
||||||
// 辅助函数,用于打印集合
|
// 数据结构
|
||||||
static void printLiveSet(const LiveSet& s, const std::string& name, std::ostream& os);
|
InterferenceGraph adjSet;
|
||||||
|
std::map<unsigned, VRegSet> adjList; // 邻接表
|
||||||
|
std::map<unsigned, int> degree;
|
||||||
|
MoveList moveList;
|
||||||
|
AliasMap alias;
|
||||||
|
ColorMap color_map;
|
||||||
|
|
||||||
|
// 活跃性分析结果
|
||||||
|
std::map<const MachineInstr*, VRegSet> live_in_map;
|
||||||
|
std::map<const MachineInstr*, VRegSet> live_out_map;
|
||||||
|
|
||||||
|
// VReg -> Value* 和 VReg -> Type* 的映射
|
||||||
|
const std::map<unsigned, Value*>& vreg_to_value_map;
|
||||||
|
const std::map<unsigned, Type*>& vreg_type_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sysy
|
} // namespace sysy
|
||||||
|
|||||||
@@ -514,12 +514,15 @@ public:
|
|||||||
explicit BasicBlock(Function *parent, const std::string &name = "")
|
explicit BasicBlock(Function *parent, const std::string &name = "")
|
||||||
: Value(Type::getLabelType(), name), parent(parent) {}
|
: Value(Type::getLabelType(), name), parent(parent) {}
|
||||||
~BasicBlock() override {
|
~BasicBlock() override {
|
||||||
for (auto pre : predecessors) {
|
// for (auto pre : predecessors) {
|
||||||
pre->removeSuccessor(this);
|
// pre->removeSuccessor(this);
|
||||||
}
|
// }
|
||||||
for (auto suc : successors) {
|
// for (auto suc : successors) {
|
||||||
suc->removePredecessor(this);
|
// suc->removePredecessor(this);
|
||||||
}
|
// }
|
||||||
|
// 这些关系应该在 BasicBlock 被从 Function 中移除时,
|
||||||
|
// 由负责 CFG 优化的 Pass (例如 SCCP 的 RemoveDeadBlock) 显式地清理。
|
||||||
|
// 析构函数只负责清理 BasicBlock 自身拥有的资源(例如,指令列表)。
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -573,7 +576,9 @@ public:
|
|||||||
if (iter != predecessors.end()) {
|
if (iter != predecessors.end()) {
|
||||||
predecessors.erase(iter);
|
predecessors.erase(iter);
|
||||||
} else {
|
} else {
|
||||||
assert(false);
|
// 如果没有找到前驱块,可能是因为它已经被移除或不存在
|
||||||
|
// 这可能是一个错误情况,或者是因为在CFG优化过程中已经处理
|
||||||
|
// assert(false && "Predecessor block not found in BasicBlock");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void removeSuccessor(BasicBlock *block) {
|
void removeSuccessor(BasicBlock *block) {
|
||||||
@@ -581,7 +586,9 @@ public:
|
|||||||
if (iter != successors.end()) {
|
if (iter != successors.end()) {
|
||||||
successors.erase(iter);
|
successors.erase(iter);
|
||||||
} else {
|
} else {
|
||||||
assert(false);
|
// 如果没有找到后继块,可能是因为它已经被移除或不存在
|
||||||
|
// 这可能是一个错误情况,或者是因为在CFG优化过程中已经处理
|
||||||
|
// assert(false && "Successor block not found in BasicBlock");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void replacePredecessor(BasicBlock *oldBlock, BasicBlock *newBlock) {
|
void replacePredecessor(BasicBlock *oldBlock, BasicBlock *newBlock) {
|
||||||
@@ -599,7 +606,7 @@ public:
|
|||||||
prev->addSuccessor(next);
|
prev->addSuccessor(next);
|
||||||
next->addPredecessor(prev);
|
next->addPredecessor(prev);
|
||||||
}
|
}
|
||||||
void removeInst(iterator pos) { instructions.erase(pos); }
|
iterator removeInst(iterator pos) { return instructions.erase(pos); }
|
||||||
void removeInst(Instruction *inst) {
|
void removeInst(Instruction *inst) {
|
||||||
auto pos = std::find_if(instructions.begin(), instructions.end(),
|
auto pos = std::find_if(instructions.begin(), instructions.end(),
|
||||||
[inst](const std::unique_ptr<Instruction> &i) { return i.get() == inst; });
|
[inst](const std::unique_ptr<Instruction> &i) { return i.get() == inst; });
|
||||||
@@ -626,6 +633,21 @@ class User : public Value {
|
|||||||
explicit User(Type *type, const std::string &name = "") : Value(type, name) {}
|
explicit User(Type *type, const std::string &name = "") : Value(type, name) {}
|
||||||
|
|
||||||
public:
|
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 引用计数降为0,Use 对象本身也会被销毁。
|
||||||
|
// }
|
||||||
unsigned getNumOperands() const { return operands.size(); } ///< 获取操作数数量
|
unsigned getNumOperands() const { return operands.size(); } ///< 获取操作数数量
|
||||||
auto operand_begin() const { return operands.begin(); } ///< 返回操作数列表的开头迭代器
|
auto operand_begin() const { return operands.begin(); } ///< 返回操作数列表的开头迭代器
|
||||||
auto operand_end() const { return operands.end(); } ///< 返回操作数列表的结尾迭代器
|
auto operand_end() const { return operands.end(); } ///< 返回操作数列表的结尾迭代器
|
||||||
@@ -695,19 +717,19 @@ class Instruction : public User {
|
|||||||
kCondBr = 0x1UL << 30,
|
kCondBr = 0x1UL << 30,
|
||||||
kBr = 0x1UL << 31,
|
kBr = 0x1UL << 31,
|
||||||
kReturn = 0x1UL << 32,
|
kReturn = 0x1UL << 32,
|
||||||
|
kUnreachable = 0x1UL << 33,
|
||||||
// mem op
|
// mem op
|
||||||
kAlloca = 0x1UL << 33,
|
kAlloca = 0x1UL << 34,
|
||||||
kLoad = 0x1UL << 34,
|
kLoad = 0x1UL << 35,
|
||||||
kStore = 0x1UL << 35,
|
kStore = 0x1UL << 36,
|
||||||
kGetElementPtr = 0x1UL << 36,
|
kGetElementPtr = 0x1UL << 37,
|
||||||
kMemset = 0x1UL << 37,
|
kMemset = 0x1UL << 38,
|
||||||
// kGetSubArray = 0x1UL << 38,
|
|
||||||
// Constant Kind removed as Constants are now Values, not Instructions.
|
|
||||||
// kConstant = 0x1UL << 37, // Conflicts with kMemset if kept as is
|
|
||||||
// phi
|
// phi
|
||||||
kPhi = 0x1UL << 39,
|
kPhi = 0x1UL << 39,
|
||||||
kBitItoF = 0x1UL << 40,
|
kBitItoF = 0x1UL << 40,
|
||||||
kBitFtoI = 0x1UL << 41,
|
kBitFtoI = 0x1UL << 41,
|
||||||
|
kSRA = 0x1UL << 42,
|
||||||
|
kMulh = 0x1UL << 43
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -804,6 +826,12 @@ public:
|
|||||||
return "Memset";
|
return "Memset";
|
||||||
case kPhi:
|
case kPhi:
|
||||||
return "Phi";
|
return "Phi";
|
||||||
|
case kBitItoF:
|
||||||
|
return "BitItoF";
|
||||||
|
case kBitFtoI:
|
||||||
|
return "BitFtoI";
|
||||||
|
case kSRA:
|
||||||
|
return "SRA";
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
@@ -815,11 +843,15 @@ public:
|
|||||||
|
|
||||||
bool isBinary() const {
|
bool isBinary() const {
|
||||||
static constexpr uint64_t BinaryOpMask =
|
static constexpr uint64_t BinaryOpMask =
|
||||||
(kAdd | kSub | kMul | kDiv | kRem | kAnd | kOr) |
|
(kAdd | kSub | kMul | kDiv | kRem | kAnd | kOr | kSRA | kMulh) |
|
||||||
(kICmpEQ | kICmpNE | kICmpLT | kICmpGT | kICmpLE | kICmpGE) |
|
(kICmpEQ | kICmpNE | kICmpLT | kICmpGT | kICmpLE | kICmpGE);
|
||||||
|
return kind & BinaryOpMask;
|
||||||
|
}
|
||||||
|
bool isFPBinary() const {
|
||||||
|
static constexpr uint64_t FPBinaryOpMask =
|
||||||
(kFAdd | kFSub | kFMul | kFDiv) |
|
(kFAdd | kFSub | kFMul | kFDiv) |
|
||||||
(kFCmpEQ | kFCmpNE | kFCmpLT | kFCmpGT | kFCmpLE | kFCmpGE);
|
(kFCmpEQ | kFCmpNE | kFCmpLT | kFCmpGT | kFCmpLE | kFCmpGE);
|
||||||
return kind & BinaryOpMask;
|
return kind & FPBinaryOpMask;
|
||||||
}
|
}
|
||||||
bool isUnary() const {
|
bool isUnary() const {
|
||||||
static constexpr uint64_t UnaryOpMask =
|
static constexpr uint64_t UnaryOpMask =
|
||||||
@@ -832,7 +864,7 @@ public:
|
|||||||
return kind & MemoryOpMask;
|
return kind & MemoryOpMask;
|
||||||
}
|
}
|
||||||
bool isTerminator() const {
|
bool isTerminator() const {
|
||||||
static constexpr uint64_t TerminatorOpMask = kCondBr | kBr | kReturn;
|
static constexpr uint64_t TerminatorOpMask = kCondBr | kBr | kReturn | kUnreachable;
|
||||||
return kind & TerminatorOpMask;
|
return kind & TerminatorOpMask;
|
||||||
}
|
}
|
||||||
bool isCmp() const {
|
bool isCmp() const {
|
||||||
@@ -852,6 +884,7 @@ public:
|
|||||||
}
|
}
|
||||||
bool isUnconditional() const { return kind == kBr; }
|
bool isUnconditional() const { return kind == kBr; }
|
||||||
bool isConditional() const { return kind == kCondBr; }
|
bool isConditional() const { return kind == kCondBr; }
|
||||||
|
bool isCondBr() const { return kind == kCondBr; }
|
||||||
bool isPhi() const { return kind == kPhi; }
|
bool isPhi() const { return kind == kPhi; }
|
||||||
bool isAlloca() const { return kind == kAlloca; }
|
bool isAlloca() const { return kind == kAlloca; }
|
||||||
bool isLoad() const { return kind == kLoad; }
|
bool isLoad() const { return kind == kLoad; }
|
||||||
@@ -860,6 +893,7 @@ public:
|
|||||||
bool isMemset() const { return kind == kMemset; }
|
bool isMemset() const { return kind == kMemset; }
|
||||||
bool isCall() const { return kind == kCall; }
|
bool isCall() const { return kind == kCall; }
|
||||||
bool isReturn() const { return kind == kReturn; }
|
bool isReturn() const { return kind == kReturn; }
|
||||||
|
bool isUnreachable() const { return kind == kUnreachable; }
|
||||||
bool isDefine() const {
|
bool isDefine() const {
|
||||||
static constexpr uint64_t DefineOpMask = kAlloca | kStore | kPhi;
|
static constexpr uint64_t DefineOpMask = kAlloca | kStore | kPhi;
|
||||||
return (kind & DefineOpMask) != 0U;
|
return (kind & DefineOpMask) != 0U;
|
||||||
@@ -894,11 +928,27 @@ class PhiInst : public Instruction {
|
|||||||
public:
|
public:
|
||||||
Value* getValue(unsigned k) const {return getOperand(2 * k);} ///< 获取位置为k的值
|
Value* getValue(unsigned k) const {return getOperand(2 * k);} ///< 获取位置为k的值
|
||||||
BasicBlock* getBlock(unsigned k) const {return dynamic_cast<BasicBlock*>(getOperand(2 * k + 1));}
|
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;} ///< 获取所有的基本块和对应的值
|
auto& getincomings() const {return blk2val;} ///< 获取所有的基本块和对应的值
|
||||||
|
|
||||||
Value* getvalfromBlk(BasicBlock* blk);
|
Value* getvalfromBlk(BasicBlock* blk) const ;
|
||||||
BasicBlock* getBlkfromVal(Value* val);
|
BasicBlock* getBlkfromVal(Value* val) const ;
|
||||||
|
|
||||||
unsigned getNumIncomingValues() const { return vsize; } ///< 获取传入值的数量
|
unsigned getNumIncomingValues() const { return vsize; } ///< 获取传入值的数量
|
||||||
void addIncoming(Value *value, BasicBlock *block) {
|
void addIncoming(Value *value, BasicBlock *block) {
|
||||||
@@ -909,6 +959,10 @@ class PhiInst : public Instruction {
|
|||||||
vsize++;
|
vsize++;
|
||||||
} ///< 添加传入值和对应的基本块
|
} ///< 添加传入值和对应的基本块
|
||||||
|
|
||||||
|
void removeIncoming(BasicBlock *block){
|
||||||
|
delBlk(block);
|
||||||
|
}
|
||||||
|
|
||||||
void delValue(Value* val);
|
void delValue(Value* val);
|
||||||
void delBlk(BasicBlock* blk);
|
void delBlk(BasicBlock* blk);
|
||||||
|
|
||||||
@@ -1059,12 +1113,10 @@ class UncondBrInst : public Instruction {
|
|||||||
friend class Function;
|
friend class Function;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
UncondBrInst(BasicBlock *block, std::vector<Value *> args,
|
UncondBrInst(BasicBlock *block,
|
||||||
BasicBlock *parent = nullptr)
|
BasicBlock *parent = nullptr)
|
||||||
: Instruction(kBr, Type::getVoidType(), parent, "") {
|
: Instruction(kBr, Type::getVoidType(), parent, "") {
|
||||||
// assert(block->getNumArguments() == args.size());
|
|
||||||
addOperand(block);
|
addOperand(block);
|
||||||
addOperands(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -1072,6 +1124,16 @@ public:
|
|||||||
auto getArguments() const {
|
auto getArguments() const {
|
||||||
return make_range(std::next(operand_begin()), operand_end());
|
return make_range(std::next(operand_begin()), operand_end());
|
||||||
}
|
}
|
||||||
|
std::vector<BasicBlock *> getSuccessors() const {
|
||||||
|
std::vector<BasicBlock *> succs;
|
||||||
|
// 假设无条件分支的目标块是它的第一个操作数
|
||||||
|
if (getNumOperands() > 0) {
|
||||||
|
if (auto target_bb = dynamic_cast<BasicBlock *>(getOperand(0))) {
|
||||||
|
succs.push_back(target_bb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return succs;
|
||||||
|
}
|
||||||
|
|
||||||
}; // class UncondBrInst
|
}; // class UncondBrInst
|
||||||
|
|
||||||
@@ -1084,16 +1146,11 @@ class CondBrInst : public Instruction {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
CondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock,
|
CondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock,
|
||||||
const std::vector<Value *> &thenArgs,
|
BasicBlock *parent = nullptr)
|
||||||
const std::vector<Value *> &elseArgs, BasicBlock *parent = nullptr)
|
|
||||||
: Instruction(kCondBr, Type::getVoidType(), parent, "") {
|
: Instruction(kCondBr, Type::getVoidType(), parent, "") {
|
||||||
// assert(thenBlock->getNumArguments() == thenArgs.size() and
|
|
||||||
// elseBlock->getNumArguments() == elseArgs.size());
|
|
||||||
addOperand(condition);
|
addOperand(condition);
|
||||||
addOperand(thenBlock);
|
addOperand(thenBlock);
|
||||||
addOperand(elseBlock);
|
addOperand(elseBlock);
|
||||||
addOperands(thenArgs);
|
|
||||||
addOperands(elseArgs);
|
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
Value* getCondition() const { return getOperand(0); }
|
Value* getCondition() const { return getOperand(0); }
|
||||||
@@ -1103,29 +1160,39 @@ public:
|
|||||||
BasicBlock* getElseBlock() const {
|
BasicBlock* getElseBlock() const {
|
||||||
return dynamic_cast<BasicBlock *>(getOperand(2));
|
return dynamic_cast<BasicBlock *>(getOperand(2));
|
||||||
}
|
}
|
||||||
// auto getThenArguments() const {
|
std::vector<BasicBlock *> getSuccessors() const {
|
||||||
// auto begin = std::next(operand_begin(), 3);
|
std::vector<BasicBlock *> succs;
|
||||||
// // auto end = std::next(begin, getThenBlock()->getNumArguments());
|
// 假设条件分支的真实块是第二个操作数,假块是第三个操作数
|
||||||
// return make_range(begin, end);
|
// 操作数通常是:[0] 条件值, [1] TrueTargetBlock, [2] FalseTargetBlock
|
||||||
// }
|
if (getNumOperands() > 2) {
|
||||||
// auto getElseArguments() const {
|
if (auto true_bb = getThenBlock()) {
|
||||||
// auto begin =
|
succs.push_back(true_bb);
|
||||||
// std::next(operand_begin(), 3 + getThenBlock()->getNumArguments());
|
}
|
||||||
// auto end = operand_end();
|
if (auto false_bb = getElseBlock()) {
|
||||||
// return make_range(begin, end);
|
succs.push_back(false_bb);
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
return succs;
|
||||||
|
}
|
||||||
|
|
||||||
}; // class CondBrInst
|
}; // class CondBrInst
|
||||||
|
|
||||||
|
class UnreachableInst : public Instruction {
|
||||||
|
public:
|
||||||
|
// 构造函数:设置指令类型为 kUnreachable
|
||||||
|
explicit UnreachableInst(const std::string& name, BasicBlock *parent = nullptr)
|
||||||
|
: Instruction(kUnreachable, Type::getVoidType(), parent, "") {}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
//! Allocate memory for stack variables, used for non-global variable declartion
|
//! Allocate memory for stack variables, used for non-global variable declartion
|
||||||
class AllocaInst : public Instruction {
|
class AllocaInst : public Instruction {
|
||||||
friend class IRBuilder;
|
friend class IRBuilder;
|
||||||
friend class Function;
|
friend class Function;
|
||||||
protected:
|
protected:
|
||||||
AllocaInst(Type *type, const std::vector<Value *> &dims = {},
|
AllocaInst(Type *type,
|
||||||
BasicBlock *parent = nullptr, const std::string &name = "")
|
BasicBlock *parent = nullptr, const std::string &name = "")
|
||||||
: Instruction(kAlloca, type, parent, name) {
|
: Instruction(kAlloca, type, parent, name) {
|
||||||
addOperands(dims);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -1133,9 +1200,6 @@ public:
|
|||||||
Type* getAllocatedType() const {
|
Type* getAllocatedType() const {
|
||||||
return getType()->as<PointerType>()->getBaseType();
|
return getType()->as<PointerType>()->getBaseType();
|
||||||
} ///< 获取分配的类型
|
} ///< 获取分配的类型
|
||||||
int getNumDims() const { return getNumOperands(); }
|
|
||||||
auto getDims() const { return getOperands(); }
|
|
||||||
Value* getDim(int index) { return getOperand(index); }
|
|
||||||
|
|
||||||
}; // class AllocaInst
|
}; // class AllocaInst
|
||||||
|
|
||||||
@@ -1182,21 +1246,15 @@ class LoadInst : public Instruction {
|
|||||||
friend class Function;
|
friend class Function;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
LoadInst(Value *pointer, const std::vector<Value *> &indices = {},
|
LoadInst(Value *pointer,
|
||||||
BasicBlock *parent = nullptr, const std::string &name = "")
|
BasicBlock *parent = nullptr, const std::string &name = "")
|
||||||
: Instruction(kLoad, pointer->getType()->as<PointerType>()->getBaseType(),
|
: Instruction(kLoad, pointer->getType()->as<PointerType>()->getBaseType(),
|
||||||
parent, name) {
|
parent, name) {
|
||||||
addOperand(pointer);
|
addOperand(pointer);
|
||||||
addOperands(indices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int getNumIndices() const { return getNumOperands() - 1; }
|
|
||||||
Value* getPointer() const { return getOperand(0); }
|
Value* getPointer() const { return getOperand(0); }
|
||||||
auto getIndices() const {
|
|
||||||
return make_range(std::next(operand_begin()), operand_end());
|
|
||||||
}
|
|
||||||
Value* getIndex(int index) const { return getOperand(index + 1); }
|
|
||||||
|
|
||||||
}; // class LoadInst
|
}; // class LoadInst
|
||||||
|
|
||||||
@@ -1207,22 +1265,15 @@ class StoreInst : public Instruction {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
StoreInst(Value *value, Value *pointer,
|
StoreInst(Value *value, Value *pointer,
|
||||||
const std::vector<Value *> &indices = {},
|
|
||||||
BasicBlock *parent = nullptr, const std::string &name = "")
|
BasicBlock *parent = nullptr, const std::string &name = "")
|
||||||
: Instruction(kStore, Type::getVoidType(), parent, name) {
|
: Instruction(kStore, Type::getVoidType(), parent, name) {
|
||||||
addOperand(value);
|
addOperand(value);
|
||||||
addOperand(pointer);
|
addOperand(pointer);
|
||||||
addOperands(indices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int getNumIndices() const { return getNumOperands() - 2; }
|
|
||||||
Value* getValue() const { return getOperand(0); }
|
Value* getValue() const { return getOperand(0); }
|
||||||
Value* getPointer() const { return getOperand(1); }
|
Value* getPointer() const { return getOperand(1); }
|
||||||
auto getIndices() const {
|
|
||||||
return make_range(std::next(operand_begin(), 2), operand_end());
|
|
||||||
}
|
|
||||||
Value* getIndex(int index) const { return getOperand(index + 2); }
|
|
||||||
|
|
||||||
}; // class StoreInst
|
}; // class StoreInst
|
||||||
|
|
||||||
@@ -1361,20 +1412,18 @@ protected:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
GlobalValue(Module *parent, Type *type, const std::string &name,
|
GlobalValue(Module *parent, Type *type, const std::string &name,
|
||||||
const std::vector<Value *> &dims = {},
|
|
||||||
ValueCounter init = {})
|
ValueCounter init = {})
|
||||||
: Value(type, name), parent(parent) {
|
: Value(type, name), parent(parent) {
|
||||||
assert(type->isPointer());
|
assert(type->isPointer());
|
||||||
// addOperands(dims);
|
|
||||||
// 维度信息已经被记录到Type中,dim只是为了方便初始化
|
// 维度信息已经被记录到Type中,dim只是为了方便初始化
|
||||||
numDims = dims.size();
|
numDims = 0;
|
||||||
if (init.size() == 0) {
|
if (init.size() == 0) {
|
||||||
unsigned num = 1;
|
unsigned num = 1;
|
||||||
for (unsigned i = 0; i < numDims; i++) {
|
auto arrayType = type->as<ArrayType>();
|
||||||
// Assume dims elements are ConstantInteger and cast appropriately
|
while (arrayType) {
|
||||||
auto dim_val = dynamic_cast<ConstantInteger*>(dims[i]);
|
numDims++;
|
||||||
assert(dim_val && "GlobalValue dims must be constant integers");
|
num *= arrayType->getNumElements();
|
||||||
num *= dim_val->getInt();
|
arrayType = arrayType->getElementType()->as<ArrayType>();
|
||||||
}
|
}
|
||||||
if (dynamic_cast<PointerType *>(type)->getBaseType() == Type::getFloatType()) {
|
if (dynamic_cast<PointerType *>(type)->getBaseType() == Type::getFloatType()) {
|
||||||
init.push_back(ConstantFloating::get(0.0F), num); // Use new constant factory
|
init.push_back(ConstantFloating::get(0.0F), num); // Use new constant factory
|
||||||
@@ -1386,9 +1435,6 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// unsigned getNumDims() const { return numDims; } ///< 获取维度数量
|
|
||||||
// Value* getDim(unsigned index) const { return getOperand(index); } ///< 获取位置为index的维度
|
|
||||||
// auto getDims() const { return getOperands(); } ///< 获取维度列表
|
|
||||||
unsigned getNumIndices() const {
|
unsigned getNumIndices() const {
|
||||||
return numDims;
|
return numDims;
|
||||||
} ///< 获取维度数量
|
} ///< 获取维度数量
|
||||||
@@ -1430,13 +1476,19 @@ class ConstantVariable : public Value {
|
|||||||
ValueCounter initValues; ///< 值
|
ValueCounter initValues; ///< 值
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ConstantVariable(Module *parent, Type *type, const std::string &name, const ValueCounter &init,
|
ConstantVariable(Module *parent, Type *type, const std::string &name, const ValueCounter &init)
|
||||||
const std::vector<Value *> &dims = {})
|
|
||||||
: Value(type, name), parent(parent) {
|
: Value(type, name), parent(parent) {
|
||||||
assert(type->isPointer());
|
assert(type->isPointer());
|
||||||
numDims = dims.size();
|
// numDims = dims.size();
|
||||||
|
numDims = 0;
|
||||||
|
if(type->as<PointerType>()->getBaseType()->isArray()) {
|
||||||
|
auto arrayType = type->as<ArrayType>();
|
||||||
|
while (arrayType) {
|
||||||
|
numDims++;
|
||||||
|
arrayType = arrayType->getElementType()->as<ArrayType>();
|
||||||
|
}
|
||||||
|
}
|
||||||
initValues = init;
|
initValues = init;
|
||||||
// addOperands(dims); 同GlobalValue,维度信息已经被记录到Type中,dim只是为了方便初始化
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -1468,9 +1520,6 @@ class ConstantVariable : public Value {
|
|||||||
|
|
||||||
return getByIndex(index);
|
return getByIndex(index);
|
||||||
} ///< 通过多维索引indices获取初始值
|
} ///< 通过多维索引indices获取初始值
|
||||||
// unsigned getNumDims() const { return numDims; } ///< 获取维度数量
|
|
||||||
// Value* getDim(unsigned index) const { return getOperand(index); } ///< 获取位置为index的维度
|
|
||||||
// auto getDims() const { return getOperands(); } ///< 获取维度列表
|
|
||||||
const ValueCounter& getInitValues() const { return initValues; } ///< 获取初始值
|
const ValueCounter& getInitValues() const { return initValues; } ///< 获取初始值
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1529,13 +1578,12 @@ class Module {
|
|||||||
return result.first->second.get();
|
return result.first->second.get();
|
||||||
} ///< 创建外部函数
|
} ///< 创建外部函数
|
||||||
///< 变量创建伴随着符号表的更新
|
///< 变量创建伴随着符号表的更新
|
||||||
GlobalValue* createGlobalValue(const std::string &name, Type *type, const std::vector<Value *> &dims = {},
|
GlobalValue* createGlobalValue(const std::string &name, Type *type, const ValueCounter &init = {}) {
|
||||||
const ValueCounter &init = {}) {
|
|
||||||
bool isFinished = variableTable.isCurNodeNull();
|
bool isFinished = variableTable.isCurNodeNull();
|
||||||
if (isFinished) {
|
if (isFinished) {
|
||||||
variableTable.enterGlobalScope();
|
variableTable.enterGlobalScope();
|
||||||
}
|
}
|
||||||
auto result = variableTable.addVariable(name, new GlobalValue(this, type, name, dims, init));
|
auto result = variableTable.addVariable(name, new GlobalValue(this, type, name, init));
|
||||||
if (isFinished) {
|
if (isFinished) {
|
||||||
variableTable.leaveScope();
|
variableTable.leaveScope();
|
||||||
}
|
}
|
||||||
@@ -1544,9 +1592,8 @@ class Module {
|
|||||||
}
|
}
|
||||||
return dynamic_cast<GlobalValue *>(result);
|
return dynamic_cast<GlobalValue *>(result);
|
||||||
} ///< 创建全局变量
|
} ///< 创建全局变量
|
||||||
ConstantVariable* createConstVar(const std::string &name, Type *type, const ValueCounter &init,
|
ConstantVariable* createConstVar(const std::string &name, Type *type, const ValueCounter &init) {
|
||||||
const std::vector<Value *> &dims = {}) {
|
auto result = variableTable.addVariable(name, new ConstantVariable(this, type, name, init));
|
||||||
auto result = variableTable.addVariable(name, new ConstantVariable(this, type, name, init, dims));
|
|
||||||
if (result == nullptr) {
|
if (result == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,6 +217,12 @@ class IRBuilder {
|
|||||||
BinaryInst * createOrInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
BinaryInst * createOrInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||||
return createBinaryInst(Instruction::kOr, Type::getIntType(), lhs, rhs, name);
|
return createBinaryInst(Instruction::kOr, Type::getIntType(), lhs, rhs, name);
|
||||||
} ///< 创建按位或指令
|
} ///< 创建按位或指令
|
||||||
|
BinaryInst * createSRAInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||||
|
return createBinaryInst(Instruction::kSRA, Type::getIntType(), lhs, rhs, name);
|
||||||
|
} ///< 创建算术右移指令
|
||||||
|
BinaryInst * createMulhInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||||
|
return createBinaryInst(Instruction::kMulh, Type::getIntType(), lhs, rhs, name);
|
||||||
|
} ///< 创建高位乘法指令
|
||||||
CallInst * createCallInst(Function *callee, const std::vector<Value *> &args, const std::string &name = "") {
|
CallInst * createCallInst(Function *callee, const std::vector<Value *> &args, const std::string &name = "") {
|
||||||
std::string newName;
|
std::string newName;
|
||||||
if (name.empty() && callee->getReturnType() != Type::getVoidType()) {
|
if (name.empty() && callee->getReturnType() != Type::getVoidType()) {
|
||||||
@@ -239,31 +245,30 @@ class IRBuilder {
|
|||||||
block->getInstructions().emplace(position, inst);
|
block->getInstructions().emplace(position, inst);
|
||||||
return inst;
|
return inst;
|
||||||
} ///< 创建return指令
|
} ///< 创建return指令
|
||||||
UncondBrInst * createUncondBrInst(BasicBlock *thenBlock, const std::vector<Value *> &args) {
|
UncondBrInst * createUncondBrInst(BasicBlock *thenBlock) {
|
||||||
auto inst = new UncondBrInst(thenBlock, args, block);
|
auto inst = new UncondBrInst(thenBlock, block);
|
||||||
assert(inst);
|
assert(inst);
|
||||||
block->getInstructions().emplace(position, inst);
|
block->getInstructions().emplace(position, inst);
|
||||||
return inst;
|
return inst;
|
||||||
} ///< 创建无条件指令
|
} ///< 创建无条件指令
|
||||||
CondBrInst * createCondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock,
|
CondBrInst * createCondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock) {
|
||||||
const std::vector<Value *> &thenArgs, const std::vector<Value *> &elseArgs) {
|
auto inst = new CondBrInst(condition, thenBlock, elseBlock, block);
|
||||||
auto inst = new CondBrInst(condition, thenBlock, elseBlock, thenArgs, elseArgs, block);
|
|
||||||
assert(inst);
|
assert(inst);
|
||||||
block->getInstructions().emplace(position, inst);
|
block->getInstructions().emplace(position, inst);
|
||||||
return inst;
|
return inst;
|
||||||
} ///< 创建条件跳转指令
|
} ///< 创建条件跳转指令
|
||||||
AllocaInst * createAllocaInst(Type *type, const std::vector<Value *> &dims = {}, const std::string &name = "") {
|
UnreachableInst * createUnreachableInst(const std::string &name = "") {
|
||||||
auto inst = new AllocaInst(type, dims, block, name);
|
auto inst = new UnreachableInst(name, block);
|
||||||
|
assert(inst);
|
||||||
|
block->getInstructions().emplace(position, inst);
|
||||||
|
return inst;
|
||||||
|
} ///< 创建不可达指令
|
||||||
|
AllocaInst * createAllocaInst(Type *type, const std::string &name = "") {
|
||||||
|
auto inst = new AllocaInst(type, block, name);
|
||||||
assert(inst);
|
assert(inst);
|
||||||
block->getInstructions().emplace(position, inst);
|
block->getInstructions().emplace(position, inst);
|
||||||
return inst;
|
return inst;
|
||||||
} ///< 创建分配指令
|
} ///< 创建分配指令
|
||||||
AllocaInst * createAllocaInstWithoutInsert(Type *type, const std::vector<Value *> &dims = {}, BasicBlock *parent = nullptr,
|
|
||||||
const std::string &name = "") {
|
|
||||||
auto inst = new AllocaInst(type, dims, parent, name);
|
|
||||||
assert(inst);
|
|
||||||
return inst;
|
|
||||||
} ///< 创建不插入指令列表的分配指令[仅用于phi指令]
|
|
||||||
LoadInst * createLoadInst(Value *pointer, const std::vector<Value *> &indices = {}, const std::string &name = "") {
|
LoadInst * createLoadInst(Value *pointer, const std::vector<Value *> &indices = {}, const std::string &name = "") {
|
||||||
std::string newName;
|
std::string newName;
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
@@ -275,7 +280,7 @@ class IRBuilder {
|
|||||||
newName = name;
|
newName = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto inst = new LoadInst(pointer, indices, block, newName);
|
auto inst = new LoadInst(pointer, block, newName);
|
||||||
assert(inst);
|
assert(inst);
|
||||||
block->getInstructions().emplace(position, inst);
|
block->getInstructions().emplace(position, inst);
|
||||||
return inst;
|
return inst;
|
||||||
@@ -286,9 +291,8 @@ class IRBuilder {
|
|||||||
block->getInstructions().emplace(position, inst);
|
block->getInstructions().emplace(position, inst);
|
||||||
return inst;
|
return inst;
|
||||||
} ///< 创建memset指令
|
} ///< 创建memset指令
|
||||||
StoreInst * createStoreInst(Value *value, Value *pointer, const std::vector<Value *> &indices = {},
|
StoreInst * createStoreInst(Value *value, Value *pointer, const std::string &name = "") {
|
||||||
const std::string &name = "") {
|
auto inst = new StoreInst(value, pointer, block, name);
|
||||||
auto inst = new StoreInst(value, pointer, indices, block, name);
|
|
||||||
assert(inst);
|
assert(inst);
|
||||||
block->getInstructions().emplace(position, inst);
|
block->getInstructions().emplace(position, inst);
|
||||||
return inst;
|
return inst;
|
||||||
@@ -308,24 +312,6 @@ class IRBuilder {
|
|||||||
block->getInstructions().emplace(block->begin(), inst);
|
block->getInstructions().emplace(block->begin(), inst);
|
||||||
return inst;
|
return inst;
|
||||||
} ///< 创建Phi指令
|
} ///< 创建Phi指令
|
||||||
// GetElementPtrInst* createGetElementPtrInst(Value *basePointer,
|
|
||||||
// const std::vector<Value *> &indices = {},
|
|
||||||
// const std::string &name = "") {
|
|
||||||
// std::string newName;
|
|
||||||
// if (name.empty()) {
|
|
||||||
// std::stringstream ss;
|
|
||||||
// ss << tmpIndex;
|
|
||||||
// newName = ss.str();
|
|
||||||
// tmpIndex++;
|
|
||||||
// } else {
|
|
||||||
// newName = name;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// auto inst = new GetElementPtrInst(basePointer, indices, block, newName);
|
|
||||||
// assert(inst);
|
|
||||||
// block->getInstructions().emplace(position, inst);
|
|
||||||
// return inst;
|
|
||||||
// }
|
|
||||||
/**
|
/**
|
||||||
* @brief 根据 LLVM 设计模式创建 GEP 指令。
|
* @brief 根据 LLVM 设计模式创建 GEP 指令。
|
||||||
* 它会自动推断返回类型,无需手动指定。
|
* 它会自动推断返回类型,无需手动指定。
|
||||||
|
|||||||
@@ -6,30 +6,82 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
// 支配树分析结果类 (保持不变)
|
// 支配树分析结果类
|
||||||
class DominatorTree : public AnalysisResultBase {
|
class DominatorTree : public AnalysisResultBase {
|
||||||
public:
|
public:
|
||||||
DominatorTree(Function* F);
|
DominatorTree(Function* F);
|
||||||
|
// 获取指定基本块的所有支配者
|
||||||
const std::set<BasicBlock*>* getDominators(BasicBlock* BB) const;
|
const std::set<BasicBlock*>* getDominators(BasicBlock* BB) const;
|
||||||
|
// 获取指定基本块的即时支配者 (Immediate Dominator)
|
||||||
BasicBlock* getImmediateDominator(BasicBlock* BB) const;
|
BasicBlock* getImmediateDominator(BasicBlock* BB) const;
|
||||||
|
// 获取指定基本块的支配边界 (Dominance Frontier)
|
||||||
const std::set<BasicBlock*>* getDominanceFrontier(BasicBlock* BB) const;
|
const std::set<BasicBlock*>* getDominanceFrontier(BasicBlock* BB) const;
|
||||||
|
// 获取指定基本块在支配树中的子节点
|
||||||
const std::set<BasicBlock*>* getDominatorTreeChildren(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*, std::set<BasicBlock*>>& getDominatorsMap() const { return Dominators; }
|
||||||
const std::map<BasicBlock*, BasicBlock*>& getIDomsMap() const { return IDoms; }
|
const std::map<BasicBlock*, BasicBlock*>& getIDomsMap() const { return IDoms; }
|
||||||
const std::map<BasicBlock*, std::set<BasicBlock*>>& getDominanceFrontiersMap() const { return DominanceFrontiers; }
|
const std::map<BasicBlock*, std::set<BasicBlock*>>& getDominanceFrontiersMap() const { return DominanceFrontiers; }
|
||||||
|
|
||||||
|
// 计算所有基本块的支配者集合
|
||||||
void computeDominators(Function* F);
|
void computeDominators(Function* F);
|
||||||
|
// 计算所有基本块的即时支配者(内部使用 Lengauer-Tarjan 算法)
|
||||||
void computeIDoms(Function* F);
|
void computeIDoms(Function* F);
|
||||||
|
// 计算所有基本块的支配边界
|
||||||
void computeDominanceFrontiers(Function* F);
|
void computeDominanceFrontiers(Function* F);
|
||||||
|
// 计算支配树的结构(即每个节点的直接子节点)
|
||||||
void computeDominatorTreeChildren(Function* F);
|
void computeDominatorTreeChildren(Function* F);
|
||||||
private:
|
private:
|
||||||
|
// 与该支配树关联的函数
|
||||||
Function* AssociatedFunction;
|
Function* AssociatedFunction;
|
||||||
std::map<BasicBlock*, std::set<BasicBlock*>> Dominators;
|
std::map<BasicBlock*, std::set<BasicBlock*>> Dominators; // 每个基本块的支配者集合
|
||||||
std::map<BasicBlock*, BasicBlock*> IDoms;
|
std::map<BasicBlock*, BasicBlock*> IDoms; // 每个基本块的即时支配者
|
||||||
std::map<BasicBlock*, std::set<BasicBlock*>> DominanceFrontiers;
|
std::map<BasicBlock*, std::set<BasicBlock*>> DominanceFrontiers; // 每个基本块的支配边界
|
||||||
std::map<BasicBlock*, std::set<BasicBlock*>> DominatorTreeChildren;
|
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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
20
src/include/midend/Pass/Optimize/BuildCFG.h
Normal file
20
src/include/midend/Pass/Optimize/BuildCFG.h
Normal 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
|
||||||
24
src/include/midend/Pass/Optimize/LargeArrayToGlobal.h
Normal file
24
src/include/midend/Pass/Optimize/LargeArrayToGlobal.h
Normal 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
|
||||||
@@ -75,11 +75,7 @@ private:
|
|||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
// 对支配树进行深度优先遍历,重命名变量并替换 load/store 指令
|
// 对支配树进行深度优先遍历,重命名变量并替换 load/store 指令
|
||||||
// alloca: 当前正在处理的 AllocaInst
|
void renameVariables(BasicBlock* currentBB);
|
||||||
// currentBB: 当前正在遍历的基本块
|
|
||||||
// dt: 支配树分析结果
|
|
||||||
// valueStack: 存储当前 AllocaInst 在当前路径上可见的 SSA 值栈
|
|
||||||
void renameVariables(AllocaInst* alloca, BasicBlock* currentBB);
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
// 阶段4: 清理
|
// 阶段4: 清理
|
||||||
|
|||||||
@@ -1,196 +1,139 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "IR.h"
|
#include "IR.h"
|
||||||
|
#include "Pass.h"
|
||||||
|
#include "SysYIROptUtils.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <queue>
|
||||||
|
#include <set>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
#include <variant>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
// 稀疏条件常量传播类
|
// 定义三值格 (Three-valued Lattice) 的状态
|
||||||
// Sparse Conditional Constant Propagation
|
enum class LatticeVal {
|
||||||
/*
|
Top, // ⊤ (未知 / 未初始化)
|
||||||
伪代码
|
Constant, // c (常量)
|
||||||
function SCCP_Optimization(Module):
|
Bottom // ⊥ (不确定 / 变化 / 未定义)
|
||||||
for each Function in Module:
|
|
||||||
changed = true
|
|
||||||
while changed:
|
|
||||||
changed = false
|
|
||||||
// 阶段1: 常量传播与折叠
|
|
||||||
changed |= PropagateConstants(Function)
|
|
||||||
// 阶段2: 控制流简化
|
|
||||||
changed |= SimplifyControlFlow(Function)
|
|
||||||
end while
|
|
||||||
end for
|
|
||||||
|
|
||||||
function PropagateConstants(Function):
|
|
||||||
// 初始化
|
|
||||||
executableBlocks = {entryBlock}
|
|
||||||
valueState = map<Value, State> // 值->状态映射
|
|
||||||
instWorkList = Queue()
|
|
||||||
edgeWorkList = Queue()
|
|
||||||
|
|
||||||
// 初始化工作列表
|
|
||||||
for each inst in entryBlock:
|
|
||||||
instWorkList.push(inst)
|
|
||||||
|
|
||||||
// 迭代处理
|
|
||||||
while !instWorkList.empty() || !edgeWorkList.empty():
|
|
||||||
// 处理指令工作列表
|
|
||||||
while !instWorkList.empty():
|
|
||||||
inst = instWorkList.pop()
|
|
||||||
// 如果指令是可执行基本块中的
|
|
||||||
if executableBlocks.contains(inst.parent):
|
|
||||||
ProcessInstruction(inst)
|
|
||||||
|
|
||||||
// 处理边工作列表
|
|
||||||
while !edgeWorkList.empty():
|
|
||||||
edge = edgeWorkList.pop()
|
|
||||||
ProcessEdge(edge)
|
|
||||||
|
|
||||||
// 应用常量替换
|
|
||||||
for each inst in Function:
|
|
||||||
if valueState[inst] == CONSTANT:
|
|
||||||
ReplaceWithConstant(inst, valueState[inst].constant)
|
|
||||||
changed = true
|
|
||||||
|
|
||||||
return changed
|
|
||||||
|
|
||||||
function ProcessInstruction(Instruction inst):
|
|
||||||
switch inst.type:
|
|
||||||
//二元操作
|
|
||||||
case BINARY_OP:
|
|
||||||
lhs = GetValueState(inst.operands[0])
|
|
||||||
rhs = GetValueState(inst.operands[1])
|
|
||||||
if lhs == CONSTANT && rhs == CONSTANT:
|
|
||||||
newState = ComputeConstant(inst.op, lhs.value, rhs.value)
|
|
||||||
UpdateState(inst, newState)
|
|
||||||
else if lhs == BOTTOM || rhs == BOTTOM:
|
|
||||||
UpdateState(inst, BOTTOM)
|
|
||||||
//phi
|
|
||||||
case PHI:
|
|
||||||
mergedState = ⊤
|
|
||||||
for each incoming in inst.incomings:
|
|
||||||
// 检查每个输入的状态
|
|
||||||
if executableBlocks.contains(incoming.block):
|
|
||||||
incomingState = GetValueState(incoming.value)
|
|
||||||
mergedState = Meet(mergedState, incomingState)
|
|
||||||
UpdateState(inst, mergedState)
|
|
||||||
// 条件分支
|
|
||||||
case COND_BRANCH:
|
|
||||||
cond = GetValueState(inst.condition)
|
|
||||||
if cond == CONSTANT:
|
|
||||||
// 判断条件分支
|
|
||||||
if cond.value == true:
|
|
||||||
AddEdgeToWorkList(inst.parent, inst.trueTarget)
|
|
||||||
else:
|
|
||||||
AddEdgeToWorkList(inst.parent, inst.falseTarget)
|
|
||||||
else if cond == BOTTOM:
|
|
||||||
AddEdgeToWorkList(inst.parent, inst.trueTarget)
|
|
||||||
AddEdgeToWorkList(inst.parent, inst.falseTarget)
|
|
||||||
|
|
||||||
case UNCOND_BRANCH:
|
|
||||||
AddEdgeToWorkList(inst.parent, inst.target)
|
|
||||||
|
|
||||||
// 其他指令处理...
|
|
||||||
|
|
||||||
function ProcessEdge(Edge edge):
|
|
||||||
fromBB, toBB = edge
|
|
||||||
if !executableBlocks.contains(toBB):
|
|
||||||
executableBlocks.add(toBB)
|
|
||||||
for each inst in toBB:
|
|
||||||
if inst is PHI:
|
|
||||||
instWorkList.push(inst)
|
|
||||||
else:
|
|
||||||
instWorkList.push(inst) // 非PHI指令
|
|
||||||
|
|
||||||
// 更新PHI节点的输入
|
|
||||||
for each phi in toBB.phis:
|
|
||||||
instWorkList.push(phi)
|
|
||||||
|
|
||||||
function SimplifyControlFlow(Function):
|
|
||||||
changed = false
|
|
||||||
// 标记可达基本块
|
|
||||||
ReachableBBs = FindReachableBlocks(Function.entry)
|
|
||||||
|
|
||||||
// 删除不可达块
|
|
||||||
for each bb in Function.blocks:
|
|
||||||
if !ReachableBBs.contains(bb):
|
|
||||||
RemoveDeadBlock(bb)
|
|
||||||
changed = true
|
|
||||||
|
|
||||||
// 简化条件分支
|
|
||||||
for each bb in Function.blocks:
|
|
||||||
terminator = bb.terminator
|
|
||||||
if terminator is COND_BRANCH:
|
|
||||||
cond = GetValueState(terminator.condition)
|
|
||||||
if cond == CONSTANT:
|
|
||||||
SimplifyBranch(terminator, cond.value)
|
|
||||||
changed = true
|
|
||||||
|
|
||||||
return changed
|
|
||||||
|
|
||||||
function RemoveDeadBlock(BasicBlock bb):
|
|
||||||
// 1. 更新前驱块的分支指令
|
|
||||||
for each pred in bb.predecessors:
|
|
||||||
UpdateTerminator(pred, bb)
|
|
||||||
|
|
||||||
// 2. 更新后继块的PHI节点
|
|
||||||
for each succ in bb.successors:
|
|
||||||
RemovePhiIncoming(succ, bb)
|
|
||||||
|
|
||||||
// 3. 删除块内所有指令
|
|
||||||
for each inst in bb.instructions:
|
|
||||||
inst.remove()
|
|
||||||
|
|
||||||
// 4. 从函数中移除基本块
|
|
||||||
Function.removeBlock(bb)
|
|
||||||
|
|
||||||
function Meet(State a, State b):
|
|
||||||
if a == ⊤: return b
|
|
||||||
if b == ⊤: return a
|
|
||||||
if a == ⊥ || b == ⊥: return ⊥
|
|
||||||
if a.value == b.value: return a
|
|
||||||
return ⊥
|
|
||||||
|
|
||||||
function UpdateState(Value v, State newState):
|
|
||||||
oldState = valueState.get(v, ⊤)
|
|
||||||
if newState != oldState:
|
|
||||||
valueState[v] = newState
|
|
||||||
for each user in v.users:
|
|
||||||
if user is Instruction:
|
|
||||||
instWorkList.push(user)
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum class LatticeValue {
|
|
||||||
Top, // ⊤ (Unknown)
|
|
||||||
Constant, // c (Constant)
|
|
||||||
Bottom // ⊥ (Undefined / Varying)
|
|
||||||
};
|
};
|
||||||
// LatticeValue: 用于表示值的状态,Top表示未知,Constant表示常量,Bottom表示未定义或变化的值。
|
|
||||||
// 这里的LatticeValue用于跟踪每个SSA值(变量、指令结果)的状态,
|
|
||||||
// 以便在SCCP过程中进行常量传播和控制流简化。
|
|
||||||
|
|
||||||
//TODO: 下列数据结构考虑集成到类中,避免重命名问题
|
// 新增枚举来区分常量的实际类型
|
||||||
static std::set<Instruction *> Worklist;
|
enum class ValueType {
|
||||||
static std::unordered_set<BasicBlock*> Executable_Blocks;
|
Integer,
|
||||||
static std::queue<std::pair<BasicBlock *, BasicBlock *> > Executable_Edges;
|
Float,
|
||||||
static std::map<Value*, LatticeValue> valueState;
|
Unknown // 用于 Top 和 Bottom 状态
|
||||||
|
};
|
||||||
|
|
||||||
class SCCP {
|
// 用于表示 SSA 值的具体状态(包含格值和常量值)
|
||||||
|
struct SSAPValue {
|
||||||
|
LatticeVal state;
|
||||||
|
std::variant<int, float> constantVal; // 使用 std::variant 存储 int 或 float
|
||||||
|
ValueType constant_type; // 记录常量是整数还是浮点数
|
||||||
|
|
||||||
|
// 默认构造函数,初始化为 Top
|
||||||
|
SSAPValue() : state(LatticeVal::Top), constantVal(0), constant_type(ValueType::Unknown) {}
|
||||||
|
// 构造函数,用于创建 Bottom 状态
|
||||||
|
SSAPValue(LatticeVal s) : state(s), constantVal(0), constant_type(ValueType::Unknown) {
|
||||||
|
assert((s == LatticeVal::Top || s == LatticeVal::Bottom) && "SSAPValue(LatticeVal) only for Top/Bottom");
|
||||||
|
}
|
||||||
|
// 构造函数,用于创建 int Constant 状态
|
||||||
|
SSAPValue(int c) : state(LatticeVal::Constant), constantVal(c), constant_type(ValueType::Integer) {}
|
||||||
|
// 构造函数,用于创建 float Constant 状态
|
||||||
|
SSAPValue(float c) : state(LatticeVal::Constant), constantVal(c), constant_type(ValueType::Float) {}
|
||||||
|
|
||||||
|
// 比较操作符,用于判断状态是否改变
|
||||||
|
bool operator==(const SSAPValue &other) const {
|
||||||
|
if (state != other.state)
|
||||||
|
return false;
|
||||||
|
if (state == LatticeVal::Constant) {
|
||||||
|
if (constant_type != other.constant_type) return false; // 类型必须匹配
|
||||||
|
return constantVal == other.constantVal; // std::variant 会比较内部值
|
||||||
|
}
|
||||||
|
return true; // Top == Top, Bottom == Bottom
|
||||||
|
}
|
||||||
|
bool operator!=(const SSAPValue &other) const { return !(*this == other); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// SCCP 上下文类,持有每个函数运行时的状态
|
||||||
|
class SCCPContext {
|
||||||
private:
|
private:
|
||||||
Module *pModule;
|
IRBuilder *builder; // IR 构建器,用于插入指令和创建常量
|
||||||
|
|
||||||
|
// 工作列表
|
||||||
|
// 存储需要重新评估的指令
|
||||||
|
std::queue<Instruction *> instWorkList;
|
||||||
|
// 存储需要重新评估的控制流边 (pair: from_block, to_block)
|
||||||
|
std::queue<std::pair<BasicBlock *, BasicBlock *>> edgeWorkList;
|
||||||
|
|
||||||
|
// 格值映射:SSA Value 到其当前状态
|
||||||
|
std::map<Value *, SSAPValue> valueState;
|
||||||
|
// 可执行基本块集合
|
||||||
|
std::unordered_set<BasicBlock *> executableBlocks;
|
||||||
|
// 追踪已访问的CFG边,防止重复添加,使用 SysYIROptUtils::PairHash
|
||||||
|
std::unordered_set<std::pair<BasicBlock*, BasicBlock*>, SysYIROptUtils::PairHash> visitedCFGEdges;
|
||||||
|
|
||||||
|
// 辅助函数:格操作 Meet
|
||||||
|
SSAPValue Meet(const SSAPValue &a, const SSAPValue &b);
|
||||||
|
// 辅助函数:获取值的当前状态,如果不存在则默认为 Top
|
||||||
|
SSAPValue GetValueState(Value *v);
|
||||||
|
// 辅助函数:更新值的状态,如果状态改变,将所有用户加入指令工作列表
|
||||||
|
void UpdateState(Value *v, SSAPValue newState);
|
||||||
|
// 辅助函数:将边加入边工作列表,并更新可执行块
|
||||||
|
void AddEdgeToWorkList(BasicBlock *fromBB, BasicBlock *toBB);
|
||||||
|
// 辅助函数:标记一个块为可执行
|
||||||
|
void MarkBlockExecutable(BasicBlock* block);
|
||||||
|
|
||||||
|
// 辅助函数:对二元操作进行常量折叠
|
||||||
|
SSAPValue ComputeConstant(BinaryInst *binaryinst, SSAPValue lhsVal, SSAPValue rhsVal);
|
||||||
|
// 辅助函数:对一元操作进行常量折叠
|
||||||
|
SSAPValue ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVal);
|
||||||
|
|
||||||
|
// 主要优化阶段
|
||||||
|
// 阶段1: 常量传播与折叠
|
||||||
|
bool PropagateConstants(Function *func);
|
||||||
|
// 阶段2: 控制流简化
|
||||||
|
bool SimplifyControlFlow(Function *func);
|
||||||
|
|
||||||
|
// 辅助函数:处理单条指令
|
||||||
|
void ProcessInstruction(Instruction *inst);
|
||||||
|
// 辅助函数:处理单条控制流边
|
||||||
|
void ProcessEdge(const std::pair<BasicBlock *, BasicBlock *> &edge);
|
||||||
|
|
||||||
|
// 控制流简化辅助函数
|
||||||
|
// 查找所有可达的基本块 (基于常量条件)
|
||||||
|
std::unordered_set<BasicBlock *> FindReachableBlocks(Function *func);
|
||||||
|
// 移除死块
|
||||||
|
void RemoveDeadBlock(BasicBlock *bb, Function *func);
|
||||||
|
// 简化分支(将条件分支替换为无条件分支)
|
||||||
|
void SimplifyBranch(CondBrInst*brInst, bool condVal); // 保持 BranchInst
|
||||||
|
// 更新前驱块的终结指令(当一个后继块被移除时)
|
||||||
|
void UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc);
|
||||||
|
// 移除 Phi 节点的入边(当其前驱块被移除时)
|
||||||
|
void RemovePhiIncoming(BasicBlock *phiParentBB, BasicBlock *removedPred);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SCCP(Module *pMoudle) : pModule(pMoudle) {}
|
SCCPContext(IRBuilder *builder) : builder(builder) {}
|
||||||
|
|
||||||
void run();
|
// 运行 SCCP 优化
|
||||||
bool PropagateConstants(Function *function);
|
void run(Function *func, AnalysisManager &AM);
|
||||||
bool SimplifyControlFlow(Function *function);
|
|
||||||
void ProcessInstruction(Instruction *inst);
|
|
||||||
void ProcessEdge(const std::pair<BasicBlock *, BasicBlock *> &edge);
|
|
||||||
void RemoveDeadBlock(BasicBlock *bb);
|
|
||||||
void UpdateState(Value *v, LatticeValue newState);
|
|
||||||
LatticeValue Meet(LatticeValue a, LatticeValue b);
|
|
||||||
LatticeValue GetValueState(Value *v);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sysy
|
// SCCP 优化遍类,继承自 OptimizationPass
|
||||||
|
class SCCP : public OptimizationPass {
|
||||||
|
private:
|
||||||
|
IRBuilder *builder; // IR 构建器,作为 Pass 的成员,传入 Context
|
||||||
|
|
||||||
|
public:
|
||||||
|
SCCP(IRBuilder *builder) : OptimizationPass("SCCP", Granularity::Function), builder(builder) {}
|
||||||
|
static void *ID;
|
||||||
|
bool runOnFunction(Function *F, AnalysisManager &AM) override;
|
||||||
|
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
|
||||||
|
void *getPassID() const override { return &ID; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sysy
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "IR.h"
|
#include "IR.h"
|
||||||
|
|
||||||
|
extern int DEBUG;
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
// 优化工具类,包含一些通用的优化方法
|
// 优化工具类,包含一些通用的优化方法
|
||||||
@@ -10,13 +11,88 @@ namespace sysy {
|
|||||||
class SysYIROptUtils{
|
class SysYIROptUtils{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// 仅仅删除use关系
|
struct PairHash {
|
||||||
static void usedelete(Instruction *instr) {
|
template <class T1, class T2>
|
||||||
for (auto &use : instr->getOperands()) {
|
std::size_t operator () (const std::pair<T1, T2>& p) const {
|
||||||
Value* val = use->getValue();
|
auto h1 = std::hash<T1>{}(p.first);
|
||||||
val->removeUse(use);
|
auto h2 = std::hash<T2>{}(p.second);
|
||||||
|
|
||||||
|
// 简单的组合哈希值,可以更复杂以减少冲突
|
||||||
|
// 使用 boost::hash_combine 的简化版本
|
||||||
|
return h1 ^ (h2 << 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void RemoveUserOperandUses(User *user) {
|
||||||
|
if (!user) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 遍历 User 的 operands 列表。
|
||||||
|
// 由于 operands 是 protected 成员,我们需要一个临时方法来访问它,
|
||||||
|
// 或者在 User 类中添加一个 friend 声明。
|
||||||
|
// 假设 User 内部有一个像 getOperands() 这样的公共方法返回 operands 的引用,
|
||||||
|
// 或者将 SysYIROptUtils 声明为 User 的 friend。
|
||||||
|
// 为了示例,我将假设可以直接访问 user->operands 或通过一个getter。
|
||||||
|
// 如果无法直接访问,请在 IR.h 的 User 类中添加:
|
||||||
|
// public: const std::vector<std::shared_ptr<Use>>& getOperands() const { return operands; }
|
||||||
|
|
||||||
|
// 迭代 copies of shared_ptr to avoid issues if removeUse modifies the list
|
||||||
|
// (though remove should handle it, iterating a copy is safer or reverse iteration).
|
||||||
|
// Since we'll clear the vector at the end, iterating forward is fine.
|
||||||
|
for (const auto& use_ptr : user->getOperands()) { // 假设 getOperands() 可用
|
||||||
|
if (use_ptr) {
|
||||||
|
Value *val = use_ptr->getValue(); // 获取 Use 指向的 Value (如 AllocaInst)
|
||||||
|
if (val) {
|
||||||
|
val->removeUse(use_ptr); // 通知 Value 从其 uses 列表中移除此 Use 关系
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 清空 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.");
|
||||||
|
BasicBlock *parentBlock = inst->getParent();
|
||||||
|
assert(parentBlock && "Instruction must have a parent BasicBlock to be deleted.");
|
||||||
|
|
||||||
|
// 步骤1: 处理所有使用者,将他们从使用 inst 变为使用 UndefinedValue
|
||||||
|
// 这将清理 inst 作为 Value 时的 uses 列表
|
||||||
|
if (!inst->getUses().empty()) {
|
||||||
|
inst->replaceAllUsesWith(UndefinedValue::get(inst->getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 步骤2: 清理 inst 作为 User 时的操作数关系
|
||||||
|
// 通知 inst 所使用的所有 Value (如 AllocaInst),移除对应的 Use 关系。
|
||||||
|
// 这里的 inst 实际上是一个 User*,所以可以安全地向下转型。
|
||||||
|
RemoveUserOperandUses(static_cast<User*>(inst));
|
||||||
|
|
||||||
|
// 步骤3: 物理删除指令
|
||||||
|
// 这会导致 Instruction 对象的 unique_ptr 销毁,从而调用其析构函数链。
|
||||||
|
parentBlock->removeInst(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BasicBlock::iterator usedelete(BasicBlock::iterator inst_it) {
|
||||||
|
Instruction *inst_to_delete = inst_it->get();
|
||||||
|
BasicBlock *parentBlock = inst_to_delete->getParent();
|
||||||
|
assert(parentBlock && "Instruction must have a parent BasicBlock for iterator deletion.");
|
||||||
|
|
||||||
|
// 步骤1: 处理所有使用者
|
||||||
|
if (!inst_to_delete->getUses().empty()) {
|
||||||
|
inst_to_delete->replaceAllUsesWith(UndefinedValue::get(inst_to_delete->getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 步骤2: 清理操作数关系
|
||||||
|
RemoveUserOperandUses(static_cast<User*>(inst_to_delete));
|
||||||
|
|
||||||
|
// 步骤3: 物理删除指令并返回下一个迭代器
|
||||||
|
return parentBlock->removeInst(inst_it);
|
||||||
|
}
|
||||||
|
|
||||||
// 判断是否是全局变量
|
// 判断是否是全局变量
|
||||||
static bool isGlobal(Value *val) {
|
static bool isGlobal(Value *val) {
|
||||||
@@ -26,7 +102,17 @@ public:
|
|||||||
// 判断是否是数组
|
// 判断是否是数组
|
||||||
static bool isArr(Value *val) {
|
static bool isArr(Value *val) {
|
||||||
auto aval = dynamic_cast<AllocaInst *>(val);
|
auto aval = dynamic_cast<AllocaInst *>(val);
|
||||||
return aval != nullptr && aval->getNumDims() != 0;
|
// 如果是 AllocaInst 且通过Type::isArray()判断为数组类型
|
||||||
|
return aval && aval->getType()->as<PointerType>()->getBaseType()->isArray();
|
||||||
|
}
|
||||||
|
// 判断是否是指向数组的指针
|
||||||
|
static bool isArrPointer(Value *val) {
|
||||||
|
auto aval = dynamic_cast<AllocaInst *>(val);
|
||||||
|
// 如果是 AllocaInst 且通过Type::isPointer()判断为指针;
|
||||||
|
auto baseType = aval->getType()->as<PointerType>()->getBaseType();
|
||||||
|
// 在sysy中,函数的数组参数会退化成指针
|
||||||
|
// 所以当AllocaInst的basetype是PointerType时(一维数组)或者是指向ArrayType的PointerType(多位数组)时,返回true
|
||||||
|
return aval && (baseType->isPointer() || baseType->as<PointerType>()->getBaseType()->isArray());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ private:
|
|||||||
IRBuilder *pBuilder;
|
IRBuilder *pBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PassManager() = default;
|
PassManager() = delete;
|
||||||
~PassManager() = default;
|
~PassManager() = default;
|
||||||
|
|
||||||
PassManager(Module *module, IRBuilder *builder) : pmodule(module) ,pBuilder(builder), analysisManager(module) {}
|
PassManager(Module *module, IRBuilder *builder) : pmodule(module) ,pBuilder(builder), analysisManager(module) {}
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ add_library(midend_lib STATIC
|
|||||||
Pass/Optimize/Mem2Reg.cpp
|
Pass/Optimize/Mem2Reg.cpp
|
||||||
Pass/Optimize/Reg2Mem.cpp
|
Pass/Optimize/Reg2Mem.cpp
|
||||||
Pass/Optimize/SysYIRCFGOpt.cpp
|
Pass/Optimize/SysYIRCFGOpt.cpp
|
||||||
|
Pass/Optimize/SCCP.cpp
|
||||||
|
Pass/Optimize/BuildCFG.cpp
|
||||||
|
Pass/Optimize/LargeArrayToGlobal.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# 包含中端模块所需的头文件路径
|
# 包含中端模块所需的头文件路径
|
||||||
|
|||||||
@@ -227,12 +227,13 @@ Function * Function::clone(const std::string &suffix) const {
|
|||||||
auto oldAllocInst = dynamic_cast<AllocaInst *>(value);
|
auto oldAllocInst = dynamic_cast<AllocaInst *>(value);
|
||||||
if (oldAllocInst != nullptr) {
|
if (oldAllocInst != nullptr) {
|
||||||
std::vector<Value *> dims;
|
std::vector<Value *> dims;
|
||||||
for (const auto &dim : oldAllocInst->getDims()) {
|
// TODO: 这里的dims用type推断
|
||||||
dims.emplace_back(dim->getValue());
|
// for (const auto &dim : oldAllocInst->getDims()) {
|
||||||
}
|
// dims.emplace_back(dim->getValue());
|
||||||
|
// }
|
||||||
ss << oldAllocInst->getName() << suffix;
|
ss << oldAllocInst->getName() << suffix;
|
||||||
auto newAllocInst =
|
auto newAllocInst =
|
||||||
new AllocaInst(oldAllocInst->getType(), dims, oldNewBlockMap.at(oldAllocInst->getParent()), ss.str());
|
new AllocaInst(oldAllocInst->getType(), oldNewBlockMap.at(oldAllocInst->getParent()), ss.str());
|
||||||
ss.str("");
|
ss.str("");
|
||||||
oldNewValueMap.emplace(oldAllocInst, newAllocInst);
|
oldNewValueMap.emplace(oldAllocInst, newAllocInst);
|
||||||
if (isAddedToCreate.find(oldAllocInst) == isAddedToCreate.end()) {
|
if (isAddedToCreate.find(oldAllocInst) == isAddedToCreate.end()) {
|
||||||
@@ -252,12 +253,13 @@ Function * Function::clone(const std::string &suffix) const {
|
|||||||
if (oldNewValueMap.find(inst.get()) == oldNewValueMap.end()) {
|
if (oldNewValueMap.find(inst.get()) == oldNewValueMap.end()) {
|
||||||
auto oldAllocInst = dynamic_cast<AllocaInst *>(inst.get());
|
auto oldAllocInst = dynamic_cast<AllocaInst *>(inst.get());
|
||||||
std::vector<Value *> dims;
|
std::vector<Value *> dims;
|
||||||
for (const auto &dim : oldAllocInst->getDims()) {
|
// TODO: 这里的dims用type推断
|
||||||
dims.emplace_back(dim->getValue());
|
// for (const auto &dim : oldAllocInst->getDims()) {
|
||||||
}
|
// dims.emplace_back(dim->getValue());
|
||||||
|
// }
|
||||||
ss << oldAllocInst->getName() << suffix;
|
ss << oldAllocInst->getName() << suffix;
|
||||||
auto newAllocInst =
|
auto newAllocInst =
|
||||||
new AllocaInst(oldAllocInst->getType(), dims, oldNewBlockMap.at(oldAllocInst->getParent()), ss.str());
|
new AllocaInst(oldAllocInst->getType(), oldNewBlockMap.at(oldAllocInst->getParent()), ss.str());
|
||||||
ss.str("");
|
ss.str("");
|
||||||
oldNewValueMap.emplace(oldAllocInst, newAllocInst);
|
oldNewValueMap.emplace(oldAllocInst, newAllocInst);
|
||||||
if (isAddedToCreate.find(oldAllocInst) == isAddedToCreate.end()) {
|
if (isAddedToCreate.find(oldAllocInst) == isAddedToCreate.end()) {
|
||||||
@@ -422,7 +424,7 @@ Function * Function::clone(const std::string &suffix) const {
|
|||||||
Value *newCond;
|
Value *newCond;
|
||||||
newCond = oldNewValueMap.at(oldCond);
|
newCond = oldNewValueMap.at(oldCond);
|
||||||
auto newCondBrInst = new CondBrInst(newCond, oldNewBlockMap.at(oldCondBrInst->getThenBlock()),
|
auto newCondBrInst = new CondBrInst(newCond, oldNewBlockMap.at(oldCondBrInst->getThenBlock()),
|
||||||
oldNewBlockMap.at(oldCondBrInst->getElseBlock()), {}, {},
|
oldNewBlockMap.at(oldCondBrInst->getElseBlock()),
|
||||||
oldNewBlockMap.at(oldCondBrInst->getParent()));
|
oldNewBlockMap.at(oldCondBrInst->getParent()));
|
||||||
oldNewValueMap.emplace(oldCondBrInst, newCondBrInst);
|
oldNewValueMap.emplace(oldCondBrInst, newCondBrInst);
|
||||||
break;
|
break;
|
||||||
@@ -431,7 +433,7 @@ Function * Function::clone(const std::string &suffix) const {
|
|||||||
case Instruction::kBr: {
|
case Instruction::kBr: {
|
||||||
auto oldBrInst = dynamic_cast<UncondBrInst *>(inst);
|
auto oldBrInst = dynamic_cast<UncondBrInst *>(inst);
|
||||||
auto newBrInst =
|
auto newBrInst =
|
||||||
new UncondBrInst(oldNewBlockMap.at(oldBrInst->getBlock()), {}, oldNewBlockMap.at(oldBrInst->getParent()));
|
new UncondBrInst(oldNewBlockMap.at(oldBrInst->getBlock()), oldNewBlockMap.at(oldBrInst->getParent()));
|
||||||
oldNewValueMap.emplace(oldBrInst, newBrInst);
|
oldNewValueMap.emplace(oldBrInst, newBrInst);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -460,11 +462,12 @@ Function * Function::clone(const std::string &suffix) const {
|
|||||||
newPointer = oldNewValueMap.at(oldPointer);
|
newPointer = oldNewValueMap.at(oldPointer);
|
||||||
|
|
||||||
std::vector<Value *> newIndices;
|
std::vector<Value *> newIndices;
|
||||||
for (const auto &index : oldLoadInst->getIndices()) {
|
// for (const auto &index : oldLoadInst->getIndices()) {
|
||||||
newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
|
// newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
|
||||||
}
|
// }
|
||||||
ss << oldLoadInst->getName() << suffix;
|
ss << oldLoadInst->getName() << suffix;
|
||||||
auto newLoadInst = new LoadInst(newPointer, newIndices, oldNewBlockMap.at(oldLoadInst->getParent()), ss.str());
|
// TODO : 这里的newLoadInst的类型需要根据oldLoadInst的类型来推断
|
||||||
|
auto newLoadInst = new LoadInst(newPointer, oldNewBlockMap.at(oldLoadInst->getParent()), ss.str());
|
||||||
ss.str("");
|
ss.str("");
|
||||||
oldNewValueMap.emplace(oldLoadInst, newLoadInst);
|
oldNewValueMap.emplace(oldLoadInst, newLoadInst);
|
||||||
break;
|
break;
|
||||||
@@ -479,10 +482,11 @@ Function * Function::clone(const std::string &suffix) const {
|
|||||||
std::vector<Value *> newIndices;
|
std::vector<Value *> newIndices;
|
||||||
newPointer = oldNewValueMap.at(oldPointer);
|
newPointer = oldNewValueMap.at(oldPointer);
|
||||||
newValue = oldNewValueMap.at(oldValue);
|
newValue = oldNewValueMap.at(oldValue);
|
||||||
for (const auto &index : oldStoreInst->getIndices()) {
|
// TODO: 这里的newIndices需要根据oldStoreInst的类型来推断
|
||||||
newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
|
// for (const auto &index : oldStoreInst->getIndices()) {
|
||||||
}
|
// newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
|
||||||
auto newStoreInst = new StoreInst(newValue, newPointer, newIndices,
|
// }
|
||||||
|
auto newStoreInst = new StoreInst(newValue, newPointer,
|
||||||
oldNewBlockMap.at(oldStoreInst->getParent()), oldStoreInst->getName());
|
oldNewBlockMap.at(oldStoreInst->getParent()), oldStoreInst->getName());
|
||||||
oldNewValueMap.emplace(oldStoreInst, newStoreInst);
|
oldNewValueMap.emplace(oldStoreInst, newStoreInst);
|
||||||
break;
|
break;
|
||||||
@@ -565,15 +569,15 @@ void User::replaceOperand(unsigned index, Value *value) {
|
|||||||
* phi相关函数
|
* phi相关函数
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Value* PhiInst::getvalfromBlk(BasicBlock* blk){
|
Value* PhiInst::getvalfromBlk(BasicBlock* blk) const {
|
||||||
refreshB2VMap();
|
// refreshB2VMap();
|
||||||
if( blk2val.find(blk) != blk2val.end()) {
|
if( blk2val.find(blk) != blk2val.end()) {
|
||||||
return blk2val.at(blk);
|
return blk2val.at(blk);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicBlock* PhiInst::getBlkfromVal(Value* val){
|
BasicBlock* PhiInst::getBlkfromVal(Value* val) const {
|
||||||
// 返回第一个值对应的基本块
|
// 返回第一个值对应的基本块
|
||||||
for(unsigned i = 0; i < vsize; i++) {
|
for(unsigned i = 0; i < vsize; i++) {
|
||||||
if(getValue(i) == val) {
|
if(getValue(i) == val) {
|
||||||
@@ -587,6 +591,9 @@ void PhiInst::delValue(Value* val){
|
|||||||
//根据value删除对应的基本块和值
|
//根据value删除对应的基本块和值
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
BasicBlock* blk = getBlkfromVal(val);
|
BasicBlock* blk = getBlkfromVal(val);
|
||||||
|
if(blk == nullptr) {
|
||||||
|
return; // 如果val没有对应的基本块,直接返回
|
||||||
|
}
|
||||||
for(i = 0; i < vsize; i++) {
|
for(i = 0; i < vsize; i++) {
|
||||||
if(getValue(i) == val) {
|
if(getValue(i) == val) {
|
||||||
break;
|
break;
|
||||||
@@ -602,6 +609,9 @@ void PhiInst::delBlk(BasicBlock* blk){
|
|||||||
//根据Blk删除对应的基本块和值
|
//根据Blk删除对应的基本块和值
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
Value* val = getvalfromBlk(blk);
|
Value* val = getvalfromBlk(blk);
|
||||||
|
if(val == nullptr) {
|
||||||
|
return; // 如果blk没有对应的值,直接返回
|
||||||
|
}
|
||||||
for(i = 0; i < vsize; i++) {
|
for(i = 0; i < vsize; i++) {
|
||||||
if(getBlock(i) == blk) {
|
if(getBlock(i) == blk) {
|
||||||
break;
|
break;
|
||||||
@@ -614,17 +624,22 @@ void PhiInst::delBlk(BasicBlock* blk){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PhiInst::replaceBlk(BasicBlock* newBlk, unsigned k){
|
void PhiInst::replaceBlk(BasicBlock* newBlk, unsigned k){
|
||||||
refreshB2VMap();
|
// refreshB2VMap();
|
||||||
Value* val = blk2val.at(getBlock(k));
|
BasicBlock* oldBlk = getBlock(k);
|
||||||
|
Value* val = blk2val.at(oldBlk);
|
||||||
|
if(newBlk == oldBlk || oldBlk == nullptr) {
|
||||||
|
return; // 如果新旧基本块相同,直接返回
|
||||||
|
}
|
||||||
|
// Value* val = blk2val.at(getBlock(k));
|
||||||
// 替换基本块
|
// 替换基本块
|
||||||
setOperand(2 * k + 1, newBlk);
|
setOperand(2 * k + 1, newBlk);
|
||||||
// 替换blk2val映射
|
// 替换blk2val映射
|
||||||
blk2val.erase(getBlock(k));
|
blk2val.erase(oldBlk);
|
||||||
blk2val.emplace(newBlk, val);
|
blk2val.emplace(newBlk, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhiInst::replaceold2new(BasicBlock* oldBlk, BasicBlock* newBlk){
|
void PhiInst::replaceold2new(BasicBlock* oldBlk, BasicBlock* newBlk){
|
||||||
refreshB2VMap();
|
// refreshB2VMap();
|
||||||
Value* val = blk2val.at(oldBlk);
|
Value* val = blk2val.at(oldBlk);
|
||||||
// 替换基本块
|
// 替换基本块
|
||||||
delBlk(oldBlk);
|
delBlk(oldBlk);
|
||||||
|
|||||||
@@ -1,19 +1,30 @@
|
|||||||
#include "Dom.h"
|
#include "Dom.h"
|
||||||
#include <limits> // for std::numeric_limits
|
#include <algorithm> // for std::set_intersection, std::reverse
|
||||||
|
#include <iostream> // for debug output
|
||||||
|
#include <limits> // for std::numeric_limits
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <functional> // for std::function
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
// 初始化 支配树静态 ID
|
// ==============================================================
|
||||||
|
// DominatorTreeAnalysisPass 的静态ID
|
||||||
|
// ==============================================================
|
||||||
void *DominatorTreeAnalysisPass::ID = (void *)&DominatorTreeAnalysisPass::ID;
|
void *DominatorTreeAnalysisPass::ID = (void *)&DominatorTreeAnalysisPass::ID;
|
||||||
|
|
||||||
// ==============================================================
|
// ==============================================================
|
||||||
// DominatorTree 结果类的实现
|
// DominatorTree 结果类的实现
|
||||||
// ==============================================================
|
// ==============================================================
|
||||||
|
|
||||||
|
// 构造函数:初始化关联函数,但不进行计算
|
||||||
DominatorTree::DominatorTree(Function *F) : AssociatedFunction(F) {
|
DominatorTree::DominatorTree(Function *F) : AssociatedFunction(F) {
|
||||||
// 构造时可以不计算,在分析遍运行里计算并填充
|
// 构造时不需要计算,在分析遍运行里计算并填充
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getter 方法 (保持不变)
|
||||||
const std::set<BasicBlock *> *DominatorTree::getDominators(BasicBlock *BB) const {
|
const std::set<BasicBlock *> *DominatorTree::getDominators(BasicBlock *BB) const {
|
||||||
auto it = Dominators.find(BB);
|
auto it = Dominators.find(BB);
|
||||||
if (it != Dominators.end()) {
|
if (it != Dominators.end()) {
|
||||||
@@ -38,164 +49,437 @@ const std::set<BasicBlock *> *DominatorTree::getDominanceFrontier(BasicBlock *BB
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::set<BasicBlock*>* DominatorTree::getDominatorTreeChildren(BasicBlock* BB) const {
|
const std::set<BasicBlock *> *DominatorTree::getDominatorTreeChildren(BasicBlock *BB) const {
|
||||||
auto it = DominatorTreeChildren.find(BB);
|
auto it = DominatorTreeChildren.find(BB);
|
||||||
if (it != DominatorTreeChildren.end()) {
|
if (it != DominatorTreeChildren.end()) {
|
||||||
return &(it->second);
|
return &(it->second);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DominatorTree::computeDominators(Function *F) {
|
// 辅助函数:打印 BasicBlock 集合 (保持不变)
|
||||||
// 经典的迭代算法计算支配者集合
|
void printBBSet(const std::string &prefix, const std::set<BasicBlock *> &s) {
|
||||||
// TODO: 可以替换为更高效的算法,如 Lengauer-Tarjan 算法
|
if (!DEBUG)
|
||||||
BasicBlock *entryBlock = F->getEntryBlock();
|
return;
|
||||||
|
std::cout << prefix << "{";
|
||||||
|
bool first = true;
|
||||||
|
for (const auto &bb : s) {
|
||||||
|
if (!first)
|
||||||
|
std::cout << ", ";
|
||||||
|
std::cout << bb->getName();
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
std::cout << "}" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto &bb_ptr : F->getBasicBlocks()) {
|
// 辅助函数:计算逆后序遍历 (RPO) - 保持不变
|
||||||
BasicBlock *bb = bb_ptr.get();
|
std::vector<BasicBlock*> DominatorTree::computeReversePostOrder(Function* F) {
|
||||||
|
std::vector<BasicBlock*> postOrder;
|
||||||
|
std::set<BasicBlock*> visited;
|
||||||
|
|
||||||
|
std::function<void(BasicBlock*)> dfs_rpo =
|
||||||
|
[&](BasicBlock* bb) {
|
||||||
|
visited.insert(bb);
|
||||||
|
for (BasicBlock* succ : bb->getSuccessors()) {
|
||||||
|
if (visited.find(succ) == visited.end()) {
|
||||||
|
dfs_rpo(succ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
postOrder.push_back(bb);
|
||||||
|
};
|
||||||
|
|
||||||
|
dfs_rpo(F->getEntryBlock());
|
||||||
|
std::reverse(postOrder.begin(), postOrder.end());
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "--- Computed RPO: ";
|
||||||
|
for (BasicBlock* bb : postOrder) {
|
||||||
|
std::cout << bb->getName() << " ";
|
||||||
|
}
|
||||||
|
std::cout << "---" << std::endl;
|
||||||
|
}
|
||||||
|
return postOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
// computeDominators 方法 (保持不变,因为它它是独立于IDom算法的)
|
||||||
|
void DominatorTree::computeDominators(Function *F) {
|
||||||
|
if (DEBUG)
|
||||||
|
std::cout << "--- Computing Dominators ---" << std::endl;
|
||||||
|
|
||||||
|
BasicBlock *entryBlock = F->getEntryBlock();
|
||||||
|
std::vector<BasicBlock*> bbs_rpo = computeReversePostOrder(F);
|
||||||
|
|
||||||
|
for (BasicBlock *bb : bbs_rpo) {
|
||||||
if (bb == entryBlock) {
|
if (bb == entryBlock) {
|
||||||
|
Dominators[bb].clear();
|
||||||
Dominators[bb].insert(bb);
|
Dominators[bb].insert(bb);
|
||||||
|
if (DEBUG) std::cout << "Init Dominators[" << bb->getName() << "]: {" << bb->getName() << "}" << std::endl;
|
||||||
} else {
|
} else {
|
||||||
for (const auto &all_bb_ptr : F->getBasicBlocks()) {
|
Dominators[bb].clear();
|
||||||
Dominators[bb].insert(all_bb_ptr.get());
|
for (BasicBlock *all_bb : bbs_rpo) {
|
||||||
|
Dominators[bb].insert(all_bb);
|
||||||
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Init Dominators[" << bb->getName() << "]: ";
|
||||||
|
printBBSet("", Dominators[bb]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool changed = true;
|
bool changed = true;
|
||||||
|
int iteration = 0;
|
||||||
while (changed) {
|
while (changed) {
|
||||||
changed = false;
|
changed = false;
|
||||||
for (const auto &bb_ptr : F->getBasicBlocks()) {
|
iteration++;
|
||||||
BasicBlock *bb = bb_ptr.get();
|
if (DEBUG) std::cout << "Iteration " << iteration << std::endl;
|
||||||
if (bb == entryBlock)
|
|
||||||
continue;
|
for (BasicBlock *bb : bbs_rpo) {
|
||||||
|
if (bb == entryBlock) continue;
|
||||||
|
|
||||||
std::set<BasicBlock *> newDom;
|
std::set<BasicBlock *> newDom;
|
||||||
bool firstPred = true;
|
bool firstPredProcessed = false;
|
||||||
|
|
||||||
for (BasicBlock *pred : bb->getPredecessors()) {
|
for (BasicBlock *pred : bb->getPredecessors()) {
|
||||||
if (Dominators.count(pred)) {
|
if(DEBUG){
|
||||||
if (firstPred) {
|
std::cout << " Processing predecessor: " << pred->getName() << std::endl;
|
||||||
newDom = Dominators[pred];
|
|
||||||
firstPred = false;
|
|
||||||
} else {
|
|
||||||
std::set<BasicBlock *> intersection;
|
|
||||||
std::set_intersection(newDom.begin(), newDom.end(), Dominators[pred].begin(), Dominators[pred].end(),
|
|
||||||
std::inserter(intersection, intersection.begin()));
|
|
||||||
newDom = intersection;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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);
|
newDom.insert(bb);
|
||||||
|
|
||||||
if (newDom != Dominators[bb]) {
|
if (newDom != Dominators[bb]) {
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << " Dominators[" << bb->getName() << "] changed from ";
|
||||||
|
printBBSet("", Dominators[bb]);
|
||||||
|
std::cout << " to ";
|
||||||
|
printBBSet("", newDom);
|
||||||
|
}
|
||||||
Dominators[bb] = newDom;
|
Dominators[bb] = newDom;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (DEBUG)
|
||||||
|
std::cout << "--- Dominators Computation Finished ---" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DominatorTree::computeIDoms(Function *F) {
|
// ==============================================================
|
||||||
// 采用与之前类似的简化实现。TODO:Lengauer-Tarjan等算法。
|
// Lengauer-Tarjan 算法辅助数据结构和函数 (私有成员)
|
||||||
BasicBlock *entryBlock = F->getEntryBlock();
|
// ==============================================================
|
||||||
IDoms[entryBlock] = nullptr;
|
|
||||||
|
|
||||||
for (const auto &bb_ptr : F->getBasicBlocks()) {
|
// DFS 遍历,填充 dfnum_map, vertex_vec, parent_map
|
||||||
BasicBlock *bb = bb_ptr.get();
|
// 对应用户代码的 dfs 函数
|
||||||
if (bb == entryBlock)
|
void DominatorTree::dfs_lt_helper(BasicBlock* u) {
|
||||||
continue;
|
dfnum_map[u] = df_counter;
|
||||||
|
if (df_counter >= vertex_vec.size()) { // 动态调整大小
|
||||||
BasicBlock *currentIDom = nullptr;
|
vertex_vec.resize(df_counter + 1);
|
||||||
const std::set<BasicBlock *> *domsOfBB = getDominators(bb);
|
}
|
||||||
if (!domsOfBB)
|
vertex_vec[df_counter] = u;
|
||||||
continue;
|
if (DEBUG) std::cout << " DFS: Visiting " << u->getName() << ", dfnum = " << df_counter << std::endl;
|
||||||
|
df_counter++;
|
||||||
for (BasicBlock *D : *domsOfBB) {
|
|
||||||
if (D == bb)
|
for (BasicBlock* v : u->getSuccessors()) {
|
||||||
continue;
|
if (dfnum_map.find(v) == dfnum_map.end()) { // 如果 v 未访问过
|
||||||
|
parent_map[v] = u;
|
||||||
bool isCandidateIDom = true;
|
if (DEBUG) std::cout << " DFS: Setting parent[" << v->getName() << "] = " << u->getName() << std::endl;
|
||||||
for (BasicBlock *candidate : *domsOfBB) {
|
dfs_lt_helper(v);
|
||||||
if (candidate == bb || candidate == D)
|
}
|
||||||
continue;
|
|
||||||
const std::set<BasicBlock *> *domsOfCandidate = getDominators(candidate);
|
|
||||||
if (domsOfCandidate && domsOfCandidate->count(D) == 0 && domsOfBB->count(candidate)) {
|
|
||||||
isCandidateIDom = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isCandidateIDom) {
|
|
||||||
currentIDom = D;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
IDoms[bb] = currentIDom;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 并查集:找到集合的代表,并进行路径压缩
|
||||||
|
// 同时更新 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) {
|
void DominatorTree::computeDominanceFrontiers(Function *F) {
|
||||||
// 经典的支配边界计算算法
|
if (DEBUG)
|
||||||
|
std::cout << "--- Computing Dominance Frontiers ---" << std::endl;
|
||||||
|
|
||||||
for (const auto &bb_ptr_X : F->getBasicBlocks()) {
|
for (const auto &bb_ptr_X : F->getBasicBlocks()) {
|
||||||
BasicBlock *X = bb_ptr_X.get();
|
BasicBlock *X = bb_ptr_X.get();
|
||||||
DominanceFrontiers[X].clear();
|
DominanceFrontiers[X].clear();
|
||||||
|
|
||||||
for (BasicBlock *Y : X->getSuccessors()) {
|
|
||||||
const std::set<BasicBlock *> *domsOfY = getDominators(Y);
|
|
||||||
if (domsOfY && domsOfY->find(X) == domsOfY->end()) {
|
|
||||||
DominanceFrontiers[X].insert(Y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::set<BasicBlock *> *domsOfX = getDominators(X);
|
|
||||||
if (!domsOfX)
|
|
||||||
continue;
|
|
||||||
for (const auto &bb_ptr_Z : F->getBasicBlocks()) {
|
for (const auto &bb_ptr_Z : F->getBasicBlocks()) {
|
||||||
BasicBlock *Z = bb_ptr_Z.get();
|
BasicBlock *Z = bb_ptr_Z.get();
|
||||||
if (Z == X)
|
|
||||||
continue;
|
|
||||||
const std::set<BasicBlock *> *domsOfZ = getDominators(Z);
|
const std::set<BasicBlock *> *domsOfZ = getDominators(Z);
|
||||||
if (domsOfZ && domsOfZ->count(X) && Z != X) {
|
|
||||||
|
|
||||||
for (BasicBlock *Y : Z->getSuccessors()) {
|
if (!domsOfZ || domsOfZ->find(X) == domsOfZ->end()) { // Z 不被 X 支配
|
||||||
const std::set<BasicBlock *> *domsOfY = getDominators(Y);
|
continue;
|
||||||
if (domsOfY && domsOfY->find(X) == domsOfY->end()) {
|
}
|
||||||
DominanceFrontiers[X].insert(Y);
|
|
||||||
}
|
for (BasicBlock *Y : Z->getSuccessors()) {
|
||||||
|
const std::set<BasicBlock *> *domsOfY = getDominators(Y);
|
||||||
|
// 如果 Y == X,或者 Y 不被 X 严格支配 (即 Y 不被 X 支配)
|
||||||
|
if (Y == X || (domsOfY && domsOfY->find(X) == domsOfY->end())) {
|
||||||
|
DominanceFrontiers[X].insert(Y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << " DF(" << X->getName() << "): ";
|
||||||
|
printBBSet("", DominanceFrontiers[X]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (DEBUG)
|
||||||
|
std::cout << "--- Dominance Frontiers Computation Finished ---" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DominatorTree::computeDominatorTreeChildren(Function *F) {
|
void DominatorTree::computeDominatorTreeChildren(Function *F) {
|
||||||
|
if (DEBUG)
|
||||||
|
std::cout << "--- Computing Dominator Tree Children ---" << std::endl;
|
||||||
|
// 首先清空,确保重新计算时是空的
|
||||||
|
for (auto &bb_ptr : F->getBasicBlocks()) {
|
||||||
|
DominatorTreeChildren[bb_ptr.get()].clear();
|
||||||
|
}
|
||||||
|
|
||||||
for (auto &bb_ptr : F->getBasicBlocks()) {
|
for (auto &bb_ptr : F->getBasicBlocks()) {
|
||||||
BasicBlock *B = bb_ptr.get();
|
BasicBlock *B = bb_ptr.get();
|
||||||
auto it = getImmediateDominator(B);
|
BasicBlock *A = getImmediateDominator(B); // A 是 B 的即时支配者
|
||||||
if (it != nullptr) {
|
|
||||||
BasicBlock *A = it;
|
if (A) { // 如果 B 有即时支配者 A (即 B 不是入口块)
|
||||||
if (A) {
|
DominatorTreeChildren[A].insert(B);
|
||||||
DominatorTreeChildren[A].insert(B);
|
if (DEBUG) {
|
||||||
|
std::cout << " " << B->getName() << " is child of " << A->getName() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (DEBUG)
|
||||||
|
std::cout << "--- Dominator Tree Children Computation Finished ---" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==============================================================
|
// ==============================================================
|
||||||
// DominatorTreeAnalysisPass 的实现
|
// DominatorTreeAnalysisPass 的实现 (保持不变)
|
||||||
// ==============================================================
|
// ==============================================================
|
||||||
|
|
||||||
|
bool DominatorTreeAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||||
bool DominatorTreeAnalysisPass::runOnFunction(Function* F, AnalysisManager &AM) {
|
// 每次运行时清空旧数据,确保重新计算
|
||||||
CurrentDominatorTree = std::make_unique<DominatorTree>(F);
|
CurrentDominatorTree = std::make_unique<DominatorTree>(F);
|
||||||
|
|
||||||
CurrentDominatorTree->computeDominators(F);
|
CurrentDominatorTree->computeDominators(F);
|
||||||
CurrentDominatorTree->computeIDoms(F);
|
CurrentDominatorTree->computeIDoms(F); // 修正后的LT算法
|
||||||
CurrentDominatorTree->computeDominanceFrontiers(F);
|
CurrentDominatorTree->computeDominanceFrontiers(F);
|
||||||
CurrentDominatorTree->computeDominatorTreeChildren(F);
|
CurrentDominatorTree->computeDominatorTreeChildren(F);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<AnalysisResultBase> DominatorTreeAnalysisPass::getResult() {
|
std::unique_ptr<AnalysisResultBase> DominatorTreeAnalysisPass::getResult() {
|
||||||
// 返回计算好的 DominatorTree 实例,所有权转移给 AnalysisManager
|
|
||||||
return std::move(CurrentDominatorTree);
|
return std::move(CurrentDominatorTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
79
src/midend/Pass/Optimize/BuildCFG.cpp
Normal file
79
src/midend/Pass/Optimize/BuildCFG.cpp
Normal 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
|
||||||
@@ -51,10 +51,8 @@ void DCEContext::run(Function *func, AnalysisManager *AM, bool &changed) {
|
|||||||
// 如果指令不在活跃集合中,则删除它。
|
// 如果指令不在活跃集合中,则删除它。
|
||||||
// 分支和返回指令由 isAlive 处理,并会被保留。
|
// 分支和返回指令由 isAlive 处理,并会被保留。
|
||||||
if (alive_insts.count(currentInst) == 0) {
|
if (alive_insts.count(currentInst) == 0) {
|
||||||
// 删除指令,保留用户风格的 SysYIROptUtils::usedelete 和 erase
|
instIter = SysYIROptUtils::usedelete(instIter); // 删除后返回下一个迭代器
|
||||||
changed = true; // 标记 IR 已被修改
|
changed = true; // 标记 IR 已被修改
|
||||||
SysYIROptUtils::usedelete(currentInst);
|
|
||||||
instIter = basicBlock->getInstructions().erase(instIter); // 删除后返回下一个迭代器
|
|
||||||
} else {
|
} else {
|
||||||
++instIter; // 指令活跃,移动到下一个
|
++instIter; // 指令活跃,移动到下一个
|
||||||
}
|
}
|
||||||
|
|||||||
143
src/midend/Pass/Optimize/LargeArrayToGlobal.cpp
Normal file
143
src/midend/Pass/Optimize/LargeArrayToGlobal.cpp
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
#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);
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
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
|
||||||
@@ -60,7 +60,7 @@ void Mem2RegContext::run(Function *func, AnalysisManager *AM) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 从入口基本块开始,对支配树进行 DFS 遍历,进行变量重命名
|
// 从入口基本块开始,对支配树进行 DFS 遍历,进行变量重命名
|
||||||
renameVariables(nullptr, func->getEntryBlock()); // 第一个参数 alloca 在这里不使用,因为是递归入口点
|
renameVariables(func->getEntryBlock()); // 第一个参数 alloca 在这里不使用,因为是递归入口点
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
// 阶段4: 清理
|
// 阶段4: 清理
|
||||||
@@ -209,16 +209,21 @@ void Mem2RegContext::insertPhis(AllocaInst *alloca, const std::unordered_set<Bas
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 对支配树进行深度优先遍历,重命名变量并替换 load/store 指令
|
// 对支配树进行深度优先遍历,重命名变量并替换 load/store 指令
|
||||||
void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *currentBB) {
|
// 移除了 AllocaInst *currentAlloca 参数,因为这个函数是为整个基本块处理所有可提升的 Alloca
|
||||||
// 维护一个局部栈,用于存储当前基本块中为 Phi 和 Store 创建的 SSA 值,以便在退出时弹出
|
void Mem2RegContext::renameVariables(BasicBlock *currentBB) {
|
||||||
std::stack<Value *> localStackPushed;
|
// 1. 在函数开始时,记录每个 promotableAlloca 的当前栈深度。
|
||||||
|
// 这将用于在函数返回时精确地回溯栈状态。
|
||||||
|
std::map<AllocaInst *, size_t> originalStackSizes;
|
||||||
|
for (auto alloca : promotableAllocas) {
|
||||||
|
originalStackSizes[alloca] = allocaToValueStackMap[alloca].size();
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
// 处理当前基本块的指令
|
// 处理当前基本块的指令
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
for (auto instIter = currentBB->getInstructions().begin(); instIter != currentBB->getInstructions().end();) {
|
for (auto instIter = currentBB->getInstructions().begin(); instIter != currentBB->getInstructions().end();) {
|
||||||
Instruction *inst = instIter->get();
|
Instruction *inst = instIter->get();
|
||||||
bool instDeleted = false;
|
bool instDeleted = false;
|
||||||
|
|
||||||
// 处理 Phi 指令 (如果是当前 alloca 的 Phi)
|
// 处理 Phi 指令 (如果是当前 alloca 的 Phi)
|
||||||
if (auto phiInst = dynamic_cast<PhiInst *>(inst)) {
|
if (auto phiInst = dynamic_cast<PhiInst *>(inst)) {
|
||||||
@@ -227,52 +232,69 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr
|
|||||||
if (allocaToPhiMap[alloca].count(currentBB) && allocaToPhiMap[alloca][currentBB] == phiInst) {
|
if (allocaToPhiMap[alloca].count(currentBB) && allocaToPhiMap[alloca][currentBB] == phiInst) {
|
||||||
// 为 Phi 指令的输出创建一个新的 SSA 值,并压入值栈
|
// 为 Phi 指令的输出创建一个新的 SSA 值,并压入值栈
|
||||||
allocaToValueStackMap[alloca].push(phiInst);
|
allocaToValueStackMap[alloca].push(phiInst);
|
||||||
localStackPushed.push(phiInst); // 记录以便弹出
|
if (DEBUG) {
|
||||||
break; // 找到对应的 alloca,处理下一个指令
|
std::cout << "Mem2Reg: Pushed Phi " << (phiInst->getName().empty() ? "anonymous" : phiInst->getName()) << " for alloca " << alloca->getName()
|
||||||
|
<< ". Stack size: " << allocaToValueStackMap[alloca].size() << std::endl;
|
||||||
|
}
|
||||||
|
break; // 找到对应的 alloca,处理下一个指令
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 处理 LoadInst
|
// 处理 LoadInst
|
||||||
else if (auto loadInst = dynamic_cast<LoadInst *>(inst)) {
|
else if (auto loadInst = dynamic_cast<LoadInst *>(inst)) {
|
||||||
// 检查这个 LoadInst 是否是为某个可提升的 alloca
|
|
||||||
for (auto alloca : promotableAllocas) {
|
for (auto alloca : promotableAllocas) {
|
||||||
if (loadInst->getPointer() == alloca) {
|
// 检查 LoadInst 的指针是否直接是 alloca,或者是指向 alloca 的 GEP
|
||||||
// loadInst->getPointer() 返回 AllocaInst*
|
Value *ptrOperand = loadInst->getPointer();
|
||||||
// 将 LoadInst 的所有用途替换为当前 alloca 值栈顶部的 SSA 值
|
if (ptrOperand == alloca || (dynamic_cast<GetElementPtrInst *>(ptrOperand) &&
|
||||||
|
dynamic_cast<GetElementPtrInst *>(ptrOperand)->getBasePointer() == alloca)) {
|
||||||
assert(!allocaToValueStackMap[alloca].empty() && "Value stack empty for alloca during load replacement!");
|
assert(!allocaToValueStackMap[alloca].empty() && "Value stack empty for alloca during load replacement!");
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Mem2Reg: Replacing load "
|
||||||
|
<< (ptrOperand->getName().empty() ? "anonymous" : ptrOperand->getName()) << " with SSA value "
|
||||||
|
<< (allocaToValueStackMap[alloca].top()->getName().empty()
|
||||||
|
? "anonymous"
|
||||||
|
: allocaToValueStackMap[alloca].top()->getName())
|
||||||
|
<< " for alloca " << alloca->getName() << std::endl;
|
||||||
|
std::cout << "Mem2Reg: allocaToValueStackMap[" << alloca->getName()
|
||||||
|
<< "] size: " << allocaToValueStackMap[alloca].size() << std::endl;
|
||||||
|
}
|
||||||
loadInst->replaceAllUsesWith(allocaToValueStackMap[alloca].top());
|
loadInst->replaceAllUsesWith(allocaToValueStackMap[alloca].top());
|
||||||
// instIter = currentBB->force_delete_inst(loadInst); // 删除 LoadInst
|
instIter = SysYIROptUtils::usedelete(instIter);
|
||||||
SysYIROptUtils::usedelete(loadInst); // 仅删除 use 关系
|
|
||||||
instIter = currentBB->getInstructions().erase(instIter); // 删除 LoadInst
|
|
||||||
instDeleted = true;
|
instDeleted = true;
|
||||||
// std::cerr << "Mem2Reg: Replaced load " << loadInst->name() << " with SSA value." << std::endl;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 处理 StoreInst
|
// 处理 StoreInst
|
||||||
else if (auto storeInst = dynamic_cast<StoreInst *>(inst)) {
|
else if (auto storeInst = dynamic_cast<StoreInst *>(inst)) {
|
||||||
// 检查这个 StoreInst 是否是为某个可提升的 alloca
|
|
||||||
for (auto alloca : promotableAllocas) {
|
for (auto alloca : promotableAllocas) {
|
||||||
if (storeInst->getPointer() == alloca) {
|
// 检查 StoreInst 的指针是否直接是 alloca,或者是指向 alloca 的 GEP
|
||||||
// 假设 storeInst->getPointer() 返回 AllocaInst*
|
Value *ptrOperand = storeInst->getPointer();
|
||||||
// 将 StoreInst 存储的值作为新的 SSA 值,压入值栈
|
if (ptrOperand == alloca || (dynamic_cast<GetElementPtrInst *>(ptrOperand) &&
|
||||||
|
dynamic_cast<GetElementPtrInst *>(ptrOperand)->getBasePointer() == alloca)) {
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Mem2Reg: Replacing store to "
|
||||||
|
<< (ptrOperand->getName().empty() ? "anonymous" : ptrOperand->getName()) << " with SSA value "
|
||||||
|
<< (storeInst->getValue()->getName().empty() ? "anonymous" : storeInst->getValue()->getName())
|
||||||
|
<< " for alloca " << alloca->getName() << std::endl;
|
||||||
|
std::cout << "Mem2Reg: allocaToValueStackMap[" << alloca->getName()
|
||||||
|
<< "] size before push: " << allocaToValueStackMap[alloca].size() << std::endl;
|
||||||
|
}
|
||||||
allocaToValueStackMap[alloca].push(storeInst->getValue());
|
allocaToValueStackMap[alloca].push(storeInst->getValue());
|
||||||
localStackPushed.push(storeInst->getValue()); // 记录以便弹出
|
instIter = SysYIROptUtils::usedelete(instIter);
|
||||||
SysYIROptUtils::usedelete(storeInst);
|
|
||||||
instIter = currentBB->getInstructions().erase(instIter); // 删除 StoreInst
|
|
||||||
instDeleted = true;
|
instDeleted = true;
|
||||||
// std::cerr << "Mem2Reg: Replaced store to " << storeInst->ptr()->name() << " with SSA value." << std::endl;
|
if (DEBUG) {
|
||||||
|
std::cout << "Mem2Reg: allocaToValueStackMap[" << alloca->getName()
|
||||||
|
<< "] size after push: " << allocaToValueStackMap[alloca].size() << std::endl;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!instDeleted) {
|
if (!instDeleted) {
|
||||||
++instIter; // 如果指令没有被删除,移动到下一个
|
++instIter; // 如果指令没有被删除,移动到下一个
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
// 处理后继基本块的 Phi 指令参数
|
// 处理后继基本块的 Phi 指令参数
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
@@ -287,38 +309,57 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr
|
|||||||
// 参数值是当前 alloca 值栈顶部的 SSA 值
|
// 参数值是当前 alloca 值栈顶部的 SSA 值
|
||||||
assert(!allocaToValueStackMap[alloca].empty() && "Value stack empty for alloca when setting phi operand!");
|
assert(!allocaToValueStackMap[alloca].empty() && "Value stack empty for alloca when setting phi operand!");
|
||||||
phiInst->addIncoming(allocaToValueStackMap[alloca].top(), currentBB);
|
phiInst->addIncoming(allocaToValueStackMap[alloca].top(), currentBB);
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Mem2Reg: Added incoming arg to Phi "
|
||||||
|
<< (phiInst->getName().empty() ? "anonymous" : phiInst->getName()) << " from "
|
||||||
|
<< currentBB->getName() << " with value "
|
||||||
|
<< (allocaToValueStackMap[alloca].top()->getName().empty()
|
||||||
|
? "anonymous"
|
||||||
|
: allocaToValueStackMap[alloca].top()->getName())
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
// 递归访问支配树的子节点
|
// 递归访问支配树的子节点
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
const std::set<BasicBlock *> *dominatedBlocks = dt->getDominatorTreeChildren(currentBB);
|
const std::set<BasicBlock *> *dominatedBlocks = dt->getDominatorTreeChildren(currentBB);
|
||||||
if(dominatedBlocks){
|
if (dominatedBlocks) { // 检查是否存在子节点
|
||||||
|
if(DEBUG){
|
||||||
|
std::cout << "Mem2Reg: Processing dominated blocks for " << currentBB->getName() << std::endl;
|
||||||
|
for (auto dominatedBB : *dominatedBlocks) {
|
||||||
|
std::cout << "Mem2Reg: Dominated block: " << (dominatedBB ? dominatedBB->getName() : "null") << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (auto dominatedBB : *dominatedBlocks) {
|
for (auto dominatedBB : *dominatedBlocks) {
|
||||||
if (dominatedBB) {
|
if (dominatedBB) { // 确保子块有效
|
||||||
std::cout << "Mem2Reg: Recursively renaming variables in dominated block: " << dominatedBB->getName() << std::endl;
|
if (DEBUG) {
|
||||||
renameVariables(currentAlloca, dominatedBB);
|
std::cout << "Mem2Reg: Recursively renaming variables in dominated block: " << dominatedBB->getName()
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
renameVariables(dominatedBB); // 递归调用,不再传递 currentAlloca
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
// 退出基本块时,弹出在此块中压入值栈的 SSA 值
|
// 退出基本块时,弹出在此块中压入值栈的 SSA 值,恢复栈到进入该块时的状态
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
while (!localStackPushed.empty()) {
|
for (auto alloca : promotableAllocas) {
|
||||||
Value *val = localStackPushed.top();
|
while (allocaToValueStackMap[alloca].size() > originalStackSizes[alloca]) {
|
||||||
localStackPushed.pop();
|
if (DEBUG) {
|
||||||
// 找到是哪个 alloca 对应的栈
|
std::cout << "Mem2Reg: Popping value "
|
||||||
for (auto alloca : promotableAllocas) {
|
<< (allocaToValueStackMap[alloca].top()->getName().empty()
|
||||||
if (!allocaToValueStackMap[alloca].empty() && allocaToValueStackMap[alloca].top() == val) {
|
? "anonymous"
|
||||||
allocaToValueStackMap[alloca].pop();
|
: allocaToValueStackMap[alloca].top()->getName())
|
||||||
break;
|
<< " for alloca " << alloca->getName() << ". Stack size: " << allocaToValueStackMap[alloca].size()
|
||||||
|
<< " -> " << (allocaToValueStackMap[alloca].size() - 1) << std::endl;
|
||||||
}
|
}
|
||||||
|
allocaToValueStackMap[alloca].pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除所有原始的 AllocaInst、LoadInst 和 StoreInst
|
// 删除所有原始的 AllocaInst、LoadInst 和 StoreInst
|
||||||
@@ -327,7 +368,6 @@ void Mem2RegContext::cleanup() {
|
|||||||
if (alloca && alloca->getParent()) {
|
if (alloca && alloca->getParent()) {
|
||||||
// 删除 alloca 指令本身
|
// 删除 alloca 指令本身
|
||||||
SysYIROptUtils::usedelete(alloca);
|
SysYIROptUtils::usedelete(alloca);
|
||||||
alloca->getParent()->removeInst(alloca); // 从基本块中删除 alloca
|
|
||||||
|
|
||||||
// std::cerr << "Mem2Reg: Deleted alloca " << alloca->name() << std::endl;
|
// std::cerr << "Mem2Reg: Deleted alloca " << alloca->name() << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ void Reg2MemContext::allocateMemoryForSSAValues(Function *func) {
|
|||||||
// 默认情况下,将所有参数是提升到内存
|
// 默认情况下,将所有参数是提升到内存
|
||||||
if (isPromotableToMemory(arg)) {
|
if (isPromotableToMemory(arg)) {
|
||||||
// 参数的类型就是 AllocaInst 需要分配的类型
|
// 参数的类型就是 AllocaInst 需要分配的类型
|
||||||
AllocaInst *alloca = builder->createAllocaInst(Type::getPointerType(arg->getType()), {}, arg->getName() + ".reg2mem");
|
AllocaInst *alloca = builder->createAllocaInst(Type::getPointerType(arg->getType()), arg->getName() + ".reg2mem");
|
||||||
// 将参数值 store 到 alloca 中 (这是 Mem2Reg 逆转的关键一步)
|
// 将参数值 store 到 alloca 中 (这是 Mem2Reg 逆转的关键一步)
|
||||||
valueToAllocaMap[arg] = alloca;
|
valueToAllocaMap[arg] = alloca;
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ void Reg2MemContext::allocateMemoryForSSAValues(Function *func) {
|
|||||||
// AllocaInst 应该在入口块,而不是当前指令所在块
|
// AllocaInst 应该在入口块,而不是当前指令所在块
|
||||||
// 这里我们只是创建,并稍后调整其位置
|
// 这里我们只是创建,并稍后调整其位置
|
||||||
// 通常的做法是在循环结束后统一将 alloca 放到 entryBlock 的顶部
|
// 通常的做法是在循环结束后统一将 alloca 放到 entryBlock 的顶部
|
||||||
AllocaInst *alloca = builder->createAllocaInst(Type::getPointerType(inst.get()->getType()), {}, inst.get()->getName() + ".reg2mem");
|
AllocaInst *alloca = builder->createAllocaInst(Type::getPointerType(inst.get()->getType()), inst.get()->getName() + ".reg2mem");
|
||||||
valueToAllocaMap[inst.get()] = alloca;
|
valueToAllocaMap[inst.get()] = alloca;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,8 +181,7 @@ void Reg2MemContext::rewritePhis(Function *func) {
|
|||||||
// 实际删除 Phi 指令
|
// 实际删除 Phi 指令
|
||||||
for (auto phi : phisToErase) {
|
for (auto phi : phisToErase) {
|
||||||
if (phi && phi->getParent()) {
|
if (phi && phi->getParent()) {
|
||||||
SysYIROptUtils::usedelete(phi); // 清理 use-def 链
|
SysYIROptUtils::usedelete(phi);
|
||||||
phi->getParent()->removeInst(phi); // 从基本块中删除
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
880
src/midend/Pass/Optimize/SCCP.cpp
Normal file
880
src/midend/Pass/Optimize/SCCP.cpp
Normal file
@@ -0,0 +1,880 @@
|
|||||||
|
#include "SCCP.h"
|
||||||
|
#include "Dom.h"
|
||||||
|
#include "Liveness.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath> // For std::fmod, std::fabs
|
||||||
|
#include <limits> // For std::numeric_limits
|
||||||
|
|
||||||
|
namespace sysy {
|
||||||
|
|
||||||
|
// Pass ID for SCCP
|
||||||
|
void *SCCP::ID = (void *)&SCCP::ID;
|
||||||
|
|
||||||
|
// SCCPContext methods
|
||||||
|
SSAPValue SCCPContext::Meet(const SSAPValue &a, const SSAPValue &b) {
|
||||||
|
if (a.state == LatticeVal::Bottom || b.state == LatticeVal::Bottom) {
|
||||||
|
return SSAPValue(LatticeVal::Bottom);
|
||||||
|
}
|
||||||
|
if (a.state == LatticeVal::Top) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
if (b.state == LatticeVal::Top) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
// Both are constants
|
||||||
|
if (a.constant_type != b.constant_type) {
|
||||||
|
return SSAPValue(LatticeVal::Bottom); // 不同类型的常量,结果为 Bottom
|
||||||
|
}
|
||||||
|
if (a.constantVal == b.constantVal) {
|
||||||
|
return a; // 相同常量
|
||||||
|
}
|
||||||
|
return SSAPValue(LatticeVal::Bottom); // 相同类型但值不同,结果为 Bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
SSAPValue SCCPContext::GetValueState(Value *v) {
|
||||||
|
if (auto constVal = dynamic_cast<ConstantValue *>(v)) {
|
||||||
|
// 特殊处理 UndefinedValue:将其视为 Bottom
|
||||||
|
if (dynamic_cast<UndefinedValue *>(constVal)) {
|
||||||
|
return SSAPValue(LatticeVal::Bottom);
|
||||||
|
}
|
||||||
|
// 处理常规的 ConstantInteger 和 ConstantFloating
|
||||||
|
if (constVal->getType()->isInt()) {
|
||||||
|
return SSAPValue(constVal->getInt());
|
||||||
|
} else if (constVal->getType()->isFloat()) {
|
||||||
|
return SSAPValue(constVal->getFloat());
|
||||||
|
} else {
|
||||||
|
// 对于其他 ConstantValue 类型(例如,ConstantArray 等),
|
||||||
|
// 如果它们的具体值不能用于标量常量传播,则保守地视为 Bottom。
|
||||||
|
return SSAPValue(LatticeVal::Bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (valueState.count(v)) {
|
||||||
|
return valueState[v];
|
||||||
|
}
|
||||||
|
return SSAPValue(); // 默认初始化为 Top
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCCPContext::UpdateState(Value *v, SSAPValue newState) {
|
||||||
|
SSAPValue oldState = GetValueState(v);
|
||||||
|
if (newState != oldState) {
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Updating state for " << v->getName() << " from (";
|
||||||
|
if (oldState.state == LatticeVal::Top)
|
||||||
|
std::cout << "Top";
|
||||||
|
else if (oldState.state == LatticeVal::Constant) {
|
||||||
|
if (oldState.constant_type == ValueType::Integer)
|
||||||
|
std::cout << "Const<int>(" << std::get<int>(oldState.constantVal) << ")";
|
||||||
|
else
|
||||||
|
std::cout << "Const<float>(" << std::get<float>(oldState.constantVal) << ")";
|
||||||
|
} else
|
||||||
|
std::cout << "Bottom";
|
||||||
|
std::cout << ") to (";
|
||||||
|
if (newState.state == LatticeVal::Top)
|
||||||
|
std::cout << "Top";
|
||||||
|
else if (newState.state == LatticeVal::Constant) {
|
||||||
|
if (newState.constant_type == ValueType::Integer)
|
||||||
|
std::cout << "Const<int>(" << std::get<int>(newState.constantVal) << ")";
|
||||||
|
else
|
||||||
|
std::cout << "Const<float>(" << std::get<float>(newState.constantVal) << ")";
|
||||||
|
} else
|
||||||
|
std::cout << "Bottom";
|
||||||
|
std::cout << ")" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
valueState[v] = newState;
|
||||||
|
// 如果状态发生变化,将所有使用者添加到指令工作列表
|
||||||
|
for (auto &use_ptr : v->getUses()) {
|
||||||
|
if (auto userInst = dynamic_cast<Instruction *>(use_ptr->getUser())) {
|
||||||
|
instWorkList.push(userInst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCCPContext::AddEdgeToWorkList(BasicBlock *fromBB, BasicBlock *toBB) {
|
||||||
|
// 检查边是否已经访问过,防止重复处理
|
||||||
|
if (visitedCFGEdges.count({fromBB, toBB})) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
visitedCFGEdges.insert({fromBB, toBB});
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Adding edge to worklist: " << fromBB->getName() << " -> " << toBB->getName() << std::endl;
|
||||||
|
}
|
||||||
|
edgeWorkList.push({fromBB, toBB});
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCCPContext::MarkBlockExecutable(BasicBlock *block) {
|
||||||
|
if (executableBlocks.insert(block).second) { // insert 返回 pair,second 为 true 表示插入成功
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Marking block " << block->getName() << " as executable." << std::endl;
|
||||||
|
}
|
||||||
|
// 将新可执行块中的所有指令添加到指令工作列表
|
||||||
|
for (auto &inst_ptr : block->getInstructions()) {
|
||||||
|
instWorkList.push(inst_ptr.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助函数:对二元操作进行常量折叠
|
||||||
|
SSAPValue SCCPContext::ComputeConstant(BinaryInst *binaryInst, SSAPValue lhsVal, SSAPValue rhsVal) {
|
||||||
|
// 确保操作数是常量
|
||||||
|
if (lhsVal.state != LatticeVal::Constant || rhsVal.state != LatticeVal::Constant) {
|
||||||
|
return SSAPValue(LatticeVal::Bottom); // 如果不是常量,则不能折叠
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理整数运算 (kAdd, kSub, kMul, kDiv, kRem, kICmp*, kAnd, kOr)
|
||||||
|
if (lhsVal.constant_type == ValueType::Integer && rhsVal.constant_type == ValueType::Integer) {
|
||||||
|
int lhs = std::get<int>(lhsVal.constantVal);
|
||||||
|
int rhs = std::get<int>(rhsVal.constantVal);
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
switch (binaryInst->getKind()) {
|
||||||
|
case Instruction::kAdd:
|
||||||
|
result = lhs + rhs;
|
||||||
|
break;
|
||||||
|
case Instruction::kSub:
|
||||||
|
result = lhs - rhs;
|
||||||
|
break;
|
||||||
|
case Instruction::kMul:
|
||||||
|
result = lhs * rhs;
|
||||||
|
break;
|
||||||
|
case Instruction::kDiv:
|
||||||
|
if (rhs == 0)
|
||||||
|
return SSAPValue(LatticeVal::Bottom); // 除零
|
||||||
|
result = lhs / rhs;
|
||||||
|
break;
|
||||||
|
case Instruction::kRem:
|
||||||
|
if (rhs == 0)
|
||||||
|
return SSAPValue(LatticeVal::Bottom); // 模零
|
||||||
|
result = lhs % rhs;
|
||||||
|
break;
|
||||||
|
case Instruction::kICmpEQ:
|
||||||
|
result = (lhs == rhs);
|
||||||
|
break;
|
||||||
|
case Instruction::kICmpNE:
|
||||||
|
result = (lhs != rhs);
|
||||||
|
break;
|
||||||
|
case Instruction::kICmpLT:
|
||||||
|
result = (lhs < rhs);
|
||||||
|
break;
|
||||||
|
case Instruction::kICmpGT:
|
||||||
|
result = (lhs > rhs);
|
||||||
|
break;
|
||||||
|
case Instruction::kICmpLE:
|
||||||
|
result = (lhs <= rhs);
|
||||||
|
break;
|
||||||
|
case Instruction::kICmpGE:
|
||||||
|
result = (lhs >= rhs);
|
||||||
|
break;
|
||||||
|
case Instruction::kAnd:
|
||||||
|
result = (lhs && rhs);
|
||||||
|
break;
|
||||||
|
case Instruction::kOr:
|
||||||
|
result = (lhs || rhs);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SSAPValue(LatticeVal::Bottom); // 未知或不匹配的二元操作
|
||||||
|
}
|
||||||
|
return SSAPValue(result);
|
||||||
|
}
|
||||||
|
// 处理浮点运算 (kFAdd, kFSub, kFMul, kFDiv, kFCmp*)
|
||||||
|
else if (lhsVal.constant_type == ValueType::Float && rhsVal.constant_type == ValueType::Float) {
|
||||||
|
float lhs = std::get<float>(lhsVal.constantVal);
|
||||||
|
float rhs = std::get<float>(rhsVal.constantVal);
|
||||||
|
float f_result = 0.0f;
|
||||||
|
int i_result = 0; // For comparison results
|
||||||
|
|
||||||
|
switch (binaryInst->getKind()) {
|
||||||
|
case Instruction::kFAdd:
|
||||||
|
f_result = lhs + rhs;
|
||||||
|
break;
|
||||||
|
case Instruction::kFSub:
|
||||||
|
f_result = lhs - rhs;
|
||||||
|
break;
|
||||||
|
case Instruction::kFMul:
|
||||||
|
f_result = lhs * rhs;
|
||||||
|
break;
|
||||||
|
case Instruction::kFDiv:
|
||||||
|
if (rhs == 0.0f)
|
||||||
|
return SSAPValue(LatticeVal::Bottom); // 除零
|
||||||
|
f_result = lhs / rhs;
|
||||||
|
break;
|
||||||
|
// kRem 不支持浮点数,但如果你的 IR 定义了浮点模运算,需要使用 std::fmod
|
||||||
|
case Instruction::kFCmpEQ:
|
||||||
|
i_result = (lhs == rhs);
|
||||||
|
return SSAPValue(i_result);
|
||||||
|
case Instruction::kFCmpNE:
|
||||||
|
i_result = (lhs != rhs);
|
||||||
|
return SSAPValue(i_result);
|
||||||
|
case Instruction::kFCmpLT:
|
||||||
|
i_result = (lhs < rhs);
|
||||||
|
return SSAPValue(i_result);
|
||||||
|
case Instruction::kFCmpGT:
|
||||||
|
i_result = (lhs > rhs);
|
||||||
|
return SSAPValue(i_result);
|
||||||
|
case Instruction::kFCmpLE:
|
||||||
|
i_result = (lhs <= rhs);
|
||||||
|
return SSAPValue(i_result);
|
||||||
|
case Instruction::kFCmpGE:
|
||||||
|
i_result = (lhs >= rhs);
|
||||||
|
return SSAPValue(i_result);
|
||||||
|
default:
|
||||||
|
return SSAPValue(LatticeVal::Bottom); // 未知或不匹配的浮点二元操作
|
||||||
|
}
|
||||||
|
return SSAPValue(f_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SSAPValue(LatticeVal::Bottom); // 类型不匹配或不支持的类型组合
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助函数:对一元操作进行常量折叠
|
||||||
|
SSAPValue SCCPContext::ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVal) {
|
||||||
|
if (operandVal.state != LatticeVal::Constant) {
|
||||||
|
return SSAPValue(LatticeVal::Bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operandVal.constant_type == ValueType::Integer) {
|
||||||
|
int val = std::get<int>(operandVal.constantVal);
|
||||||
|
switch (unaryInst->getKind()) {
|
||||||
|
case Instruction::kAdd:
|
||||||
|
return SSAPValue(val);
|
||||||
|
case Instruction::kNeg:
|
||||||
|
return SSAPValue(-val);
|
||||||
|
case Instruction::kNot:
|
||||||
|
return SSAPValue(!val);
|
||||||
|
default:
|
||||||
|
return SSAPValue(LatticeVal::Bottom);
|
||||||
|
}
|
||||||
|
} else if (operandVal.constant_type == ValueType::Float) {
|
||||||
|
float val = std::get<float>(operandVal.constantVal);
|
||||||
|
switch (unaryInst->getKind()) {
|
||||||
|
case Instruction::kAdd:
|
||||||
|
return SSAPValue(val);
|
||||||
|
case Instruction::kFNeg:
|
||||||
|
return SSAPValue(-val);
|
||||||
|
case Instruction::kFNot:
|
||||||
|
return SSAPValue(static_cast<int>(val == 0.0f)); // 浮点数非,0.0f 为真,其他为假
|
||||||
|
default:
|
||||||
|
return SSAPValue(LatticeVal::Bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SSAPValue(LatticeVal::Bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助函数:处理单条指令
|
||||||
|
void SCCPContext::ProcessInstruction(Instruction *inst) {
|
||||||
|
SSAPValue oldState = GetValueState(inst);
|
||||||
|
SSAPValue newState;
|
||||||
|
|
||||||
|
if (!executableBlocks.count(inst->getParent())) {
|
||||||
|
// 如果指令所在的块不可执行,其值应保持 Top
|
||||||
|
// 除非它之前已经是 Bottom,因为 Bottom 是单调的
|
||||||
|
if (oldState.state != LatticeVal::Bottom) {
|
||||||
|
newState = SSAPValue(); // Top
|
||||||
|
} else {
|
||||||
|
newState = oldState; // 保持 Bottom
|
||||||
|
}
|
||||||
|
UpdateState(inst, newState);
|
||||||
|
return; // 不处理不可达块中的指令的实际值
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (inst->getKind()) {
|
||||||
|
case Instruction::kAdd:
|
||||||
|
case Instruction::kSub:
|
||||||
|
case Instruction::kMul:
|
||||||
|
case Instruction::kDiv:
|
||||||
|
case Instruction::kRem:
|
||||||
|
case Instruction::kICmpEQ:
|
||||||
|
case Instruction::kICmpNE:
|
||||||
|
case Instruction::kICmpLT:
|
||||||
|
case Instruction::kICmpGT:
|
||||||
|
case Instruction::kICmpLE:
|
||||||
|
case Instruction::kICmpGE:
|
||||||
|
case Instruction::kFAdd:
|
||||||
|
case Instruction::kFSub:
|
||||||
|
case Instruction::kFMul:
|
||||||
|
case Instruction::kFDiv:
|
||||||
|
case Instruction::kFCmpEQ:
|
||||||
|
case Instruction::kFCmpNE:
|
||||||
|
case Instruction::kFCmpLT:
|
||||||
|
case Instruction::kFCmpGT:
|
||||||
|
case Instruction::kFCmpLE:
|
||||||
|
case Instruction::kFCmpGE:
|
||||||
|
case Instruction::kAnd:
|
||||||
|
case Instruction::kOr: {
|
||||||
|
BinaryInst *binaryInst = static_cast<BinaryInst *>(inst);
|
||||||
|
SSAPValue lhs = GetValueState(binaryInst->getOperand(0));
|
||||||
|
SSAPValue rhs = GetValueState(binaryInst->getOperand(1));
|
||||||
|
// 如果任一操作数是 Bottom,结果就是 Bottom
|
||||||
|
if (lhs.state == LatticeVal::Bottom || rhs.state == LatticeVal::Bottom) {
|
||||||
|
newState = SSAPValue(LatticeVal::Bottom);
|
||||||
|
} else if (lhs.state == LatticeVal::Top || rhs.state == LatticeVal::Top) {
|
||||||
|
newState = SSAPValue(); // Top
|
||||||
|
} else { // 都是常量
|
||||||
|
newState = ComputeConstant(binaryInst, lhs, rhs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Instruction::kNeg:
|
||||||
|
case Instruction::kNot:
|
||||||
|
case Instruction::kFNeg:
|
||||||
|
case Instruction::kFNot: {
|
||||||
|
UnaryInst *unaryInst = static_cast<UnaryInst *>(inst);
|
||||||
|
SSAPValue operand = GetValueState(unaryInst->getOperand());
|
||||||
|
if (operand.state == LatticeVal::Bottom) {
|
||||||
|
newState = SSAPValue(LatticeVal::Bottom);
|
||||||
|
} else if (operand.state == LatticeVal::Top) {
|
||||||
|
newState = SSAPValue(); // Top
|
||||||
|
} else { // 是常量
|
||||||
|
newState = ComputeConstant(unaryInst, operand);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 直接处理类型转换指令
|
||||||
|
case Instruction::kFtoI: {
|
||||||
|
SSAPValue operand = GetValueState(inst->getOperand(0));
|
||||||
|
if (operand.state == LatticeVal::Constant && operand.constant_type == ValueType::Float) {
|
||||||
|
newState = SSAPValue(static_cast<int>(std::get<float>(operand.constantVal)));
|
||||||
|
} else if (operand.state == LatticeVal::Bottom) {
|
||||||
|
newState = SSAPValue(LatticeVal::Bottom);
|
||||||
|
} else { // Top
|
||||||
|
newState = SSAPValue();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Instruction::kItoF: {
|
||||||
|
SSAPValue operand = GetValueState(inst->getOperand(0));
|
||||||
|
if (operand.state == LatticeVal::Constant && operand.constant_type == ValueType::Integer) {
|
||||||
|
newState = SSAPValue(static_cast<float>(std::get<int>(operand.constantVal)));
|
||||||
|
} else if (operand.state == LatticeVal::Bottom) {
|
||||||
|
newState = SSAPValue(LatticeVal::Bottom);
|
||||||
|
} else { // Top
|
||||||
|
newState = SSAPValue();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Instruction::kBitFtoI: {
|
||||||
|
SSAPValue operand = GetValueState(inst->getOperand(0));
|
||||||
|
if (operand.state == LatticeVal::Constant && operand.constant_type == ValueType::Float) {
|
||||||
|
float fval = std::get<float>(operand.constantVal);
|
||||||
|
newState = SSAPValue(*reinterpret_cast<int *>(&fval));
|
||||||
|
} else if (operand.state == LatticeVal::Bottom) {
|
||||||
|
newState = SSAPValue(LatticeVal::Bottom);
|
||||||
|
} else { // Top
|
||||||
|
newState = SSAPValue();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Instruction::kBitItoF: {
|
||||||
|
SSAPValue operand = GetValueState(inst->getOperand(0));
|
||||||
|
if (operand.state == LatticeVal::Constant && operand.constant_type == ValueType::Integer) {
|
||||||
|
int ival = std::get<int>(operand.constantVal);
|
||||||
|
newState = SSAPValue(*reinterpret_cast<float *>(&ival));
|
||||||
|
} else if (operand.state == LatticeVal::Bottom) {
|
||||||
|
newState = SSAPValue(LatticeVal::Bottom);
|
||||||
|
} else { // Top
|
||||||
|
newState = SSAPValue();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Instruction::kLoad: {
|
||||||
|
// 对于 Load 指令,除非我们有特殊的别名分析,否则假定为 Bottom
|
||||||
|
// 或者如果它加载的是一个已知常量地址的全局常量
|
||||||
|
Value *ptr = inst->getOperand(0);
|
||||||
|
if (auto globalVal = dynamic_cast<GlobalValue *>(ptr)) {
|
||||||
|
// 如果 GlobalValue 有初始化器,并且它是常量,我们可以传播
|
||||||
|
// 这需要额外的逻辑来检查 globalVal 的初始化器
|
||||||
|
// 暂时保守地设置为 Bottom
|
||||||
|
newState = SSAPValue(LatticeVal::Bottom);
|
||||||
|
} else {
|
||||||
|
newState = SSAPValue(LatticeVal::Bottom);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Instruction::kStore:
|
||||||
|
// Store 指令不产生值,其 SSAPValue 不重要
|
||||||
|
newState = SSAPValue(); // 保持 Top
|
||||||
|
break;
|
||||||
|
case Instruction::kCall:
|
||||||
|
// 大多数 Call 指令都假定为 Bottom,除非是纯函数且所有参数都是常量
|
||||||
|
newState = SSAPValue(LatticeVal::Bottom);
|
||||||
|
break;
|
||||||
|
case Instruction::kGetElementPtr: {
|
||||||
|
// GEP 指令计算地址,通常其结果值(地址指向的内容)是 Bottom
|
||||||
|
// 除非所有索引和基指针都是常量,指向一个确定常量值的内存位置
|
||||||
|
bool all_ops_constant = true;
|
||||||
|
for (unsigned i = 0; i < inst->getNumOperands(); ++i) {
|
||||||
|
if (GetValueState(inst->getOperand(i)).state != LatticeVal::Constant) {
|
||||||
|
all_ops_constant = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 即使地址是常量,地址处的内容通常不是。所以通常是 Bottom
|
||||||
|
newState = SSAPValue(LatticeVal::Bottom);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Instruction::kPhi: {
|
||||||
|
PhiInst *phi = static_cast<PhiInst *>(inst);
|
||||||
|
SSAPValue phiResult = SSAPValue(); // 初始为 Top
|
||||||
|
|
||||||
|
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,则提前退出
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newState = phiResult;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Instruction::kAlloca: // 对应 kAlloca
|
||||||
|
// Alloca 分配内存,返回一个指针,其内容是 Bottom
|
||||||
|
newState = SSAPValue(LatticeVal::Bottom);
|
||||||
|
break;
|
||||||
|
case Instruction::kBr: // 对应 kBr
|
||||||
|
case Instruction::kCondBr: // 对应 kCondBr
|
||||||
|
case Instruction::kReturn: // 对应 kReturn
|
||||||
|
case Instruction::kUnreachable: // 对应 kUnreachable
|
||||||
|
// 终结符指令不产生值
|
||||||
|
newState = SSAPValue(); // 保持 Top
|
||||||
|
break;
|
||||||
|
case Instruction::kMemset:
|
||||||
|
// Memset 不产生值,但有副作用,不进行常量传播
|
||||||
|
newState = SSAPValue(LatticeVal::Bottom);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Unimplemented instruction kind in SCCP: " << inst->getKind() << std::endl;
|
||||||
|
}
|
||||||
|
newState = SSAPValue(LatticeVal::Bottom); // 未知指令保守处理为 Bottom
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
UpdateState(inst, newState);
|
||||||
|
|
||||||
|
// 特殊处理终结符指令,影响 CFG 边的可达性
|
||||||
|
if (inst->isTerminator()) {
|
||||||
|
if (inst->isBranch()) {
|
||||||
|
|
||||||
|
if (inst->isCondBr()) { // 使用 kCondBr
|
||||||
|
CondBrInst *branchInst = static_cast<CondBrInst *>(inst);
|
||||||
|
SSAPValue condVal = GetValueState(branchInst->getOperand(0));
|
||||||
|
if (condVal.state == LatticeVal::Constant) {
|
||||||
|
bool condition_is_true = false;
|
||||||
|
if (condVal.constant_type == ValueType::Integer) {
|
||||||
|
condition_is_true = (std::get<int>(condVal.constantVal) != 0);
|
||||||
|
} else if (condVal.constant_type == ValueType::Float) {
|
||||||
|
condition_is_true = (std::get<float>(condVal.constantVal) != 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (condition_is_true) {
|
||||||
|
AddEdgeToWorkList(branchInst->getParent(), branchInst->getThenBlock());
|
||||||
|
} else {
|
||||||
|
AddEdgeToWorkList(branchInst->getParent(), branchInst->getElseBlock());
|
||||||
|
}
|
||||||
|
} else { // 条件是 Top 或 Bottom,两条路径都可能
|
||||||
|
AddEdgeToWorkList(branchInst->getParent(), branchInst->getThenBlock());
|
||||||
|
AddEdgeToWorkList(branchInst->getParent(), branchInst->getElseBlock());
|
||||||
|
}
|
||||||
|
} else { // 无条件分支 (kBr)
|
||||||
|
UncondBrInst *branchInst = static_cast<UncondBrInst *>(inst);
|
||||||
|
AddEdgeToWorkList(branchInst->getParent(), branchInst->getBlock());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助函数:处理单条控制流边
|
||||||
|
void SCCPContext::ProcessEdge(const std::pair<BasicBlock *, BasicBlock *> &edge) {
|
||||||
|
BasicBlock *fromBB = edge.first;
|
||||||
|
BasicBlock *toBB = edge.second;
|
||||||
|
|
||||||
|
MarkBlockExecutable(toBB);
|
||||||
|
|
||||||
|
// 对于目标块中的所有 Phi 指令,重新评估其值,因为可能有新的前驱被激活
|
||||||
|
for (auto &inst_ptr : toBB->getInstructions()) {
|
||||||
|
if (dynamic_cast<PhiInst *>(inst_ptr.get())) {
|
||||||
|
instWorkList.push(inst_ptr.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 阶段1: 常量传播与折叠
|
||||||
|
bool SCCPContext::PropagateConstants(Function *func) {
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
// 初始化:所有值 Top,所有块不可执行
|
||||||
|
for (auto &bb_ptr : func->getBasicBlocks()) {
|
||||||
|
executableBlocks.erase(bb_ptr.get());
|
||||||
|
for (auto &inst_ptr : bb_ptr->getInstructions()) {
|
||||||
|
valueState[inst_ptr.get()] = SSAPValue(); // Top
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标记入口块为可执行
|
||||||
|
if (!func->getBasicBlocks().empty()) {
|
||||||
|
MarkBlockExecutable(func->getEntryBlock());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主循环:处理工作列表直到不动点
|
||||||
|
while (!instWorkList.empty() || !edgeWorkList.empty()) {
|
||||||
|
while (!edgeWorkList.empty()) {
|
||||||
|
ProcessEdge(edgeWorkList.front());
|
||||||
|
edgeWorkList.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!instWorkList.empty()) {
|
||||||
|
Instruction *inst = instWorkList.front();
|
||||||
|
instWorkList.pop();
|
||||||
|
ProcessInstruction(inst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 应用常量替换和死代码消除
|
||||||
|
std::vector<Instruction *> instsToDelete;
|
||||||
|
for (auto &bb_ptr : func->getBasicBlocks()) {
|
||||||
|
BasicBlock *bb = bb_ptr.get();
|
||||||
|
if (!executableBlocks.count(bb)) {
|
||||||
|
// 整个块是死块,标记所有指令删除
|
||||||
|
for (auto &inst_ptr : bb->getInstructions()) {
|
||||||
|
instsToDelete.push_back(inst_ptr.get());
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (auto it = bb->begin(); it != bb->end();) {
|
||||||
|
Instruction *inst = it->get();
|
||||||
|
SSAPValue ssaPVal = GetValueState(inst);
|
||||||
|
|
||||||
|
if (ssaPVal.state == LatticeVal::Constant) {
|
||||||
|
ConstantValue *constVal = nullptr;
|
||||||
|
if (ssaPVal.constant_type == ValueType::Integer) {
|
||||||
|
constVal = ConstantInteger::get(std::get<int>(ssaPVal.constantVal));
|
||||||
|
} else if (ssaPVal.constant_type == ValueType::Float) {
|
||||||
|
constVal = ConstantFloating::get(std::get<float>(ssaPVal.constantVal));
|
||||||
|
} else {
|
||||||
|
constVal = UndefinedValue::get(inst->getType()); // 不应发生
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Replacing " << inst->getName() << " with constant ";
|
||||||
|
if (ssaPVal.constant_type == ValueType::Integer)
|
||||||
|
std::cout << std::get<int>(ssaPVal.constantVal);
|
||||||
|
else
|
||||||
|
std::cout << std::get<float>(ssaPVal.constantVal);
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
inst->replaceAllUsesWith(constVal);
|
||||||
|
instsToDelete.push_back(inst);
|
||||||
|
++it;
|
||||||
|
changed = true;
|
||||||
|
} else {
|
||||||
|
// 如果操作数是常量,直接替换为常量值(常量折叠)
|
||||||
|
for (unsigned i = 0; i < inst->getNumOperands(); ++i) {
|
||||||
|
Value *operand = inst->getOperand(i);
|
||||||
|
SSAPValue opVal = GetValueState(operand);
|
||||||
|
if (opVal.state == LatticeVal::Constant) {
|
||||||
|
ConstantValue *constOp = nullptr;
|
||||||
|
if (opVal.constant_type == ValueType::Integer) {
|
||||||
|
constOp = ConstantInteger::get(std::get<int>(opVal.constantVal));
|
||||||
|
} else if (opVal.constant_type == ValueType::Float) {
|
||||||
|
constOp = ConstantFloating::get(std::get<float>(opVal.constantVal));
|
||||||
|
} else {
|
||||||
|
constOp = UndefinedValue::get(operand->getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constOp != operand) {
|
||||||
|
inst->setOperand(i, constOp);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实际删除指令
|
||||||
|
// TODO: 删除的逻辑需要考虑修改
|
||||||
|
for (Instruction *inst : instsToDelete) {
|
||||||
|
// 在尝试删除之前,先检查指令是否仍然附加到其父基本块。
|
||||||
|
// 如果它已经没有父块,可能说明它已被其他方式处理或已处于无效状态。
|
||||||
|
if (inst->getParent() != nullptr) {
|
||||||
|
// 调用负责完整删除的函数,该函数应负责清除uses并将其从父块中移除。
|
||||||
|
SysYIROptUtils::usedelete(inst);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// 指令已不属于任何父块,无需再次删除。
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cerr << "Info: Instruction " << inst->getName() << " was already detached or is not in a parent block." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 阶段2: 控制流简化
|
||||||
|
bool SCCPContext::SimplifyControlFlow(Function *func) {
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
// 重新确定可达块,因为 PropagateConstants 可能改变了分支条件
|
||||||
|
std::unordered_set<BasicBlock *> newReachableBlocks = FindReachableBlocks(func);
|
||||||
|
|
||||||
|
// 移除不可达块
|
||||||
|
std::vector<BasicBlock *> blocksToDelete;
|
||||||
|
for (auto &bb_ptr : func->getBasicBlocks()) {
|
||||||
|
if (bb_ptr.get() == func->getEntryBlock())
|
||||||
|
continue; // 入口块不能删除
|
||||||
|
if (newReachableBlocks.find(bb_ptr.get()) == newReachableBlocks.end()) {
|
||||||
|
blocksToDelete.push_back(bb_ptr.get());
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (BasicBlock *bb : blocksToDelete) {
|
||||||
|
RemoveDeadBlock(bb, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 简化分支指令
|
||||||
|
for (auto &bb_ptr : func->getBasicBlocks()) {
|
||||||
|
BasicBlock *bb = bb_ptr.get();
|
||||||
|
if (!newReachableBlocks.count(bb))
|
||||||
|
continue; // 只处理可达块
|
||||||
|
|
||||||
|
Instruction *terminator = bb->terminator()->get();
|
||||||
|
if (terminator->isBranch()) {
|
||||||
|
|
||||||
|
if (terminator->isCondBr()) { // 检查是否是条件分支 (kCondBr)
|
||||||
|
CondBrInst *branchInst = static_cast<CondBrInst *>(terminator);
|
||||||
|
SSAPValue condVal = GetValueState(branchInst->getOperand(0));
|
||||||
|
if (condVal.state == LatticeVal::Constant) {
|
||||||
|
bool condition_is_true = false;
|
||||||
|
if (condVal.constant_type == ValueType::Integer) {
|
||||||
|
condition_is_true = (std::get<int>(condVal.constantVal) != 0);
|
||||||
|
} else if (condVal.constant_type == ValueType::Float) {
|
||||||
|
condition_is_true = (std::get<float>(condVal.constantVal) != 0.0f);
|
||||||
|
}
|
||||||
|
SimplifyBranch(branchInst, condition_is_true);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找所有可达的基本块 (基于常量条件)
|
||||||
|
std::unordered_set<BasicBlock *> SCCPContext::FindReachableBlocks(Function *func) {
|
||||||
|
std::unordered_set<BasicBlock *> reachable;
|
||||||
|
std::queue<BasicBlock *> q;
|
||||||
|
|
||||||
|
if (func->getEntryBlock()) {
|
||||||
|
q.push(func->getEntryBlock());
|
||||||
|
reachable.insert(func->getEntryBlock());
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!q.empty()) {
|
||||||
|
BasicBlock *currentBB = q.front();
|
||||||
|
q.pop();
|
||||||
|
|
||||||
|
Instruction *terminator = currentBB->terminator()->get();
|
||||||
|
if (!terminator)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (terminator->isBranch()) {
|
||||||
|
if (terminator->isCondBr()) { // 检查是否是条件分支 (kCondBr)
|
||||||
|
CondBrInst *branchInst = static_cast<CondBrInst *>(terminator);
|
||||||
|
SSAPValue condVal = GetValueState(branchInst->getOperand(0));
|
||||||
|
if (condVal.state == LatticeVal::Constant) {
|
||||||
|
bool condition_is_true = false;
|
||||||
|
if (condVal.constant_type == ValueType::Integer) {
|
||||||
|
condition_is_true = (std::get<int>(condVal.constantVal) != 0);
|
||||||
|
} else if (condVal.constant_type == ValueType::Float) {
|
||||||
|
condition_is_true = (std::get<float>(condVal.constantVal) != 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (condition_is_true) {
|
||||||
|
BasicBlock *trueBlock = branchInst->getThenBlock();
|
||||||
|
if (reachable.find(trueBlock) == reachable.end()) {
|
||||||
|
reachable.insert(trueBlock);
|
||||||
|
q.push(trueBlock);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
BasicBlock *falseBlock = branchInst->getElseBlock();
|
||||||
|
if (reachable.find(falseBlock) == reachable.end()) {
|
||||||
|
reachable.insert(falseBlock);
|
||||||
|
q.push(falseBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // 条件是 Top 或 Bottom,两条路径都可达
|
||||||
|
for (auto succ : branchInst->getSuccessors()) {
|
||||||
|
if (reachable.find(succ) == reachable.end()) {
|
||||||
|
reachable.insert(succ);
|
||||||
|
q.push(succ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // 无条件分支 (kBr)
|
||||||
|
UncondBrInst *branchInst = static_cast<UncondBrInst *>(terminator);
|
||||||
|
BasicBlock *targetBlock = branchInst->getBlock();
|
||||||
|
if (reachable.find(targetBlock) == reachable.end()) {
|
||||||
|
reachable.insert(targetBlock);
|
||||||
|
q.push(targetBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (terminator->isReturn() || terminator->isUnreachable()) {
|
||||||
|
// ReturnInst 没有后继,不需要处理
|
||||||
|
// UnreachableInst 也没有后继,不需要处理
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除死块
|
||||||
|
void SCCPContext::RemoveDeadBlock(BasicBlock *bb, Function *func) {
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Removing dead block: " << bb->getName() << std::endl;
|
||||||
|
}
|
||||||
|
// 首先更新其所有前驱的终结指令,移除指向死块的边
|
||||||
|
std::vector<BasicBlock *> preds_to_update;
|
||||||
|
for (auto &pred : bb->getPredecessors()) {
|
||||||
|
if (pred != nullptr) { // 检查是否为空指针
|
||||||
|
preds_to_update.push_back(pred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (BasicBlock *pred : preds_to_update) {
|
||||||
|
if (executableBlocks.count(pred)) {
|
||||||
|
UpdateTerminator(pred, bb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除其后继的 Phi 节点的入边
|
||||||
|
std::vector<BasicBlock *> succs_to_update;
|
||||||
|
for (auto succ : bb->getSuccessors()) {
|
||||||
|
succs_to_update.push_back(succ);
|
||||||
|
}
|
||||||
|
for (BasicBlock *succ : succs_to_update) {
|
||||||
|
RemovePhiIncoming(succ, bb);
|
||||||
|
succ->removePredecessor(bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
func->removeBasicBlock(bb); // 从函数中移除基本块
|
||||||
|
}
|
||||||
|
|
||||||
|
// 简化分支(将条件分支替换为无条件分支)
|
||||||
|
void SCCPContext::SimplifyBranch(CondBrInst *brInst, bool condVal) {
|
||||||
|
BasicBlock *parentBB = brInst->getParent();
|
||||||
|
BasicBlock *trueBlock = brInst->getThenBlock();
|
||||||
|
BasicBlock *falseBlock = brInst->getElseBlock();
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Simplifying branch in " << parentBB->getName() << ": cond is " << (condVal ? "true" : "false")
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder->setPosition(parentBB, parentBB->findInstIterator(brInst));
|
||||||
|
if (condVal) { // 条件为真,跳转到真分支
|
||||||
|
builder->createUncondBrInst(trueBlock); // 插入无条件分支 kBr
|
||||||
|
SysYIROptUtils::usedelete(brInst); // 移除旧的条件分支指令
|
||||||
|
parentBB->removeSuccessor(falseBlock);
|
||||||
|
falseBlock->removePredecessor(parentBB);
|
||||||
|
RemovePhiIncoming(falseBlock, parentBB);
|
||||||
|
} else { // 条件为假,跳转到假分支
|
||||||
|
builder->createUncondBrInst(falseBlock); // 插入无条件分支 kBr
|
||||||
|
SysYIROptUtils::usedelete(brInst); // 移除旧的条件分支指令
|
||||||
|
parentBB->removeSuccessor(trueBlock);
|
||||||
|
trueBlock->removePredecessor(parentBB);
|
||||||
|
RemovePhiIncoming(trueBlock, parentBB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新前驱块的终结指令(当一个后继块被移除时)
|
||||||
|
void SCCPContext::UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc) {
|
||||||
|
Instruction *terminator = predBB->terminator()->get();
|
||||||
|
if (!terminator)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (terminator->isBranch()) {
|
||||||
|
if (terminator->isCondBr()) { // 如果是条件分支
|
||||||
|
CondBrInst *branchInst = static_cast<CondBrInst *>(terminator);
|
||||||
|
if (branchInst->getThenBlock() == removedSucc) {
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Updating cond br in " << predBB->getName() << ": True block (" << removedSucc->getName()
|
||||||
|
<< ") removed. Converting to Br to " << branchInst->getElseBlock()->getName() << std::endl;
|
||||||
|
}
|
||||||
|
builder->setPosition(predBB, predBB->findInstIterator(branchInst));
|
||||||
|
builder->createUncondBrInst(branchInst->getElseBlock());
|
||||||
|
SysYIROptUtils::usedelete(branchInst);
|
||||||
|
predBB->removeSuccessor(removedSucc);
|
||||||
|
} else if (branchInst->getElseBlock() == removedSucc) {
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Updating cond br in " << predBB->getName() << ": False block (" << removedSucc->getName()
|
||||||
|
<< ") removed. Converting to Br to " << branchInst->getThenBlock()->getName() << std::endl;
|
||||||
|
}
|
||||||
|
builder->setPosition(predBB, predBB->findInstIterator(branchInst));
|
||||||
|
builder->createUncondBrInst(branchInst->getThenBlock());
|
||||||
|
SysYIROptUtils::usedelete(branchInst);
|
||||||
|
predBB->removeSuccessor(removedSucc);
|
||||||
|
}
|
||||||
|
} else { // 无条件分支 (kBr)
|
||||||
|
UncondBrInst *branchInst = static_cast<UncondBrInst *>(terminator);
|
||||||
|
if (branchInst->getBlock() == removedSucc) {
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Updating unconditional br in " << predBB->getName() << ": Target block ("
|
||||||
|
<< removedSucc->getName() << ") removed. Replacing with Unreachable." << std::endl;
|
||||||
|
}
|
||||||
|
SysYIROptUtils::usedelete(branchInst);
|
||||||
|
predBB->removeSuccessor(removedSucc);
|
||||||
|
builder->setPosition(predBB, predBB->end());
|
||||||
|
builder->createUnreachableInst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除 Phi 节点的入边(当其前驱块被移除时)
|
||||||
|
void SCCPContext::RemovePhiIncoming(BasicBlock *phiParentBB, BasicBlock *removedPred) { // 修正 removedPred 类型
|
||||||
|
std::vector<Instruction *> insts_to_check;
|
||||||
|
for (auto &inst_ptr : phiParentBB->getInstructions()) {
|
||||||
|
insts_to_check.push_back(inst_ptr.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Instruction *inst : insts_to_check) {
|
||||||
|
if (auto phi = dynamic_cast<PhiInst *>(inst)) {
|
||||||
|
phi->delBlk(removedPred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 运行 SCCP 优化
|
||||||
|
void SCCPContext::run(Function *func, AnalysisManager &AM) {
|
||||||
|
bool changed_constant_propagation = PropagateConstants(func);
|
||||||
|
bool changed_control_flow = SimplifyControlFlow(func);
|
||||||
|
|
||||||
|
// 如果任何一个阶段修改了 IR,标记分析结果为失效
|
||||||
|
if (changed_constant_propagation || changed_control_flow) {
|
||||||
|
// AM.invalidate(); // 假设有这样的方法来使所有分析结果失效
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SCCP Pass methods
|
||||||
|
bool SCCP::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "Running SCCP on function: " << F->getName() << std::endl;
|
||||||
|
}
|
||||||
|
SCCPContext context(builder);
|
||||||
|
context.run(F, AM);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCCP::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
|
||||||
|
// analysisInvalidations.insert(nullptr); // 表示使所有默认分析失效
|
||||||
|
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树可能受影响
|
||||||
|
analysisInvalidations.insert(&LivenessAnalysisPass::ID); // 活跃性分析很可能失效
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sysy
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
#include "SysYIRCFGOpt.h"
|
#include "SysYIRCFGOpt.h"
|
||||||
#include "SysYIROptUtils.h"
|
#include "SysYIROptUtils.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
#include <queue> // 引入队列,SysYDelNoPreBLock需要
|
#include <queue> // 引入队列,SysYDelNoPreBLock需要
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
@@ -18,7 +18,6 @@ void *SysYBlockMergePass::ID = (void *)&SysYBlockMergePass::ID;
|
|||||||
void *SysYAddReturnPass::ID = (void *)&SysYAddReturnPass::ID;
|
void *SysYAddReturnPass::ID = (void *)&SysYAddReturnPass::ID;
|
||||||
void *SysYCondBr2BrPass::ID = (void *)&SysYCondBr2BrPass::ID;
|
void *SysYCondBr2BrPass::ID = (void *)&SysYCondBr2BrPass::ID;
|
||||||
|
|
||||||
|
|
||||||
// ======================================================================
|
// ======================================================================
|
||||||
// SysYCFGOptUtils: 辅助工具类,包含实际的CFG优化逻辑
|
// SysYCFGOptUtils: 辅助工具类,包含实际的CFG优化逻辑
|
||||||
// ======================================================================
|
// ======================================================================
|
||||||
@@ -33,33 +32,35 @@ bool SysYCFGOptUtils::SysYDelInstAfterBr(Function *func) {
|
|||||||
auto &instructions = basicBlock->getInstructions();
|
auto &instructions = basicBlock->getInstructions();
|
||||||
auto Branchiter = instructions.end();
|
auto Branchiter = instructions.end();
|
||||||
for (auto iter = instructions.begin(); iter != instructions.end(); ++iter) {
|
for (auto iter = instructions.begin(); iter != instructions.end(); ++iter) {
|
||||||
if ((*iter)->isTerminator()){
|
if ((*iter)->isTerminator()) {
|
||||||
Branch = true;
|
Branch = true;
|
||||||
Branchiter = iter;
|
Branchiter = iter;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Branchiter != instructions.end()) ++Branchiter;
|
if (Branchiter != instructions.end())
|
||||||
|
++Branchiter;
|
||||||
while (Branchiter != instructions.end()) {
|
while (Branchiter != instructions.end()) {
|
||||||
changed = true;
|
changed = true;
|
||||||
Branchiter = instructions.erase(Branchiter);
|
Branchiter = instructions.erase(Branchiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Branch) { // 更新前驱后继关系
|
if (Branch) { // 更新前驱后继关系
|
||||||
auto thelastinstinst = basicBlock->getInstructions().end();
|
auto thelastinstinst = basicBlock->terminator();
|
||||||
--thelastinstinst;
|
|
||||||
auto &Successors = basicBlock->getSuccessors();
|
auto &Successors = basicBlock->getSuccessors();
|
||||||
for (auto iterSucc = Successors.begin(); iterSucc != Successors.end();) {
|
for (auto iterSucc = Successors.begin(); iterSucc != Successors.end();) {
|
||||||
(*iterSucc)->removePredecessor(basicBlock.get());
|
(*iterSucc)->removePredecessor(basicBlock.get());
|
||||||
basicBlock->removeSuccessor(*iterSucc);
|
basicBlock->removeSuccessor(*iterSucc);
|
||||||
}
|
}
|
||||||
if (thelastinstinst->get()->isUnconditional()) {
|
if (thelastinstinst->get()->isUnconditional()) {
|
||||||
BasicBlock* branchBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(0));
|
auto brinst = dynamic_cast<UncondBrInst *>(thelastinstinst->get());
|
||||||
|
BasicBlock *branchBlock = dynamic_cast<BasicBlock *>(brinst->getBlock());
|
||||||
basicBlock->addSuccessor(branchBlock);
|
basicBlock->addSuccessor(branchBlock);
|
||||||
branchBlock->addPredecessor(basicBlock.get());
|
branchBlock->addPredecessor(basicBlock.get());
|
||||||
} else if (thelastinstinst->get()->isConditional()) {
|
} else if (thelastinstinst->get()->isConditional()) {
|
||||||
BasicBlock* thenBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(1));
|
auto brinst = dynamic_cast<CondBrInst *>(thelastinstinst->get());
|
||||||
BasicBlock* elseBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(2));
|
BasicBlock *thenBlock = dynamic_cast<BasicBlock *>(brinst->getThenBlock());
|
||||||
|
BasicBlock *elseBlock = dynamic_cast<BasicBlock *>(brinst->getElseBlock());
|
||||||
basicBlock->addSuccessor(thenBlock);
|
basicBlock->addSuccessor(thenBlock);
|
||||||
basicBlock->addSuccessor(elseBlock);
|
basicBlock->addSuccessor(elseBlock);
|
||||||
thenBlock->addPredecessor(basicBlock.get());
|
thenBlock->addPredecessor(basicBlock.get());
|
||||||
@@ -75,29 +76,27 @@ bool SysYCFGOptUtils::SysYDelInstAfterBr(Function *func) {
|
|||||||
bool SysYCFGOptUtils::SysYBlockMerge(Function *func) {
|
bool SysYCFGOptUtils::SysYBlockMerge(Function *func) {
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
for (auto blockiter = func->getBasicBlocks().begin();
|
for (auto blockiter = func->getBasicBlocks().begin(); blockiter != func->getBasicBlocks().end();) {
|
||||||
blockiter != func->getBasicBlocks().end();) {
|
|
||||||
if (blockiter->get()->getNumSuccessors() == 1) {
|
if (blockiter->get()->getNumSuccessors() == 1) {
|
||||||
// 如果当前块只有一个后继块
|
// 如果当前块只有一个后继块
|
||||||
// 且后继块只有一个前驱块
|
// 且后继块只有一个前驱块
|
||||||
// 则将当前块和后继块合并
|
// 则将当前块和后继块合并
|
||||||
if (((blockiter->get())->getSuccessors()[0])->getNumPredecessors() == 1) {
|
if (((blockiter->get())->getSuccessors()[0])->getNumPredecessors() == 1) {
|
||||||
// std::cout << "merge block: " << blockiter->get()->getName() << std::endl;
|
// std::cout << "merge block: " << blockiter->get()->getName() << std::endl;
|
||||||
BasicBlock* block = blockiter->get();
|
BasicBlock *block = blockiter->get();
|
||||||
BasicBlock* nextBlock = blockiter->get()->getSuccessors()[0];
|
BasicBlock *nextBlock = blockiter->get()->getSuccessors()[0];
|
||||||
// auto nextarguments = nextBlock->getArguments();
|
// auto nextarguments = nextBlock->getArguments();
|
||||||
// 删除br指令
|
// 删除br指令
|
||||||
if (block->getNumInstructions() != 0) {
|
if (block->getNumInstructions() != 0) {
|
||||||
auto thelastinstinst = block->end();
|
auto thelastinstinst = block->terminator();
|
||||||
(--thelastinstinst);
|
|
||||||
if (thelastinstinst->get()->isUnconditional()) {
|
if (thelastinstinst->get()->isUnconditional()) {
|
||||||
SysYIROptUtils::usedelete(thelastinstinst->get());
|
thelastinstinst = SysYIROptUtils::usedelete(thelastinstinst);
|
||||||
thelastinstinst = block->getInstructions().erase(thelastinstinst);
|
|
||||||
} else if (thelastinstinst->get()->isConditional()) {
|
} else if (thelastinstinst->get()->isConditional()) {
|
||||||
// 如果是条件分支,判断条件是否相同,主要优化相同布尔表达式
|
// 按道理不会走到这个分支
|
||||||
if (thelastinstinst->get()->getOperand(1)->getName() == thelastinstinst->get()->getOperand(1)->getName()) {
|
// 如果是条件分支,查看then else是否相同
|
||||||
SysYIROptUtils::usedelete(thelastinstinst->get());
|
auto brinst = dynamic_cast<CondBrInst *>(thelastinstinst->get());
|
||||||
thelastinstinst = block->getInstructions().erase(thelastinstinst);
|
if (brinst->getThenBlock() == brinst->getElseBlock()) {
|
||||||
|
thelastinstinst = SysYIROptUtils::usedelete(thelastinstinst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,315 +136,423 @@ bool SysYCFGOptUtils::SysYBlockMerge(Function *func) {
|
|||||||
|
|
||||||
// 删除无前驱块,兼容SSA后的处理
|
// 删除无前驱块,兼容SSA后的处理
|
||||||
bool SysYCFGOptUtils::SysYDelNoPreBLock(Function *func) {
|
bool SysYCFGOptUtils::SysYDelNoPreBLock(Function *func) {
|
||||||
|
bool changed = false; // 标记是否有基本块被删除
|
||||||
|
std::set<BasicBlock *> reachableBlocks; // 用于存储所有可达的基本块
|
||||||
|
std::queue<BasicBlock *> blockQueue; // BFS 遍历队列
|
||||||
|
|
||||||
bool changed = false;
|
BasicBlock *entryBlock = func->getEntryBlock();
|
||||||
|
if (entryBlock) { // 确保函数有入口块
|
||||||
for (auto &block : func->getBasicBlocks()) {
|
reachableBlocks.insert(entryBlock); // 将入口块标记为可达
|
||||||
block->setreachableFalse();
|
blockQueue.push(entryBlock); // 入口块入队
|
||||||
}
|
}
|
||||||
// 对函数基本块做一个拓扑排序,排查不可达基本块
|
// 如果没有入口块(比如一个空函数),则没有块是可达的,所有块都将被删除。
|
||||||
auto entryBlock = func->getEntryBlock();
|
|
||||||
entryBlock->setreachableTrue();
|
while (!blockQueue.empty()) { // BFS 遍历:只要队列不空
|
||||||
std::queue<BasicBlock *> blockqueue;
|
BasicBlock *currentBlock = blockQueue.front();
|
||||||
blockqueue.push(entryBlock);
|
blockQueue.pop(); // 取出当前块
|
||||||
while (!blockqueue.empty()) {
|
|
||||||
auto block = blockqueue.front();
|
for (auto &succ : currentBlock->getSuccessors()) { // 遍历当前块的所有后继
|
||||||
blockqueue.pop();
|
// 如果后继块不在 reachableBlocks 中(即尚未被访问过)
|
||||||
for (auto &succ : block->getSuccessors()) {
|
if (reachableBlocks.find(succ) == reachableBlocks.end()) {
|
||||||
if (!succ->getreachable()) {
|
reachableBlocks.insert(succ); // 标记为可达
|
||||||
succ->setreachableTrue();
|
blockQueue.push(succ); // 入队,以便继续遍历
|
||||||
blockqueue.push(succ);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除不可达基本块指令
|
std::vector<BasicBlock *> blocksToDelete; // 用于存储所有不可达的基本块
|
||||||
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end(); blockIter++) {
|
|
||||||
if (!blockIter->get()->getreachable()) {
|
for (auto &blockPtr : func->getBasicBlocks()) {
|
||||||
for (auto instIter = blockIter->get()->getInstructions().begin();
|
BasicBlock *block = blockPtr.get();
|
||||||
instIter != blockIter->get()->getInstructions().end();) {
|
// 如果当前块不在 reachableBlocks 集合中,说明它是不可达的
|
||||||
SysYIROptUtils::usedelete(instIter->get());
|
if (reachableBlocks.find(block) == reachableBlocks.end()) {
|
||||||
instIter = blockIter->get()->getInstructions().erase(instIter);
|
blocksToDelete.push_back(block); // 将其加入待删除列表
|
||||||
}
|
changed = true; // 只要找到一个不可达块,就说明函数发生了改变
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (BasicBlock *unreachableBlock : blocksToDelete) {
|
||||||
|
// 遍历不可达块中的所有指令,并删除它们
|
||||||
|
for (auto instIter = unreachableBlock->getInstructions().begin();
|
||||||
|
instIter != unreachableBlock->getInstructions().end();) {
|
||||||
|
instIter = SysYIROptUtils::usedelete(instIter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (BasicBlock *unreachableBlock : blocksToDelete) {
|
||||||
|
for (BasicBlock *succBlock : unreachableBlock->getSuccessors()) {
|
||||||
|
// 只有当后继块自身是可达的(没有被删除)时才需要处理
|
||||||
|
if (reachableBlocks.count(succBlock)) {
|
||||||
|
for (auto &phiInstPtr : succBlock->getInstructions()) {
|
||||||
|
// Phi 指令总是在基本块的开头。一旦遇到非 Phi 指令即可停止。
|
||||||
|
if (phiInstPtr->getKind() != Instruction::kPhi) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 将这个 Phi 节点中来自不可达前驱(unreachableBlock)的输入参数删除
|
||||||
|
dynamic_cast<PhiInst *>(phiInstPtr.get())->delBlk(unreachableBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();) {
|
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();) {
|
||||||
if (!blockIter->get()->getreachable()) {
|
BasicBlock *currentBlock = blockIter->get();
|
||||||
for (auto succblock : blockIter->get()->getSuccessors()) {
|
// 如果当前块不在可达块集合中,则将其从函数中移除
|
||||||
for (auto &phiinst : succblock->getInstructions()) {
|
if (reachableBlocks.find(currentBlock) == reachableBlocks.end()) {
|
||||||
if (phiinst->getKind() != Instruction::kPhi) {
|
// func->removeBasicBlock 应该返回下一个有效的迭代器
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 使用 delBlk 方法正确地删除对应于被删除基本块的传入值
|
|
||||||
dynamic_cast<PhiInst *>(phiinst.get())->delBlk(blockIter->get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 删除不可达基本块,注意迭代器不可达问题
|
|
||||||
func->removeBasicBlock((blockIter++)->get());
|
func->removeBasicBlock((blockIter++)->get());
|
||||||
changed = true;
|
|
||||||
} else {
|
} else {
|
||||||
blockIter++;
|
blockIter++; // 如果可达,则移动到下一个块
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除空块
|
bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
|
||||||
bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder) {
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
// 收集不可达基本块
|
// 步骤 1: 识别并映射所有符合“空块”定义的基本块及其目标后继
|
||||||
// 这里的不可达基本块是指没有实际指令的基本块
|
// 使用 std::map 来存储 <空块, 空块跳转目标>
|
||||||
// 当一个基本块没有实际指令例如只有phi指令和一个uncondbr指令时,也会被视作不可达
|
// 这样可以处理空块链:A -> B -> C,如果 B 是空块,A 应该跳到 C
|
||||||
auto basicBlocks = func->getBasicBlocks();
|
std::map<BasicBlock *, BasicBlock *> emptyBlockRedirectMap;
|
||||||
std::map<sysy::BasicBlock *, BasicBlock *> EmptyBlocks;
|
|
||||||
// 空块儿和后继的基本块的映射
|
// 为了避免在遍历 func->getBasicBlocks() 时修改它导致迭代器失效,
|
||||||
for (auto &basicBlock : basicBlocks) {
|
// 我们先收集所有的基本块。
|
||||||
if (basicBlock->getNumInstructions() == 0) {
|
std::vector<BasicBlock *> allBlocks;
|
||||||
if (basicBlock->getNumSuccessors() == 1) {
|
for (auto &blockPtr : func->getBasicBlocks()) {
|
||||||
EmptyBlocks[basicBlock.get()] = basicBlock->getSuccessors().front();
|
allBlocks.push_back(blockPtr.get());
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
// 如果只有phi指令和一个uncondbr。(phi)*(uncondbr)?
|
|
||||||
// 判断除了最后一个指令之外是不是只有phi指令
|
|
||||||
bool onlyPhi = true;
|
|
||||||
for (auto &inst : basicBlock->getInstructions()) {
|
|
||||||
if (!inst->isPhi() && !inst->isUnconditional()) {
|
|
||||||
onlyPhi = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(onlyPhi && basicBlock->getNumSuccessors() == 1) // 确保有后继且只有一个
|
|
||||||
EmptyBlocks[basicBlock.get()] = basicBlock->getSuccessors().front();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// 更新基本块信息,增加必要指令
|
|
||||||
for (auto &basicBlock : basicBlocks) {
|
for (BasicBlock *block : allBlocks) {
|
||||||
// 把空块转换成只有跳转指令的不可达块 (这段逻辑在优化遍中可能需要调整,这里是原样保留)
|
// 入口块通常不应该被认为是空块并删除,除非它没有实际指令且只有一个后继,
|
||||||
// 通常,DelEmptyBlock 应该在BlockMerge之后运行,如果存在完全空块,它会尝试填充一个Br指令。
|
// 但为了安全起见,通常会跳过入口块的删除。
|
||||||
// 但是,它主要目的是重定向跳转。
|
// 如果入口块是空的,它应该被合并到它的后继,但处理起来更复杂,这里先不处理入口块为空的情况
|
||||||
if (distance(basicBlock->begin(), basicBlock->end()) == 0) {
|
if (block == func->getEntryBlock()) {
|
||||||
if (basicBlock->getNumSuccessors() == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (basicBlock->getNumSuccessors() > 1) {
|
|
||||||
// 如果一个空块有多个后继,说明CFG结构有问题或者需要特殊处理,这里简单assert
|
|
||||||
assert(false && "Empty block with multiple successors found during SysYDelEmptyBlock");
|
|
||||||
}
|
|
||||||
// 这里的逻辑有点问题,如果一个块是空的,且只有一个后继,应该直接跳转到后继。
|
|
||||||
// 如果这个块最终被删除了,那么其前驱也需要重定向。
|
|
||||||
// 这个循环的目的是重定向现有的跳转指令,而不是创建新的。
|
|
||||||
// 所以下面的逻辑才是核心。
|
|
||||||
// pBuilder->setPosition(basicBlock.get(), basicBlock->end());
|
|
||||||
// pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {});
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto thelastinst = basicBlock->getInstructions().end();
|
// 检查基本块是否是空的:除了Phi指令外,只包含一个终止指令 (Terminator)
|
||||||
--thelastinst;
|
// 且该终止指令必须是无条件跳转。
|
||||||
|
// 空块必须只有一个后继才能被简化
|
||||||
// 根据br指令传递的后继块信息,跳过空块链
|
if (block->getNumSuccessors() == 1) {
|
||||||
if (thelastinst->get()->isUnconditional()) {
|
bool hasNonPhiNonTerminator = false;
|
||||||
BasicBlock* OldBrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
|
// 遍历除了最后一个指令之外的指令
|
||||||
BasicBlock *thelastBlockOld = nullptr;
|
for (auto instIter = block->getInstructions().begin(); instIter != block->getInstructions().end();) {
|
||||||
// 如果空块链表为多个块
|
// 如果是终止指令(例如 br, ret),且不是最后一个指令,则该块有问题
|
||||||
while (EmptyBlocks.count(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)))) {
|
if ((*instIter)->isTerminator() && instIter != block->terminator()) {
|
||||||
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
|
hasNonPhiNonTerminator = true;
|
||||||
thelastinst->get()->replaceOperand(0, EmptyBlocks[thelastBlockOld]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果有重定向发生
|
|
||||||
if (thelastBlockOld != nullptr) {
|
|
||||||
basicBlock->removeSuccessor(OldBrBlock);
|
|
||||||
OldBrBlock->removePredecessor(basicBlock.get());
|
|
||||||
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)));
|
|
||||||
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->addPredecessor(basicBlock.get());
|
|
||||||
changed = true; // 标记IR被修改
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (thelastBlockOld != nullptr) {
|
|
||||||
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getInstructions()) {
|
|
||||||
if (InstInNew->isPhi()) {
|
|
||||||
// 使用 delBlk 方法删除 oldBlock 对应的传入值
|
|
||||||
dynamic_cast<PhiInst *>(InstInNew.get())->delBlk(thelastBlockOld);
|
|
||||||
} else {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
// 如果不是 Phi 指令且不是终止指令
|
||||||
}
|
if (!(*instIter)->isPhi() && !(*instIter)->isTerminator()) {
|
||||||
|
hasNonPhiNonTerminator = true;
|
||||||
} else if (thelastinst->get()->getKind() == Instruction::kCondBr) {
|
break;
|
||||||
auto OldThenBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
|
}
|
||||||
auto OldElseBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2));
|
++instIter;
|
||||||
bool thenChanged = false;
|
if (!hasNonPhiNonTerminator &&
|
||||||
bool elseChanged = false;
|
instIter == block->getInstructions().end()) { // 如果块中只有 Phi 指令和一个 Terminator
|
||||||
|
// 确保最后一个指令是无条件跳转
|
||||||
|
auto lastInst = block->terminator()->get();
|
||||||
BasicBlock *thelastBlockOld = nullptr;
|
if (lastInst && lastInst->isUnconditional()) {
|
||||||
while (EmptyBlocks.count(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)))) {
|
emptyBlockRedirectMap[block] = block->getSuccessors().front();
|
||||||
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
|
|
||||||
thelastinst->get()->replaceOperand(
|
|
||||||
1, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))]);
|
|
||||||
thenChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thenChanged) {
|
|
||||||
basicBlock->removeSuccessor(OldThenBlock);
|
|
||||||
OldThenBlock->removePredecessor(basicBlock.get());
|
|
||||||
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)));
|
|
||||||
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))->addPredecessor(basicBlock.get());
|
|
||||||
changed = true; // 标记IR被修改
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理 then 和 else 分支合并的情况
|
|
||||||
if (dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)) ==
|
|
||||||
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))) {
|
|
||||||
auto thebrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
|
|
||||||
SysYIROptUtils::usedelete(thelastinst->get());
|
|
||||||
thelastinst = basicBlock->getInstructions().erase(thelastinst);
|
|
||||||
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
|
|
||||||
pBuilder->createUncondBrInst(thebrBlock, {});
|
|
||||||
changed = true; // 标记IR被修改
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thelastBlockOld != nullptr) {
|
|
||||||
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))->getInstructions()) {
|
|
||||||
if (InstInNew->isPhi()) {
|
|
||||||
// 使用 delBlk 方法删除 oldBlock 对应的传入值
|
|
||||||
dynamic_cast<PhiInst *>(InstInNew.get())->delBlk(thelastBlockOld);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
thelastBlockOld = nullptr;
|
|
||||||
while (EmptyBlocks.count(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2)))) {
|
|
||||||
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2));
|
|
||||||
thelastinst->get()->replaceOperand(
|
|
||||||
2, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))]);
|
|
||||||
elseChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elseChanged) {
|
|
||||||
basicBlock->removeSuccessor(OldElseBlock);
|
|
||||||
OldElseBlock->removePredecessor(basicBlock.get());
|
|
||||||
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2)));
|
|
||||||
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))->addPredecessor(basicBlock.get());
|
|
||||||
changed = true; // 标记IR被修改
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理 then 和 else 分支合并的情况
|
|
||||||
if (dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)) ==
|
|
||||||
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))) {
|
|
||||||
auto thebrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
|
|
||||||
SysYIROptUtils::usedelete(thelastinst->get());
|
|
||||||
thelastinst = basicBlock->getInstructions().erase(thelastinst);
|
|
||||||
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
|
|
||||||
pBuilder->createUncondBrInst(thebrBlock, {});
|
|
||||||
changed = true; // 标记IR被修改
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 如果有重定向发生
|
|
||||||
// 需要更新后继块的前驱关系
|
|
||||||
if (thelastBlockOld != nullptr) {
|
|
||||||
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))->getInstructions()) {
|
|
||||||
if (InstInNew->isPhi()) {
|
|
||||||
// 使用 delBlk 方法删除 oldBlock 对应的传入值
|
|
||||||
dynamic_cast<PhiInst *>(InstInNew.get())->delBlk(thelastBlockOld);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
// 如果不是终止指令,但有后继 (例如,末尾没有显式终止指令的块)
|
|
||||||
// 这段逻辑可能需要更严谨的CFG检查来确保正确性
|
|
||||||
if (basicBlock->getNumSuccessors() == 1) {
|
|
||||||
// 这里的逻辑似乎是想为没有terminator的块添加一个,但通常这应该在CFG构建阶段完成。
|
|
||||||
// 如果这里仍然执行,确保它符合预期。
|
|
||||||
// pBuilder->setPosition(basicBlock.get(), basicBlock->end());
|
|
||||||
// pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {});
|
|
||||||
// auto thelastinst = basicBlock->getInstructions().end();
|
|
||||||
// (--thelastinst);
|
|
||||||
// auto OldBrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
|
|
||||||
// sysy::BasicBlock *thelastBlockOld = nullptr;
|
|
||||||
// while (EmptyBlocks.find(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))) !=
|
|
||||||
// EmptyBlocks.end()) {
|
|
||||||
// thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
|
|
||||||
|
|
||||||
// thelastinst->get()->replaceOperand(
|
|
||||||
// 0, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))]);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// basicBlock->removeSuccessor(OldBrBlock);
|
|
||||||
// OldBrBlock->removePredecessor(basicBlock.get());
|
|
||||||
// basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)));
|
|
||||||
// dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->addPredecessor(basicBlock.get());
|
|
||||||
// changed = true; // 标记IR被修改
|
|
||||||
// if (thelastBlockOld != nullptr) {
|
|
||||||
// int indexphi = 0;
|
|
||||||
// for (auto &pred : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getPredecessors()) {
|
|
||||||
// if (pred == thelastBlockOld) {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// indexphi++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getInstructions()) {
|
|
||||||
// if (InstInNew->isPhi()) {
|
|
||||||
// dynamic_cast<PhiInst *>(InstInNew.get())->removeOperand(indexphi + 1);
|
|
||||||
// } else {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 真正的删除空块
|
// 步骤 2: 遍历 emptyBlockRedirectMap,处理空块链
|
||||||
for (auto iter = func->getBasicBlocks().begin(); iter != func->getBasicBlocks().end();) {
|
// 确保每个空块都直接重定向到其最终的非空后继块
|
||||||
|
for (auto const &[emptyBlock, directSucc] : emptyBlockRedirectMap) {
|
||||||
|
BasicBlock *targetBlock = directSucc;
|
||||||
|
// 沿着空块链一直找到最终的非空块目标
|
||||||
|
while (emptyBlockRedirectMap.count(targetBlock)) {
|
||||||
|
targetBlock = emptyBlockRedirectMap[targetBlock];
|
||||||
|
}
|
||||||
|
emptyBlockRedirectMap[emptyBlock] = targetBlock; // 更新映射到最终目标
|
||||||
|
}
|
||||||
|
|
||||||
if (EmptyBlocks.count(iter->get())) {
|
// 步骤 3: 遍历所有基本块,重定向其终止指令,绕过空块
|
||||||
// EntryBlock跳过
|
// 注意:这里需要再次遍历所有块,包括可能成为新目标的块
|
||||||
if (iter->get() == func->getEntryBlock()) {
|
for (BasicBlock *currentBlock : allBlocks) {
|
||||||
++iter;
|
// 如果 currentBlock 本身就是个空块,它会通过其前驱的重定向被处理,这里跳过
|
||||||
continue;
|
if (emptyBlockRedirectMap.count(currentBlock)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前块的最后一个指令(终止指令)
|
||||||
|
if (currentBlock->getInstructions().empty()) {
|
||||||
|
// 理论上,除了入口块和可能被合并的空块外,所有块都应该有终止指令
|
||||||
|
// 如果这里碰到空块,可能是逻辑错误或者需要特殊处理
|
||||||
|
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
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto instIter = iter->get()->getInstructions().begin();
|
Instruction *inst = dynamic_cast<Instruction *>(val);
|
||||||
instIter != iter->get()->getInstructions().end();) {
|
// 如果定义指令不在任何空块中,它就是最终来源
|
||||||
SysYIROptUtils::usedelete(instIter->get()); // 仅删除 use 关系
|
if (!emptyBlockRedirectMap.count(currentDefBlock)) {
|
||||||
// 显式地从基本块中删除指令并更新迭代器
|
return val;
|
||||||
instIter = iter->get()->getInstructions().erase(instIter);
|
|
||||||
}
|
}
|
||||||
// 删除不可达基本块的phi指令的操作数
|
|
||||||
for (auto &succ : iter->get()->getSuccessors()) {
|
// 如果是 Phi 指令,且它在空块中,则继续追溯其在空块链中前驱的传入值
|
||||||
for (auto &instinsucc : succ->getInstructions()) {
|
if (inst->getKind() == Instruction::kPhi) {
|
||||||
if (instinsucc->isPhi()) {
|
PhiInst *phi = dynamic_cast<PhiInst *>(inst);
|
||||||
// iter->get() 就是当前被删除的空基本块,它作为前驱连接到这里的Phi指令
|
// 查找哪个前驱是空块链中的上一个块
|
||||||
dynamic_cast<PhiInst *>(instinsucc.get())->delBlk(iter->get());
|
for (size_t i = 0; i < phi->getNumOperands(); i += 2) {
|
||||||
|
BasicBlock *incomingBlock = dynamic_cast<BasicBlock *>(phi->getOperand(i + 1));
|
||||||
|
// 检查 incomingBlock 是否是当前空块的前驱,且也在空块映射中(或就是 P)
|
||||||
|
// 找到在空块链中导致 currentDefBlock 的那个前驱块
|
||||||
|
if (emptyBlockRedirectMap.count(incomingBlock) || incomingBlock == currentBlock) {
|
||||||
|
// 递归追溯该传入值
|
||||||
|
return getUltimateSourceValue(phi->getIncomingValue(incomingBlock), incomingBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果是其他指令或者无法追溯到Phi链,则认为它在空块中产生,无法安全传播,返回null或原值
|
||||||
|
// 在严格的空块定义下,除了Phi和Terminator,不应有其他指令产生值。
|
||||||
|
return val; // Fallback: If not a Phi, or unable to trace, return itself (may be dangling)
|
||||||
|
};
|
||||||
|
|
||||||
|
auto lastInst = currentBlock->getInstructions().back().get();
|
||||||
|
|
||||||
|
if (lastInst->isUnconditional()) { // 无条件跳转
|
||||||
|
UncondBrInst *brInst = dynamic_cast<UncondBrInst *>(lastInst);
|
||||||
|
BasicBlock *oldTarget = dynamic_cast<BasicBlock *>(brInst->getBlock()); // 原始跳转目标
|
||||||
|
|
||||||
|
if (emptyBlockRedirectMap.count(oldTarget)) { // 如果目标是空块
|
||||||
|
BasicBlock *newTarget = emptyBlockRedirectMap[oldTarget]; // 获取最终目标
|
||||||
|
|
||||||
|
// 更新 CFG 关系
|
||||||
|
currentBlock->removeSuccessor(oldTarget);
|
||||||
|
oldTarget->removePredecessor(currentBlock);
|
||||||
|
|
||||||
|
brInst->replaceOperand(0, newTarget); // 更新跳转指令的操作数
|
||||||
|
currentBlock->addSuccessor(newTarget);
|
||||||
|
newTarget->addPredecessor(currentBlock);
|
||||||
|
|
||||||
|
changed = true; // 标记发生改变
|
||||||
|
|
||||||
|
for (auto &phiInstPtr : newTarget->getInstructions()) {
|
||||||
|
if (phiInstPtr->getKind() == Instruction::kPhi) {
|
||||||
|
PhiInst *phiInst = dynamic_cast<PhiInst *>(phiInstPtr.get());
|
||||||
|
BasicBlock *actualEmptyPredecessorOfS = nullptr;
|
||||||
|
for (size_t i = 0; i < phiInst->getNumOperands(); i += 2) {
|
||||||
|
BasicBlock *incomingBlock = dynamic_cast<BasicBlock *>(phiInst->getOperand(i + 1));
|
||||||
|
if (incomingBlock && emptyBlockRedirectMap.count(incomingBlock) &&
|
||||||
|
emptyBlockRedirectMap[incomingBlock] == newTarget) {
|
||||||
|
actualEmptyPredecessorOfS = incomingBlock;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actualEmptyPredecessorOfS) {
|
||||||
|
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
|
||||||
|
Value *valueFromEmptyPredecessor = phiInst->getIncomingValue(actualEmptyPredecessorOfS);
|
||||||
|
|
||||||
|
// 追溯这个值,找到它在非空块中的最终来源
|
||||||
|
// currentBlock 是 P
|
||||||
|
// oldTarget 是 E1 (链的起点)
|
||||||
|
// actualEmptyPredecessorOfS 是 En (链的终点,S 的前驱)
|
||||||
|
Value *ultimateSourceValue = getUltimateSourceValue(valueFromEmptyPredecessor, actualEmptyPredecessorOfS);
|
||||||
|
|
||||||
|
// 替换 Phi 节点的传入块和传入值
|
||||||
|
if (ultimateSourceValue) { // 确保成功追溯到有效来源
|
||||||
|
phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
|
||||||
|
} else {
|
||||||
|
assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction");
|
||||||
|
// 无法追溯到有效来源,这可能是个错误或特殊情况
|
||||||
|
// 此时可能需要移除该 Phi 项,或者插入一个 undef 值
|
||||||
|
phiInst->removeIncoming(actualEmptyPredecessorOfS);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Phi 指令通常在基本块的开头,如果不是 Phi 指令就停止检查
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func->removeBasicBlock((iter++)->get());
|
} else if (lastInst->getKind() == Instruction::kCondBr) { // 条件跳转
|
||||||
|
CondBrInst *condBrInst = dynamic_cast<CondBrInst *>(lastInst);
|
||||||
|
BasicBlock *oldThenTarget = dynamic_cast<BasicBlock *>(condBrInst->getThenBlock());
|
||||||
|
BasicBlock *oldElseTarget = dynamic_cast<BasicBlock *>(condBrInst->getElseBlock());
|
||||||
|
|
||||||
|
bool thenPathChanged = false;
|
||||||
|
bool elsePathChanged = false;
|
||||||
|
|
||||||
|
// 处理 Then 分支
|
||||||
|
if (emptyBlockRedirectMap.count(oldThenTarget)) {
|
||||||
|
BasicBlock *newThenTarget = emptyBlockRedirectMap[oldThenTarget];
|
||||||
|
condBrInst->replaceOperand(1, newThenTarget); // 更新跳转指令操作数
|
||||||
|
|
||||||
|
currentBlock->removeSuccessor(oldThenTarget);
|
||||||
|
oldThenTarget->removePredecessor(currentBlock);
|
||||||
|
currentBlock->addSuccessor(newThenTarget);
|
||||||
|
newThenTarget->addPredecessor(currentBlock);
|
||||||
|
thenPathChanged = true;
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
// 处理新 Then 目标块中的 Phi 指令
|
||||||
|
// for (auto &phiInstPtr : newThenTarget->getInstructions()) {
|
||||||
|
// if (phiInstPtr->getKind() == Instruction::kPhi) {
|
||||||
|
// dynamic_cast<PhiInst *>(phiInstPtr.get())->delBlk(oldThenTarget);
|
||||||
|
// } else {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
for (auto &phiInstPtr : newThenTarget->getInstructions()) {
|
||||||
|
if (phiInstPtr->getKind() == Instruction::kPhi) {
|
||||||
|
PhiInst *phiInst = dynamic_cast<PhiInst *>(phiInstPtr.get());
|
||||||
|
BasicBlock *actualEmptyPredecessorOfS = nullptr;
|
||||||
|
for (size_t i = 0; i < phiInst->getNumOperands(); i += 2) {
|
||||||
|
BasicBlock *incomingBlock = dynamic_cast<BasicBlock *>(phiInst->getOperand(i + 1));
|
||||||
|
if (incomingBlock && emptyBlockRedirectMap.count(incomingBlock) &&
|
||||||
|
emptyBlockRedirectMap[incomingBlock] == newThenTarget) {
|
||||||
|
actualEmptyPredecessorOfS = incomingBlock;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actualEmptyPredecessorOfS) {
|
||||||
|
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
|
||||||
|
Value *valueFromEmptyPredecessor = phiInst->getIncomingValue(actualEmptyPredecessorOfS);
|
||||||
|
|
||||||
|
// 追溯这个值,找到它在非空块中的最终来源
|
||||||
|
// currentBlock 是 P
|
||||||
|
// oldTarget 是 E1 (链的起点)
|
||||||
|
// actualEmptyPredecessorOfS 是 En (链的终点,S 的前驱)
|
||||||
|
Value *ultimateSourceValue = getUltimateSourceValue(valueFromEmptyPredecessor, actualEmptyPredecessorOfS);
|
||||||
|
|
||||||
|
// 替换 Phi 节点的传入块和传入值
|
||||||
|
if (ultimateSourceValue) { // 确保成功追溯到有效来源
|
||||||
|
phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
|
||||||
|
} else {
|
||||||
|
assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction");
|
||||||
|
// 无法追溯到有效来源,这可能是个错误或特殊情况
|
||||||
|
// 此时可能需要移除该 Phi 项,或者插入一个 undef 值
|
||||||
|
phiInst->removeIncoming(actualEmptyPredecessorOfS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理 Else 分支
|
||||||
|
if (emptyBlockRedirectMap.count(oldElseTarget)) {
|
||||||
|
BasicBlock *newElseTarget = emptyBlockRedirectMap[oldElseTarget];
|
||||||
|
condBrInst->replaceOperand(2, newElseTarget); // 更新跳转指令操作数
|
||||||
|
|
||||||
|
currentBlock->removeSuccessor(oldElseTarget);
|
||||||
|
oldElseTarget->removePredecessor(currentBlock);
|
||||||
|
currentBlock->addSuccessor(newElseTarget);
|
||||||
|
newElseTarget->addPredecessor(currentBlock);
|
||||||
|
elsePathChanged = true;
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
// 处理新 Else 目标块中的 Phi 指令
|
||||||
|
// for (auto &phiInstPtr : newElseTarget->getInstructions()) {
|
||||||
|
// if (phiInstPtr->getKind() == Instruction::kPhi) {
|
||||||
|
// dynamic_cast<PhiInst *>(phiInstPtr.get())->delBlk(oldElseTarget);
|
||||||
|
// } else {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
for (auto &phiInstPtr : newElseTarget->getInstructions()) {
|
||||||
|
if (phiInstPtr->getKind() == Instruction::kPhi) {
|
||||||
|
PhiInst *phiInst = dynamic_cast<PhiInst *>(phiInstPtr.get());
|
||||||
|
BasicBlock *actualEmptyPredecessorOfS = nullptr;
|
||||||
|
for (size_t i = 0; i < phiInst->getNumOperands(); i += 2) {
|
||||||
|
BasicBlock *incomingBlock = dynamic_cast<BasicBlock *>(phiInst->getOperand(i + 1));
|
||||||
|
if (incomingBlock && emptyBlockRedirectMap.count(incomingBlock) &&
|
||||||
|
emptyBlockRedirectMap[incomingBlock] == newElseTarget) {
|
||||||
|
actualEmptyPredecessorOfS = incomingBlock;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actualEmptyPredecessorOfS) {
|
||||||
|
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
|
||||||
|
Value *valueFromEmptyPredecessor = phiInst->getIncomingValue(actualEmptyPredecessorOfS);
|
||||||
|
|
||||||
|
// 追溯这个值,找到它在非空块中的最终来源
|
||||||
|
// currentBlock 是 P
|
||||||
|
// oldTarget 是 E1 (链的起点)
|
||||||
|
// actualEmptyPredecessorOfS 是 En (链的终点,S 的前驱)
|
||||||
|
Value *ultimateSourceValue = getUltimateSourceValue(valueFromEmptyPredecessor, actualEmptyPredecessorOfS);
|
||||||
|
|
||||||
|
// 替换 Phi 节点的传入块和传入值
|
||||||
|
if (ultimateSourceValue) { // 确保成功追溯到有效来源
|
||||||
|
phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
|
||||||
|
} else {
|
||||||
|
assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction");
|
||||||
|
// 无法追溯到有效来源,这可能是个错误或特殊情况
|
||||||
|
// 此时可能需要移除该 Phi 项,或者插入一个 undef 值
|
||||||
|
phiInst->removeIncoming(actualEmptyPredecessorOfS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 额外处理:如果条件跳转的两个分支现在指向同一个块,则可以简化为无条件跳转
|
||||||
|
if (condBrInst->getThenBlock() == condBrInst->getElseBlock()) {
|
||||||
|
BasicBlock *commonTarget = dynamic_cast<BasicBlock *>(condBrInst->getThenBlock());
|
||||||
|
SysYIROptUtils::usedelete(lastInst); // 删除旧的条件跳转指令
|
||||||
|
pBuilder->setPosition(currentBlock, currentBlock->end());
|
||||||
|
pBuilder->createUncondBrInst(commonTarget); // 插入新的无条件跳转指令
|
||||||
|
|
||||||
|
// 更安全地更新 CFG 关系
|
||||||
|
std::set<BasicBlock *> currentSuccessors;
|
||||||
|
currentSuccessors.insert(oldThenTarget);
|
||||||
|
currentSuccessors.insert(oldElseTarget);
|
||||||
|
|
||||||
|
// 移除旧的后继关系
|
||||||
|
for (BasicBlock *succ : currentSuccessors) {
|
||||||
|
currentBlock->removeSuccessor(succ);
|
||||||
|
succ->removePredecessor(currentBlock);
|
||||||
|
}
|
||||||
|
// 添加新的后继关系
|
||||||
|
currentBlock->addSuccessor(commonTarget);
|
||||||
|
commonTarget->addPredecessor(currentBlock);
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 步骤 4: 真正地删除空基本块
|
||||||
|
// 注意:只能在所有跳转和 Phi 指令都更新完毕后才能删除这些块
|
||||||
|
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();) {
|
||||||
|
BasicBlock *currentBlock = blockIter->get();
|
||||||
|
if (emptyBlockRedirectMap.count(currentBlock)) { // 如果在空块映射中
|
||||||
|
// 入口块不应该被删除,即使它符合空块定义,因为函数需要一个入口
|
||||||
|
if (currentBlock == func->getEntryBlock()) {
|
||||||
|
++blockIter;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在删除块之前,确保其内部指令被正确删除(虽然这类块指令很少)
|
||||||
|
for (auto instIter = currentBlock->getInstructions().begin();
|
||||||
|
instIter != currentBlock->getInstructions().end();) {
|
||||||
|
instIter = SysYIROptUtils::usedelete(instIter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除块
|
||||||
|
func->removeBasicBlock((blockIter++)->get());
|
||||||
changed = true;
|
changed = true;
|
||||||
} else {
|
} else {
|
||||||
++iter;
|
++blockIter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,7 +560,7 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 如果函数没有返回指令,则添加一个默认返回指令(主要解决void函数没有返回指令的问题)
|
// 如果函数没有返回指令,则添加一个默认返回指令(主要解决void函数没有返回指令的问题)
|
||||||
bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder* pBuilder) {
|
bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder *pBuilder) {
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
auto basicBlocks = func->getBasicBlocks();
|
auto basicBlocks = func->getBasicBlocks();
|
||||||
for (auto &block : basicBlocks) {
|
for (auto &block : basicBlocks) {
|
||||||
@@ -467,7 +574,8 @@ bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder* pBuilder) {
|
|||||||
auto thelastinst = block->getInstructions().end();
|
auto thelastinst = block->getInstructions().end();
|
||||||
--thelastinst;
|
--thelastinst;
|
||||||
if (thelastinst->get()->getKind() != Instruction::kReturn) {
|
if (thelastinst->get()->getKind() != Instruction::kReturn) {
|
||||||
// std::cout << "Warning: Function " << func->getName() << " has no return instruction, adding default return." << std::endl;
|
// std::cout << "Warning: Function " << func->getName() << " has no return instruction, adding default
|
||||||
|
// return." << std::endl;
|
||||||
|
|
||||||
pBuilder->setPosition(block.get(), block->end());
|
pBuilder->setPosition(block.get(), block->end());
|
||||||
// TODO: 如果int float函数缺少返回值是否需要报错
|
// TODO: 如果int float函数缺少返回值是否需要报错
|
||||||
@@ -491,18 +599,18 @@ bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder* pBuilder) {
|
|||||||
// 主要针对已知条件值的分支转换为无条件分支
|
// 主要针对已知条件值的分支转换为无条件分支
|
||||||
// 例如 if (cond) { ... } else { ... } 中的 cond 已经
|
// 例如 if (cond) { ... } else { ... } 中的 cond 已经
|
||||||
// 确定为 true 或 false 的情况
|
// 确定为 true 或 false 的情况
|
||||||
bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) {
|
bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder *pBuilder) {
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
for (auto &basicblock : func->getBasicBlocks()) {
|
for (auto &basicblock : func->getBasicBlocks()) {
|
||||||
if (basicblock->getNumInstructions() == 0)
|
if (basicblock->getNumInstructions() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto thelast = basicblock->getInstructions().end();
|
auto thelast = basicblock->terminator();
|
||||||
--thelast;
|
|
||||||
|
|
||||||
if (thelast->get()->isConditional()){
|
if (thelast->get()->isConditional()) {
|
||||||
ConstantValue *constOperand = dynamic_cast<ConstantValue *>(thelast->get()->getOperand(0));
|
auto condBrInst = dynamic_cast<CondBrInst *>(thelast->get());
|
||||||
|
ConstantValue *constOperand = dynamic_cast<ConstantValue *>(condBrInst->getCondition());
|
||||||
std::string opname;
|
std::string opname;
|
||||||
int constint = 0;
|
int constint = 0;
|
||||||
float constfloat = 0.0F;
|
float constfloat = 0.0F;
|
||||||
@@ -521,14 +629,13 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) {
|
|||||||
if (constfloat_Use || constint_Use) {
|
if (constfloat_Use || constint_Use) {
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
auto thenBlock = dynamic_cast<BasicBlock *>(thelast->get()->getOperand(1));
|
auto thenBlock = dynamic_cast<BasicBlock *>(condBrInst->getThenBlock());
|
||||||
auto elseBlock = dynamic_cast<BasicBlock *>(thelast->get()->getOperand(2));
|
auto elseBlock = dynamic_cast<BasicBlock *>(condBrInst->getElseBlock());
|
||||||
SysYIROptUtils::usedelete(thelast->get());
|
thelast = SysYIROptUtils::usedelete(thelast);
|
||||||
thelast = basicblock->getInstructions().erase(thelast);
|
|
||||||
if ((constfloat_Use && constfloat == 1.0F) || (constint_Use && constint == 1)) {
|
if ((constfloat_Use && constfloat == 1.0F) || (constint_Use && constint == 1)) {
|
||||||
// cond为true或非0
|
// cond为true或非0
|
||||||
pBuilder->setPosition(basicblock.get(), basicblock->end());
|
pBuilder->setPosition(basicblock.get(), basicblock->end());
|
||||||
pBuilder->createUncondBrInst(thenBlock, {});
|
pBuilder->createUncondBrInst(thenBlock);
|
||||||
|
|
||||||
// 更新CFG关系
|
// 更新CFG关系
|
||||||
basicblock->removeSuccessor(elseBlock);
|
basicblock->removeSuccessor(elseBlock);
|
||||||
@@ -540,13 +647,13 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值
|
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值
|
||||||
dynamic_cast<PhiInst *>(phiinst.get())->delBlk(basicblock.get());
|
dynamic_cast<PhiInst *>(phiinst.get())->removeIncoming(basicblock.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else { // cond为false或0
|
} else { // cond为false或0
|
||||||
|
|
||||||
pBuilder->setPosition(basicblock.get(), basicblock->end());
|
pBuilder->setPosition(basicblock.get(), basicblock->end());
|
||||||
pBuilder->createUncondBrInst(elseBlock, {});
|
pBuilder->createUncondBrInst(elseBlock);
|
||||||
|
|
||||||
// 更新CFG关系
|
// 更新CFG关系
|
||||||
basicblock->removeSuccessor(thenBlock);
|
basicblock->removeSuccessor(thenBlock);
|
||||||
@@ -558,9 +665,8 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值
|
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值
|
||||||
dynamic_cast<PhiInst *>(phiinst.get())->delBlk(basicblock.get());
|
dynamic_cast<PhiInst *>(phiinst.get())->removeIncoming(basicblock.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -573,28 +679,28 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) {
|
|||||||
// 独立的CFG优化遍的实现
|
// 独立的CFG优化遍的实现
|
||||||
// ======================================================================
|
// ======================================================================
|
||||||
|
|
||||||
bool SysYDelInstAfterBrPass::runOnFunction(Function *F, AnalysisManager& AM) {
|
bool SysYDelInstAfterBrPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||||
return SysYCFGOptUtils::SysYDelInstAfterBr(F);
|
return SysYCFGOptUtils::SysYDelInstAfterBr(F);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SysYDelEmptyBlockPass::runOnFunction(Function *F, AnalysisManager& AM) {
|
bool SysYDelEmptyBlockPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||||
return SysYCFGOptUtils::SysYDelEmptyBlock(F, pBuilder);
|
return SysYCFGOptUtils::SysYDelEmptyBlock(F, pBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SysYDelNoPreBLockPass::runOnFunction(Function *F, AnalysisManager& AM) {
|
bool SysYDelNoPreBLockPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||||
return SysYCFGOptUtils::SysYDelNoPreBLock(F);
|
return SysYCFGOptUtils::SysYDelNoPreBLock(F);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SysYBlockMergePass::runOnFunction(Function *F, AnalysisManager& AM) {
|
bool SysYBlockMergePass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||||
return SysYCFGOptUtils::SysYBlockMerge(F);
|
return SysYCFGOptUtils::SysYBlockMerge(F);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SysYAddReturnPass::runOnFunction(Function *F, AnalysisManager& AM) {
|
bool SysYAddReturnPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||||
return SysYCFGOptUtils::SysYAddReturn(F, pBuilder);
|
return SysYCFGOptUtils::SysYAddReturn(F, pBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SysYCondBr2BrPass::runOnFunction(Function *F, AnalysisManager& AM) {
|
bool SysYCondBr2BrPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||||
return SysYCFGOptUtils::SysYCondBr2Br(F, pBuilder);
|
return SysYCFGOptUtils::SysYCondBr2Br(F, pBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sysy
|
} // namespace sysy
|
||||||
@@ -5,6 +5,9 @@
|
|||||||
#include "DCE.h"
|
#include "DCE.h"
|
||||||
#include "Mem2Reg.h"
|
#include "Mem2Reg.h"
|
||||||
#include "Reg2Mem.h"
|
#include "Reg2Mem.h"
|
||||||
|
#include "SCCP.h"
|
||||||
|
#include "BuildCFG.h"
|
||||||
|
#include "LargeArrayToGlobal.h"
|
||||||
#include "Pass.h"
|
#include "Pass.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
@@ -34,10 +37,13 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
|||||||
3. 添加优化passid
|
3. 添加优化passid
|
||||||
*/
|
*/
|
||||||
// 注册分析遍
|
// 注册分析遍
|
||||||
registerAnalysisPass<sysy::DominatorTreeAnalysisPass>();
|
registerAnalysisPass<DominatorTreeAnalysisPass>();
|
||||||
registerAnalysisPass<sysy::LivenessAnalysisPass>();
|
registerAnalysisPass<LivenessAnalysisPass>();
|
||||||
|
|
||||||
// 注册优化遍
|
// 注册优化遍
|
||||||
|
registerOptimizationPass<BuildCFG>();
|
||||||
|
registerOptimizationPass<LargeArrayToGlobalPass>();
|
||||||
|
|
||||||
registerOptimizationPass<SysYDelInstAfterBrPass>();
|
registerOptimizationPass<SysYDelInstAfterBrPass>();
|
||||||
registerOptimizationPass<SysYDelNoPreBLockPass>();
|
registerOptimizationPass<SysYDelNoPreBLockPass>();
|
||||||
registerOptimizationPass<SysYBlockMergePass>();
|
registerOptimizationPass<SysYBlockMergePass>();
|
||||||
@@ -50,11 +56,23 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
|||||||
registerOptimizationPass<Mem2Reg>(builderIR);
|
registerOptimizationPass<Mem2Reg>(builderIR);
|
||||||
registerOptimizationPass<Reg2Mem>(builderIR);
|
registerOptimizationPass<Reg2Mem>(builderIR);
|
||||||
|
|
||||||
|
registerOptimizationPass<SCCP>(builderIR);
|
||||||
|
|
||||||
if (optLevel >= 1) {
|
if (optLevel >= 1) {
|
||||||
//经过设计安排优化遍的执行顺序以及执行逻辑
|
//经过设计安排优化遍的执行顺序以及执行逻辑
|
||||||
if (DEBUG) std::cout << "Applying -O1 optimizations.\n";
|
if (DEBUG) std::cout << "Applying -O1 optimizations.\n";
|
||||||
if (DEBUG) std::cout << "--- Running custom optimization sequence ---\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->clearPasses();
|
||||||
this->addPass(&SysYDelInstAfterBrPass::ID);
|
this->addPass(&SysYDelInstAfterBrPass::ID);
|
||||||
this->addPass(&SysYDelNoPreBLockPass::ID);
|
this->addPass(&SysYDelNoPreBLockPass::ID);
|
||||||
@@ -87,6 +105,15 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
|||||||
printPasses();
|
printPasses();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->clearPasses();
|
||||||
|
this->addPass(&SCCP::ID);
|
||||||
|
this->run();
|
||||||
|
|
||||||
|
if(DEBUG) {
|
||||||
|
std::cout << "=== IR After SCCP Optimizations ===\n";
|
||||||
|
printPasses();
|
||||||
|
}
|
||||||
|
|
||||||
this->clearPasses();
|
this->clearPasses();
|
||||||
this->addPass(&Reg2Mem::ID);
|
this->addPass(&Reg2Mem::ID);
|
||||||
this->run();
|
this->run();
|
||||||
|
|||||||
@@ -15,6 +15,29 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
namespace sysy {
|
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};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// std::vector<Value*> BinaryValueStack; ///< 用于存储value的栈
|
// std::vector<Value*> BinaryValueStack; ///< 用于存储value的栈
|
||||||
// std::vector<int> BinaryOpStack; ///< 用于存储二元表达式的操作符栈
|
// std::vector<int> BinaryOpStack; ///< 用于存储二元表达式的操作符栈
|
||||||
@@ -249,7 +272,26 @@ void SysYIRGenerator::compute() {
|
|||||||
case BinaryOp::ADD: resultValue = builder.createAddInst(lhs, rhs); break;
|
case BinaryOp::ADD: resultValue = builder.createAddInst(lhs, rhs); break;
|
||||||
case BinaryOp::SUB: resultValue = builder.createSubInst(lhs, rhs); break;
|
case BinaryOp::SUB: resultValue = builder.createSubInst(lhs, rhs); break;
|
||||||
case BinaryOp::MUL: resultValue = builder.createMulInst(lhs, rhs); break;
|
case BinaryOp::MUL: resultValue = builder.createMulInst(lhs, rhs); break;
|
||||||
case BinaryOp::DIV: resultValue = builder.createDivInst(lhs, rhs); break;
|
case BinaryOp::DIV: {
|
||||||
|
ConstantInteger *rhsConst = dynamic_cast<ConstantInteger *>(rhs);
|
||||||
|
if (rhsConst) {
|
||||||
|
int divisor = rhsConst->getInt();
|
||||||
|
if (divisor > 0 && (divisor & (divisor - 1)) == 0) {
|
||||||
|
int shift = 0;
|
||||||
|
int temp = divisor;
|
||||||
|
while (temp > 1) {
|
||||||
|
temp >>= 1;
|
||||||
|
shift++;
|
||||||
|
}
|
||||||
|
resultValue = builder.createSRAInst(lhs, ConstantInteger::get(shift));
|
||||||
|
} else {
|
||||||
|
resultValue = builder.createDivInst(lhs, rhs);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resultValue = builder.createDivInst(lhs, rhs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case BinaryOp::MOD: resultValue = builder.createRemInst(lhs, rhs); break;
|
case BinaryOp::MOD: resultValue = builder.createRemInst(lhs, rhs); break;
|
||||||
}
|
}
|
||||||
} else if (commonType == Type::getFloatType()) {
|
} else if (commonType == Type::getFloatType()) {
|
||||||
@@ -533,7 +575,7 @@ std::any SysYIRGenerator::visitGlobalConstDecl(SysYParser::GlobalConstDeclContex
|
|||||||
if (!dims.empty()) { // 如果有维度,说明是数组
|
if (!dims.empty()) { // 如果有维度,说明是数组
|
||||||
variableType = buildArrayType(type, dims); // 构建完整的 ArrayType
|
variableType = buildArrayType(type, dims); // 构建完整的 ArrayType
|
||||||
}
|
}
|
||||||
module->createConstVar(name, Type::getPointerType(variableType), values, dims);
|
module->createConstVar(name, Type::getPointerType(variableType), values);
|
||||||
}
|
}
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
@@ -562,7 +604,7 @@ std::any SysYIRGenerator::visitGlobalVarDecl(SysYParser::GlobalVarDeclContext *c
|
|||||||
if (!dims.empty()) { // 如果有维度,说明是数组
|
if (!dims.empty()) { // 如果有维度,说明是数组
|
||||||
variableType = buildArrayType(type, dims); // 构建完整的 ArrayType
|
variableType = buildArrayType(type, dims); // 构建完整的 ArrayType
|
||||||
}
|
}
|
||||||
module->createGlobalValue(name, Type::getPointerType(variableType), dims, values);
|
module->createGlobalValue(name, Type::getPointerType(variableType), values);
|
||||||
}
|
}
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
@@ -586,7 +628,7 @@ std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext *ctx) {
|
|||||||
|
|
||||||
// 显式地为局部常量在栈上分配空间
|
// 显式地为局部常量在栈上分配空间
|
||||||
// alloca 的类型将是指针指向常量类型,例如 `int*` 或 `int[2][3]*`
|
// alloca 的类型将是指针指向常量类型,例如 `int*` 或 `int[2][3]*`
|
||||||
AllocaInst *alloca = builder.createAllocaInst(Type::getPointerType(variableType), {}, name);
|
AllocaInst *alloca = builder.createAllocaInst(Type::getPointerType(variableType), name);
|
||||||
|
|
||||||
ArrayValueTree *root = std::any_cast<ArrayValueTree *>(constDef->constInitVal()->accept(this));
|
ArrayValueTree *root = std::any_cast<ArrayValueTree *>(constDef->constInitVal()->accept(this));
|
||||||
ValueCounter values;
|
ValueCounter values;
|
||||||
@@ -653,7 +695,44 @@ std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext *ctx) {
|
|||||||
Value *currentValue = counterValues[k];
|
Value *currentValue = counterValues[k];
|
||||||
unsigned currentRepeatNum = counterNumbers[k];
|
unsigned currentRepeatNum = counterNumbers[k];
|
||||||
|
|
||||||
|
// 检查是否是0,并且重复次数足够大(例如 >16),才用 memset
|
||||||
|
if (ConstantInteger *constInt = dynamic_cast<ConstantInteger *>(currentValue)) {
|
||||||
|
if (constInt->getInt() == 0 && currentRepeatNum >= 16) { // 阈值可调整(如16、32等)
|
||||||
|
// 计算 memset 的起始地址(基于当前线性偏移量)
|
||||||
|
std::vector<Value *> memsetStartIndices;
|
||||||
|
int tempLinearIndex = linearIndexOffset;
|
||||||
|
|
||||||
|
// 将线性索引转换为多维索引
|
||||||
|
for (int dimIdx = dimSizes.size() - 1; dimIdx >= 0; --dimIdx) {
|
||||||
|
memsetStartIndices.insert(memsetStartIndices.begin(),
|
||||||
|
ConstantInteger::get(static_cast<int>(tempLinearIndex % dimSizes[dimIdx])));
|
||||||
|
tempLinearIndex /= dimSizes[dimIdx];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造 GEP 计算 memset 的起始地址
|
||||||
|
std::vector<Value *> gepIndicesForMemset;
|
||||||
|
gepIndicesForMemset.push_back(ConstantInteger::get(0)); // 跳过 alloca 类型
|
||||||
|
gepIndicesForMemset.insert(gepIndicesForMemset.end(), memsetStartIndices.begin(),
|
||||||
|
memsetStartIndices.end());
|
||||||
|
|
||||||
|
Value *memsetPtr = builder.createGetElementPtrInst(alloca, gepIndicesForMemset);
|
||||||
|
|
||||||
|
// 计算 memset 的字节数 = 元素个数 × 元素大小
|
||||||
|
Type *elementType = type;;
|
||||||
|
uint64_t elementSize = elementType->getSize();
|
||||||
|
Value *size = ConstantInteger::get(currentRepeatNum * elementSize);
|
||||||
|
|
||||||
|
// 生成 memset 指令(假设你的 IRBuilder 有 createMemset 方法)
|
||||||
|
builder.createMemsetInst(memsetPtr, ConstantInteger::get(0), size, ConstantInteger::get(0));
|
||||||
|
|
||||||
|
// 跳过这些已处理的0
|
||||||
|
linearIndexOffset += currentRepeatNum;
|
||||||
|
continue; // 直接进入下一次循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < currentRepeatNum; ++i) {
|
for (unsigned i = 0; i < currentRepeatNum; ++i) {
|
||||||
|
// 对于非零值,生成对应的 store 指令
|
||||||
std::vector<Value *> currentIndices;
|
std::vector<Value *> currentIndices;
|
||||||
int tempLinearIndex = linearIndexOffset + i; // 使用偏移量和当前重复次数内的索引
|
int tempLinearIndex = linearIndexOffset + i; // 使用偏移量和当前重复次数内的索引
|
||||||
|
|
||||||
@@ -707,7 +786,7 @@ std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx) {
|
|||||||
// 对于数组,alloca 的类型将是指针指向数组类型,例如 `int[2][3]*`
|
// 对于数组,alloca 的类型将是指针指向数组类型,例如 `int[2][3]*`
|
||||||
// 对于标量,alloca 的类型将是指针指向标量类型,例如 `int*`
|
// 对于标量,alloca 的类型将是指针指向标量类型,例如 `int*`
|
||||||
AllocaInst* alloca =
|
AllocaInst* alloca =
|
||||||
builder.createAllocaInst(Type::getPointerType(variableType), {}, name);
|
builder.createAllocaInst(Type::getPointerType(variableType), name);
|
||||||
|
|
||||||
if (varDef->initVal() != nullptr) {
|
if (varDef->initVal() != nullptr) {
|
||||||
ValueCounter values;
|
ValueCounter values;
|
||||||
@@ -764,36 +843,70 @@ std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx) {
|
|||||||
|
|
||||||
int linearIndexOffset = 0; // 用于追踪当前处理的线性索引的偏移量
|
int linearIndexOffset = 0; // 用于追踪当前处理的线性索引的偏移量
|
||||||
for (int k = 0; k < counterValues.size(); ++k) {
|
for (int k = 0; k < counterValues.size(); ++k) {
|
||||||
// 当前 Value 的值和重复次数
|
// 当前 Value 的值和重复次数
|
||||||
Value* currentValue = counterValues[k];
|
Value *currentValue = counterValues[k];
|
||||||
unsigned currentRepeatNum = counterNumbers[k];
|
unsigned currentRepeatNum = counterNumbers[k];
|
||||||
|
// 检查是否是0,并且重复次数足够大(例如 >16),才用 memset
|
||||||
|
if (ConstantInteger *constInt = dynamic_cast<ConstantInteger *>(currentValue)) {
|
||||||
|
if (constInt->getInt() == 0 && currentRepeatNum >= 16) { // 阈值可调整(如16、32等)
|
||||||
|
// 计算 memset 的起始地址(基于当前线性偏移量)
|
||||||
|
std::vector<Value *> memsetStartIndices;
|
||||||
|
int tempLinearIndex = linearIndexOffset;
|
||||||
|
|
||||||
for (unsigned i = 0; i < currentRepeatNum; ++i) {
|
// 将线性索引转换为多维索引
|
||||||
std::vector<Value *> currentIndices;
|
for (int dimIdx = dimSizes.size() - 1; dimIdx >= 0; --dimIdx) {
|
||||||
int tempLinearIndex = linearIndexOffset + i; // 使用偏移量和当前重复次数内的索引
|
memsetStartIndices.insert(memsetStartIndices.begin(),
|
||||||
|
ConstantInteger::get(static_cast<int>(tempLinearIndex % dimSizes[dimIdx])));
|
||||||
|
tempLinearIndex /= dimSizes[dimIdx];
|
||||||
|
}
|
||||||
|
|
||||||
// 将线性索引转换为多维索引
|
// 构造 GEP 计算 memset 的起始地址
|
||||||
for (int dimIdx = dimSizes.size() - 1; dimIdx >= 0; --dimIdx) {
|
std::vector<Value *> gepIndicesForMemset;
|
||||||
currentIndices.insert(currentIndices.begin(),
|
gepIndicesForMemset.push_back(ConstantInteger::get(0)); // 跳过 alloca 类型
|
||||||
ConstantInteger::get(static_cast<int>(tempLinearIndex % dimSizes[dimIdx])));
|
gepIndicesForMemset.insert(gepIndicesForMemset.end(), memsetStartIndices.begin(),
|
||||||
tempLinearIndex /= dimSizes[dimIdx];
|
memsetStartIndices.end());
|
||||||
}
|
|
||||||
|
|
||||||
// 对于局部数组,alloca 本身就是 GEP 的基指针。
|
Value *memsetPtr = builder.createGetElementPtrInst(alloca, gepIndicesForMemset);
|
||||||
// GEP 的第一个索引必须是 0,用于“步过”整个数组。
|
|
||||||
std::vector<Value*> gepIndicesForInit;
|
|
||||||
gepIndicesForInit.push_back(ConstantInteger::get(0));
|
|
||||||
gepIndicesForInit.insert(gepIndicesForInit.end(), currentIndices.begin(), currentIndices.end());
|
|
||||||
|
|
||||||
// 计算元素的地址
|
// 计算 memset 的字节数 = 元素个数 × 元素大小
|
||||||
Value* elementAddress = getGEPAddressInst(alloca, gepIndicesForInit);
|
Type *elementType = type;
|
||||||
// 生成 store 指令
|
;
|
||||||
builder.createStoreInst(currentValue, elementAddress);
|
uint64_t elementSize = elementType->getSize();
|
||||||
|
Value *size = ConstantInteger::get(currentRepeatNum * elementSize);
|
||||||
|
|
||||||
|
// 生成 memset 指令(假设你的 IRBuilder 有 createMemset 方法)
|
||||||
|
builder.createMemsetInst(memsetPtr, ConstantInteger::get(0), size, ConstantInteger::get(0));
|
||||||
|
|
||||||
|
// 跳过这些已处理的0
|
||||||
|
linearIndexOffset += currentRepeatNum;
|
||||||
|
continue; // 直接进入下一次循环
|
||||||
}
|
}
|
||||||
// 更新线性索引偏移量,以便下一次迭代从正确的位置开始
|
}
|
||||||
linearIndexOffset += currentRepeatNum;
|
for (unsigned i = 0; i < currentRepeatNum; ++i) {
|
||||||
}
|
std::vector<Value *> currentIndices;
|
||||||
|
int tempLinearIndex = linearIndexOffset + i; // 使用偏移量和当前重复次数内的索引
|
||||||
|
|
||||||
|
// 将线性索引转换为多维索引
|
||||||
|
for (int dimIdx = dimSizes.size() - 1; dimIdx >= 0; --dimIdx) {
|
||||||
|
currentIndices.insert(currentIndices.begin(),
|
||||||
|
ConstantInteger::get(static_cast<int>(tempLinearIndex % dimSizes[dimIdx])));
|
||||||
|
tempLinearIndex /= dimSizes[dimIdx];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对于局部数组,alloca 本身就是 GEP 的基指针。
|
||||||
|
// GEP 的第一个索引必须是 0,用于“步过”整个数组。
|
||||||
|
std::vector<Value *> gepIndicesForInit;
|
||||||
|
gepIndicesForInit.push_back(ConstantInteger::get(0));
|
||||||
|
gepIndicesForInit.insert(gepIndicesForInit.end(), currentIndices.begin(), currentIndices.end());
|
||||||
|
|
||||||
|
// 计算元素的地址
|
||||||
|
Value *elementAddress = getGEPAddressInst(alloca, gepIndicesForInit);
|
||||||
|
// 生成 store 指令
|
||||||
|
builder.createStoreInst(currentValue, elementAddress);
|
||||||
|
}
|
||||||
|
// 更新线性索引偏移量,以便下一次迭代从正确的位置开始
|
||||||
|
linearIndexOffset += currentRepeatNum;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -895,7 +1008,7 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
|
|||||||
currentParamDims.push_back(ConstantInteger::get(-1)); // 标记第一个维度为未知
|
currentParamDims.push_back(ConstantInteger::get(-1)); // 标记第一个维度为未知
|
||||||
for (const auto &exp : param->exp()) {
|
for (const auto &exp : param->exp()) {
|
||||||
// 访问表达式以获取维度大小,这些维度必须是常量
|
// 访问表达式以获取维度大小,这些维度必须是常量
|
||||||
Value* dimVal = std::any_cast<Value *>(visitExp(exp));
|
Value* dimVal = computeExp(exp);
|
||||||
// 确保维度是常量整数,否则 buildArrayType 会断言失败
|
// 确保维度是常量整数,否则 buildArrayType 会断言失败
|
||||||
assert(dynamic_cast<ConstantInteger*>(dimVal) && "Array dimension in parameter must be a constant integer!");
|
assert(dynamic_cast<ConstantInteger*>(dimVal) && "Array dimension in parameter must be a constant integer!");
|
||||||
currentParamDims.push_back(dimVal);
|
currentParamDims.push_back(dimVal);
|
||||||
@@ -950,7 +1063,7 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
|
|||||||
auto funcArgs = function->getArguments();
|
auto funcArgs = function->getArguments();
|
||||||
std::vector<AllocaInst *> allocas;
|
std::vector<AllocaInst *> allocas;
|
||||||
for (int i = 0; i < paramActualTypes.size(); ++i) {
|
for (int i = 0; i < paramActualTypes.size(); ++i) {
|
||||||
AllocaInst *alloca = builder.createAllocaInst(Type::getPointerType(paramActualTypes[i]), {}, paramNames[i]);
|
AllocaInst *alloca = builder.createAllocaInst(Type::getPointerType(paramActualTypes[i]), paramNames[i]);
|
||||||
allocas.push_back(alloca);
|
allocas.push_back(alloca);
|
||||||
module->addVariable(paramNames[i], alloca);
|
module->addVariable(paramNames[i], alloca);
|
||||||
}
|
}
|
||||||
@@ -965,7 +1078,8 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
|
|||||||
BasicBlock* funcBodyEntry = function->addBasicBlock("funcBodyEntry_" + name);
|
BasicBlock* funcBodyEntry = function->addBasicBlock("funcBodyEntry_" + name);
|
||||||
|
|
||||||
// 从 entryBB 无条件跳转到 funcBodyEntry
|
// 从 entryBB 无条件跳转到 funcBodyEntry
|
||||||
builder.createUncondBrInst(funcBodyEntry, {});
|
builder.createUncondBrInst(funcBodyEntry);
|
||||||
|
BasicBlock::conectBlocks(entry, funcBodyEntry); // 连接 entryBB 和 funcBodyEntry
|
||||||
builder.setPosition(funcBodyEntry,funcBodyEntry->end()); // 将插入点设置到 funcBodyEntry
|
builder.setPosition(funcBodyEntry,funcBodyEntry->end()); // 将插入点设置到 funcBodyEntry
|
||||||
|
|
||||||
for (auto item : ctx->blockStmt()->blockItem()) {
|
for (auto item : ctx->blockStmt()->blockItem()) {
|
||||||
@@ -1141,7 +1255,7 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
|
|||||||
ctx->stmt(0)->accept(this);
|
ctx->stmt(0)->accept(this);
|
||||||
module->leaveScope();
|
module->leaveScope();
|
||||||
}
|
}
|
||||||
builder.createUncondBrInst(exitBlock, {});
|
builder.createUncondBrInst(exitBlock);
|
||||||
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
|
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
|
||||||
|
|
||||||
labelstring << "if_else.L" << builder.getLabelIndex();
|
labelstring << "if_else.L" << builder.getLabelIndex();
|
||||||
@@ -1158,7 +1272,7 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
|
|||||||
ctx->stmt(1)->accept(this);
|
ctx->stmt(1)->accept(this);
|
||||||
module->leaveScope();
|
module->leaveScope();
|
||||||
}
|
}
|
||||||
builder.createUncondBrInst(exitBlock, {});
|
builder.createUncondBrInst(exitBlock);
|
||||||
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
|
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
|
||||||
|
|
||||||
labelstring << "if_exit.L" << builder.getLabelIndex();
|
labelstring << "if_exit.L" << builder.getLabelIndex();
|
||||||
@@ -1188,7 +1302,7 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
|
|||||||
ctx->stmt(0)->accept(this);
|
ctx->stmt(0)->accept(this);
|
||||||
module->leaveScope();
|
module->leaveScope();
|
||||||
}
|
}
|
||||||
builder.createUncondBrInst(exitBlock, {});
|
builder.createUncondBrInst(exitBlock);
|
||||||
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
|
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
|
||||||
|
|
||||||
labelstring << "if_exit.L" << builder.getLabelIndex();
|
labelstring << "if_exit.L" << builder.getLabelIndex();
|
||||||
@@ -1210,7 +1324,7 @@ std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
|
|||||||
labelstring << "while_head.L" << builder.getLabelIndex();
|
labelstring << "while_head.L" << builder.getLabelIndex();
|
||||||
BasicBlock *headBlock = function->addBasicBlock(labelstring.str());
|
BasicBlock *headBlock = function->addBasicBlock(labelstring.str());
|
||||||
labelstring.str("");
|
labelstring.str("");
|
||||||
builder.createUncondBrInst(headBlock, {});
|
builder.createUncondBrInst(headBlock);
|
||||||
BasicBlock::conectBlocks(curBlock, headBlock);
|
BasicBlock::conectBlocks(curBlock, headBlock);
|
||||||
builder.setPosition(headBlock, headBlock->end());
|
builder.setPosition(headBlock, headBlock->end());
|
||||||
|
|
||||||
@@ -1243,7 +1357,7 @@ std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
|
|||||||
module->leaveScope();
|
module->leaveScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.createUncondBrInst(headBlock, {});
|
builder.createUncondBrInst(headBlock);
|
||||||
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
|
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
|
||||||
builder.popBreakBlock();
|
builder.popBreakBlock();
|
||||||
builder.popContinueBlock();
|
builder.popContinueBlock();
|
||||||
@@ -1259,14 +1373,14 @@ std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
|
|||||||
|
|
||||||
std::any SysYIRGenerator::visitBreakStmt(SysYParser::BreakStmtContext *ctx) {
|
std::any SysYIRGenerator::visitBreakStmt(SysYParser::BreakStmtContext *ctx) {
|
||||||
BasicBlock* breakBlock = builder.getBreakBlock();
|
BasicBlock* breakBlock = builder.getBreakBlock();
|
||||||
builder.createUncondBrInst(breakBlock, {});
|
builder.createUncondBrInst(breakBlock);
|
||||||
BasicBlock::conectBlocks(builder.getBasicBlock(), breakBlock);
|
BasicBlock::conectBlocks(builder.getBasicBlock(), breakBlock);
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any SysYIRGenerator::visitContinueStmt(SysYParser::ContinueStmtContext *ctx) {
|
std::any SysYIRGenerator::visitContinueStmt(SysYParser::ContinueStmtContext *ctx) {
|
||||||
BasicBlock* continueBlock = builder.getContinueBlock();
|
BasicBlock* continueBlock = builder.getContinueBlock();
|
||||||
builder.createUncondBrInst(continueBlock, {});
|
builder.createUncondBrInst(continueBlock);
|
||||||
BasicBlock::conectBlocks(builder.getBasicBlock(), continueBlock);
|
BasicBlock::conectBlocks(builder.getBasicBlock(), continueBlock);
|
||||||
return std::any();
|
return std::any();
|
||||||
}
|
}
|
||||||
@@ -1807,7 +1921,7 @@ std::any SysYIRGenerator::visitLAndExp(SysYParser::LAndExpContext *ctx){
|
|||||||
labelstring.str("");
|
labelstring.str("");
|
||||||
|
|
||||||
auto cond = std::any_cast<Value *>(visitEqExp(ctx->eqExp(i)));
|
auto cond = std::any_cast<Value *>(visitEqExp(ctx->eqExp(i)));
|
||||||
builder.createCondBrInst(cond, newtrueBlock, falseBlock, {}, {});
|
builder.createCondBrInst(cond, newtrueBlock, falseBlock);
|
||||||
|
|
||||||
BasicBlock::conectBlocks(curBlock, newtrueBlock);
|
BasicBlock::conectBlocks(curBlock, newtrueBlock);
|
||||||
BasicBlock::conectBlocks(curBlock, falseBlock);
|
BasicBlock::conectBlocks(curBlock, falseBlock);
|
||||||
@@ -1817,7 +1931,7 @@ std::any SysYIRGenerator::visitLAndExp(SysYParser::LAndExpContext *ctx){
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto cond = std::any_cast<Value *>(visitEqExp(conds.back()));
|
auto cond = std::any_cast<Value *>(visitEqExp(conds.back()));
|
||||||
builder.createCondBrInst(cond, trueBlock, falseBlock, {}, {});
|
builder.createCondBrInst(cond, trueBlock, falseBlock);
|
||||||
|
|
||||||
BasicBlock::conectBlocks(curBlock, trueBlock);
|
BasicBlock::conectBlocks(curBlock, trueBlock);
|
||||||
BasicBlock::conectBlocks(curBlock, falseBlock);
|
BasicBlock::conectBlocks(curBlock, falseBlock);
|
||||||
@@ -1934,7 +2048,7 @@ void Utils::createExternalFunction(
|
|||||||
for (int i = 0; i < paramTypes.size(); ++i) {
|
for (int i = 0; i < paramTypes.size(); ++i) {
|
||||||
auto arg = new Argument(paramTypes[i], function, i, paramNames[i]);
|
auto arg = new Argument(paramTypes[i], function, i, paramNames[i]);
|
||||||
auto alloca = pBuilder->createAllocaInst(
|
auto alloca = pBuilder->createAllocaInst(
|
||||||
Type::getPointerType(paramTypes[i]), {}, paramNames[i]);
|
Type::getPointerType(paramTypes[i]), paramNames[i]);
|
||||||
function->insertArgument(arg);
|
function->insertArgument(arg);
|
||||||
auto store = pBuilder->createStoreInst(arg, alloca);
|
auto store = pBuilder->createStoreInst(arg, alloca);
|
||||||
pModule->addVariable(paramNames[i], alloca);
|
pModule->addVariable(paramNames[i], alloca);
|
||||||
|
|||||||
@@ -240,6 +240,8 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
|||||||
case Kind::kMul:
|
case Kind::kMul:
|
||||||
case Kind::kDiv:
|
case Kind::kDiv:
|
||||||
case Kind::kRem:
|
case Kind::kRem:
|
||||||
|
case Kind::kSRA:
|
||||||
|
case Kind::kMulh:
|
||||||
case Kind::kFAdd:
|
case Kind::kFAdd:
|
||||||
case Kind::kFSub:
|
case Kind::kFSub:
|
||||||
case Kind::kFMul:
|
case Kind::kFMul:
|
||||||
@@ -272,6 +274,8 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
|||||||
case Kind::kMul: std::cout << "mul"; break;
|
case Kind::kMul: std::cout << "mul"; break;
|
||||||
case Kind::kDiv: std::cout << "sdiv"; break;
|
case Kind::kDiv: std::cout << "sdiv"; break;
|
||||||
case Kind::kRem: std::cout << "srem"; break;
|
case Kind::kRem: std::cout << "srem"; break;
|
||||||
|
case Kind::kSRA: std::cout << "ashr"; break;
|
||||||
|
case Kind::kMulh: std::cout << "mulh"; break;
|
||||||
case Kind::kFAdd: std::cout << "fadd"; break;
|
case Kind::kFAdd: std::cout << "fadd"; break;
|
||||||
case Kind::kFSub: std::cout << "fsub"; break;
|
case Kind::kFSub: std::cout << "fsub"; break;
|
||||||
case Kind::kFMul: std::cout << "fmul"; break;
|
case Kind::kFMul: std::cout << "fmul"; break;
|
||||||
@@ -409,6 +413,11 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
|||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Kind::kUnreachable: {
|
||||||
|
std::cout << "Unreachable" << std::endl;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
|
||||||
case Kind::kAlloca: {
|
case Kind::kAlloca: {
|
||||||
auto allocaInst = dynamic_cast<AllocaInst *>(pInst);
|
auto allocaInst = dynamic_cast<AllocaInst *>(pInst);
|
||||||
std::cout << "%" << allocaInst->getName() << " = alloca ";
|
std::cout << "%" << allocaInst->getName() << " = alloca ";
|
||||||
@@ -419,17 +428,6 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
|||||||
auto allocatedType = allocaInst->getAllocatedType();
|
auto allocatedType = allocaInst->getAllocatedType();
|
||||||
printType(allocatedType);
|
printType(allocatedType);
|
||||||
|
|
||||||
// 仍然打印维度信息,如果存在的话
|
|
||||||
if (allocaInst->getNumDims() > 0) {
|
|
||||||
std::cout << ", ";
|
|
||||||
for (size_t i = 0; i < allocaInst->getNumDims(); i++) {
|
|
||||||
if (i > 0) std::cout << ", ";
|
|
||||||
printType(Type::getIntType()); // 维度大小通常是 i32 类型
|
|
||||||
std::cout << " ";
|
|
||||||
printValue(allocaInst->getDim(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << ", align 4" << std::endl;
|
std::cout << ", align 4" << std::endl;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -442,17 +440,6 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
|||||||
std::cout << " ";
|
std::cout << " ";
|
||||||
printValue(loadInst->getPointer()); // 要加载的地址
|
printValue(loadInst->getPointer()); // 要加载的地址
|
||||||
|
|
||||||
// 仍然打印索引信息,如果存在的话
|
|
||||||
if (loadInst->getNumIndices() > 0) {
|
|
||||||
std::cout << ", indices "; // 或者其他分隔符,取决于你期望的格式
|
|
||||||
for (size_t i = 0; i < loadInst->getNumIndices(); i++) {
|
|
||||||
if (i > 0) std::cout << ", ";
|
|
||||||
printType(loadInst->getIndex(i)->getType());
|
|
||||||
std::cout << " ";
|
|
||||||
printValue(loadInst->getIndex(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << ", align 4" << std::endl;
|
std::cout << ", align 4" << std::endl;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -467,16 +454,6 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
|||||||
std::cout << " ";
|
std::cout << " ";
|
||||||
printValue(storeInst->getPointer()); // 目标地址
|
printValue(storeInst->getPointer()); // 目标地址
|
||||||
|
|
||||||
// 仍然打印索引信息,如果存在的话
|
|
||||||
if (storeInst->getNumIndices() > 0) {
|
|
||||||
std::cout << ", indices "; // 或者其他分隔符
|
|
||||||
for (size_t i = 0; i < storeInst->getNumIndices(); i++) {
|
|
||||||
if (i > 0) std::cout << ", ";
|
|
||||||
printType(storeInst->getIndex(i)->getType());
|
|
||||||
std::cout << " ";
|
|
||||||
printValue(storeInst->getIndex(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << ", align 4" << std::endl;
|
std::cout << ", align 4" << std::endl;
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ using namespace sysy;
|
|||||||
|
|
||||||
int DEBUG = 0;
|
int DEBUG = 0;
|
||||||
int DEEPDEBUG = 0;
|
int DEEPDEBUG = 0;
|
||||||
|
int DEEPERDEBUG = 0;
|
||||||
|
int DEBUGLENGTH = 50;
|
||||||
|
|
||||||
static string argStopAfter;
|
static string argStopAfter;
|
||||||
static string argInputFile;
|
static string argInputFile;
|
||||||
|
|||||||
Reference in New Issue
Block a user