Compare commits

...

14 Commits

Author SHA1 Message Date
c268191826 [midend-SCCP]修改BaiscBlock的析构逻辑,将CFG修改的职责交给优化遍,注释Mem2Reg的调试信息。 2025-08-01 01:44:33 +08:00
0f1fcc835d [midend-SCCP]删除User的析构函数,usedelete增加逻辑通知inst所使用的value移除对应的use关系(一般在这之前会替换使用inst的uses为其他值),TODO:仍然存在bug需要调试 2025-07-31 22:32:04 +08:00
c5af4f1c49 [midend-SCCP]bug修复,增加不可达指令(理论来说后端不会出现这条指令,只是为了IR完整性添加),添加相关方法,phi指令方法修复;目前能够跑完所有优化,但是User的析构函数重定义导致全局析构不能正确完成,需要修复 2025-07-31 22:03:35 +08:00
9a53e1b917 [midend]适应上一次commit修改已有优化遍中相关指令删除的代码 2025-07-31 21:10:59 +08:00
ef09bc70d4 [midend]修改了removeinst方法,应对不同的使用情况,增加user析构函数使得user对象销毁顺带销毁其use关系销毁,重构usedelete方法封装指令删除和use关系删除 2025-07-31 21:10:20 +08:00
aed4577490 [midend]同上,删除了打印函数对维度信息的错误访问 2025-07-31 19:57:19 +08:00
35b421b60b [midend]修改原因同上一次commit 2025-07-31 19:38:43 +08:00
f3f603a032 [midend]消除冗余维度信息记录,适配IR生成器,TODO:其他优化遍生成指令修改,或者后端的访问 2025-07-31 19:36:39 +08:00
de0f8422e9 [midend-SCCP]没有编译报错但是Segmemtation falut 2025-07-31 17:29:34 +08:00
35691ab7bc [midend-SCCP]为跳转指令增加getSuccessors方法 2025-07-31 17:19:57 +08:00
61768fa180 [midend-SCCP]头文件构架完毕,cpp文件部分报错暂时不commit 2025-07-31 17:00:02 +08:00
520ebd96f0 [midend-SCCP]增加不可达指令,修改跳转指令参数(基本块args已弃用默认为{}) 2025-07-31 16:59:22 +08:00
6868f638d7 [midend-SCCP]增加基本块对的哈希值计算方法,增加删除use关系和指令的函数 2025-07-31 16:57:47 +08:00
206a0af424 [midend-SCCP]暂存1 2025-07-30 16:33:56 +08:00
15 changed files with 1512 additions and 406 deletions

View File

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

View File

@ -514,12 +514,15 @@ public:
explicit BasicBlock(Function *parent, const std::string &name = "")
: Value(Type::getLabelType(), name), parent(parent) {}
~BasicBlock() override {
for (auto pre : predecessors) {
pre->removeSuccessor(this);
}
for (auto suc : successors) {
suc->removePredecessor(this);
}
// for (auto pre : predecessors) {
// pre->removeSuccessor(this);
// }
// for (auto suc : successors) {
// suc->removePredecessor(this);
// }
// 这些关系应该在 BasicBlock 被从 Function 中移除时,
// 由负责 CFG 优化的 Pass (例如 SCCP 的 RemoveDeadBlock) 显式地清理。
// 析构函数只负责清理 BasicBlock 自身拥有的资源(例如,指令列表)。
}
public:
@ -599,7 +602,7 @@ public:
prev->addSuccessor(next);
next->addPredecessor(prev);
}
void removeInst(iterator pos) { instructions.erase(pos); }
iterator removeInst(iterator pos) { return instructions.erase(pos); }
void removeInst(Instruction *inst) {
auto pos = std::find_if(instructions.begin(), instructions.end(),
[inst](const std::unique_ptr<Instruction> &i) { return i.get() == inst; });
@ -626,6 +629,21 @@ class User : public Value {
explicit User(Type *type, const std::string &name = "") : Value(type, name) {}
public:
// ~User() override {
// // 当 User 对象被销毁时例如LoadInst 或 StoreInst 被删除时),
// // 它必须通知它所使用的所有 Value将对应的 Use 关系从它们的 uses 列表中移除。
// // 这样可以防止 Value 的 uses 列表中出现悬空的 Use 对象。
// for (const auto &use_ptr : operands) {
// // 确保 use_ptr 非空,并且其内部指向的 Value* 也非空
// // (虽然通常情况下不会为空,但为了健壮性考虑)
// if (use_ptr && use_ptr->getValue()) {
// use_ptr->getValue()->removeUse(use_ptr);
// }
// }
// // operands 向量本身是 std::vector<std::shared_ptr<Use>>
// // 在此析构函数结束后operands 向量会被销毁,其内部的 shared_ptr 也会被释放,
// // 如果 shared_ptr 引用计数降为0Use 对象本身也会被销毁。
// }
unsigned getNumOperands() const { return operands.size(); } ///< 获取操作数数量
auto operand_begin() const { return operands.begin(); } ///< 返回操作数列表的开头迭代器
auto operand_end() const { return operands.end(); } ///< 返回操作数列表的结尾迭代器
@ -695,15 +713,13 @@ class Instruction : public User {
kCondBr = 0x1UL << 30,
kBr = 0x1UL << 31,
kReturn = 0x1UL << 32,
kUnreachable = 0x1UL << 33,
// mem op
kAlloca = 0x1UL << 33,
kLoad = 0x1UL << 34,
kStore = 0x1UL << 35,
kGetElementPtr = 0x1UL << 36,
kMemset = 0x1UL << 37,
// kGetSubArray = 0x1UL << 38,
// Constant Kind removed as Constants are now Values, not Instructions.
// kConstant = 0x1UL << 37, // Conflicts with kMemset if kept as is
kAlloca = 0x1UL << 34,
kLoad = 0x1UL << 35,
kStore = 0x1UL << 36,
kGetElementPtr = 0x1UL << 37,
kMemset = 0x1UL << 38,
// phi
kPhi = 0x1UL << 39,
kBitItoF = 0x1UL << 40,
@ -832,7 +848,7 @@ public:
return kind & MemoryOpMask;
}
bool isTerminator() const {
static constexpr uint64_t TerminatorOpMask = kCondBr | kBr | kReturn;
static constexpr uint64_t TerminatorOpMask = kCondBr | kBr | kReturn | kUnreachable;
return kind & TerminatorOpMask;
}
bool isCmp() const {
@ -852,6 +868,7 @@ public:
}
bool isUnconditional() const { return kind == kBr; }
bool isConditional() const { return kind == kCondBr; }
bool isCondBr() const { return kind == kCondBr; }
bool isPhi() const { return kind == kPhi; }
bool isAlloca() const { return kind == kAlloca; }
bool isLoad() const { return kind == kLoad; }
@ -860,6 +877,7 @@ public:
bool isMemset() const { return kind == kMemset; }
bool isCall() const { return kind == kCall; }
bool isReturn() const { return kind == kReturn; }
bool isUnreachable() const { return kind == kUnreachable; }
bool isDefine() const {
static constexpr uint64_t DefineOpMask = kAlloca | kStore | kPhi;
return (kind & DefineOpMask) != 0U;
@ -894,6 +912,9 @@ class PhiInst : public Instruction {
public:
Value* getValue(unsigned k) const {return getOperand(2 * k);} ///< 获取位置为k的值
BasicBlock* getBlock(unsigned k) const {return dynamic_cast<BasicBlock*>(getOperand(2 * k + 1));}
//增加llvm同名方法实现获取value和block
Value* getIncomingValue(unsigned k) const {return getOperand(2 * k);} ///< 获取位置为k的值
BasicBlock* getIncomingBlock(unsigned k) const {return dynamic_cast<BasicBlock*>(getOperand(2 * k + 1));}
auto& getincomings() const {return blk2val;} ///< 获取所有的基本块和对应的值
@ -1059,12 +1080,10 @@ class UncondBrInst : public Instruction {
friend class Function;
protected:
UncondBrInst(BasicBlock *block, std::vector<Value *> args,
UncondBrInst(BasicBlock *block,
BasicBlock *parent = nullptr)
: Instruction(kBr, Type::getVoidType(), parent, "") {
// assert(block->getNumArguments() == args.size());
addOperand(block);
addOperands(args);
}
public:
@ -1072,6 +1091,16 @@ public:
auto getArguments() const {
return make_range(std::next(operand_begin()), operand_end());
}
std::vector<BasicBlock *> getSuccessors() const {
std::vector<BasicBlock *> succs;
// 假设无条件分支的目标块是它的第一个操作数
if (getNumOperands() > 0) {
if (auto target_bb = dynamic_cast<BasicBlock *>(getOperand(0))) {
succs.push_back(target_bb);
}
}
return succs;
}
}; // class UncondBrInst
@ -1084,16 +1113,11 @@ class CondBrInst : public Instruction {
protected:
CondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock,
const std::vector<Value *> &thenArgs,
const std::vector<Value *> &elseArgs, BasicBlock *parent = nullptr)
BasicBlock *parent = nullptr)
: Instruction(kCondBr, Type::getVoidType(), parent, "") {
// assert(thenBlock->getNumArguments() == thenArgs.size() and
// elseBlock->getNumArguments() == elseArgs.size());
addOperand(condition);
addOperand(thenBlock);
addOperand(elseBlock);
addOperands(thenArgs);
addOperands(elseArgs);
}
public:
Value* getCondition() const { return getOperand(0); }
@ -1103,29 +1127,39 @@ public:
BasicBlock* getElseBlock() const {
return dynamic_cast<BasicBlock *>(getOperand(2));
}
// auto getThenArguments() const {
// auto begin = std::next(operand_begin(), 3);
// // auto end = std::next(begin, getThenBlock()->getNumArguments());
// return make_range(begin, end);
// }
// auto getElseArguments() const {
// auto begin =
// std::next(operand_begin(), 3 + getThenBlock()->getNumArguments());
// auto end = operand_end();
// return make_range(begin, end);
// }
std::vector<BasicBlock *> getSuccessors() const {
std::vector<BasicBlock *> succs;
// 假设条件分支的真实块是第二个操作数,假块是第三个操作数
// 操作数通常是:[0] 条件值, [1] TrueTargetBlock, [2] FalseTargetBlock
if (getNumOperands() > 2) {
if (auto true_bb = getThenBlock()) {
succs.push_back(true_bb);
}
if (auto false_bb = getElseBlock()) {
succs.push_back(false_bb);
}
}
return succs;
}
}; // 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
class AllocaInst : public Instruction {
friend class IRBuilder;
friend class Function;
protected:
AllocaInst(Type *type, const std::vector<Value *> &dims = {},
AllocaInst(Type *type,
BasicBlock *parent = nullptr, const std::string &name = "")
: Instruction(kAlloca, type, parent, name) {
addOperands(dims);
}
public:
@ -1133,9 +1167,6 @@ public:
Type* getAllocatedType() const {
return getType()->as<PointerType>()->getBaseType();
} ///< 获取分配的类型
int getNumDims() const { return getNumOperands(); }
auto getDims() const { return getOperands(); }
Value* getDim(int index) { return getOperand(index); }
}; // class AllocaInst
@ -1182,21 +1213,15 @@ class LoadInst : public Instruction {
friend class Function;
protected:
LoadInst(Value *pointer, const std::vector<Value *> &indices = {},
LoadInst(Value *pointer,
BasicBlock *parent = nullptr, const std::string &name = "")
: Instruction(kLoad, pointer->getType()->as<PointerType>()->getBaseType(),
parent, name) {
addOperand(pointer);
addOperands(indices);
}
public:
int getNumIndices() const { return getNumOperands() - 1; }
Value* getPointer() const { return getOperand(0); }
auto getIndices() const {
return make_range(std::next(operand_begin()), operand_end());
}
Value* getIndex(int index) const { return getOperand(index + 1); }
}; // class LoadInst
@ -1207,22 +1232,15 @@ class StoreInst : public Instruction {
protected:
StoreInst(Value *value, Value *pointer,
const std::vector<Value *> &indices = {},
BasicBlock *parent = nullptr, const std::string &name = "")
: Instruction(kStore, Type::getVoidType(), parent, name) {
addOperand(value);
addOperand(pointer);
addOperands(indices);
}
public:
int getNumIndices() const { return getNumOperands() - 2; }
Value* getValue() const { return getOperand(0); }
Value* getPointer() const { return getOperand(1); }
auto getIndices() const {
return make_range(std::next(operand_begin(), 2), operand_end());
}
Value* getIndex(int index) const { return getOperand(index + 2); }
}; // class StoreInst
@ -1361,20 +1379,18 @@ protected:
protected:
GlobalValue(Module *parent, Type *type, const std::string &name,
const std::vector<Value *> &dims = {},
ValueCounter init = {})
: Value(type, name), parent(parent) {
assert(type->isPointer());
// addOperands(dims);
// 维度信息已经被记录到Type中dim只是为了方便初始化
numDims = dims.size();
numDims = 0;
if (init.size() == 0) {
unsigned num = 1;
for (unsigned i = 0; i < numDims; i++) {
// Assume dims elements are ConstantInteger and cast appropriately
auto dim_val = dynamic_cast<ConstantInteger*>(dims[i]);
assert(dim_val && "GlobalValue dims must be constant integers");
num *= dim_val->getInt();
auto arrayType = type->as<ArrayType>();
while (arrayType) {
numDims++;
num *= arrayType->getNumElements();
arrayType = arrayType->getElementType()->as<ArrayType>();
}
if (dynamic_cast<PointerType *>(type)->getBaseType() == Type::getFloatType()) {
init.push_back(ConstantFloating::get(0.0F), num); // Use new constant factory
@ -1386,9 +1402,6 @@ protected:
}
public:
// unsigned getNumDims() const { return numDims; } ///< 获取维度数量
// Value* getDim(unsigned index) const { return getOperand(index); } ///< 获取位置为index的维度
// auto getDims() const { return getOperands(); } ///< 获取维度列表
unsigned getNumIndices() const {
return numDims;
} ///< 获取维度数量
@ -1430,13 +1443,19 @@ class ConstantVariable : public Value {
ValueCounter initValues; ///< 值
protected:
ConstantVariable(Module *parent, Type *type, const std::string &name, const ValueCounter &init,
const std::vector<Value *> &dims = {})
ConstantVariable(Module *parent, Type *type, const std::string &name, const ValueCounter &init)
: Value(type, name), parent(parent) {
assert(type->isPointer());
numDims = dims.size();
// numDims = dims.size();
numDims = 0;
if(type->as<PointerType>()->getBaseType()->isArray()) {
auto arrayType = type->as<ArrayType>();
while (arrayType) {
numDims++;
arrayType = arrayType->getElementType()->as<ArrayType>();
}
}
initValues = init;
// addOperands(dims); 同GlobalValue维度信息已经被记录到Type中dim只是为了方便初始化
}
public:
@ -1468,9 +1487,6 @@ class ConstantVariable : public Value {
return getByIndex(index);
} ///< 通过多维索引indices获取初始值
// unsigned getNumDims() const { return numDims; } ///< 获取维度数量
// Value* getDim(unsigned index) const { return getOperand(index); } ///< 获取位置为index的维度
// auto getDims() const { return getOperands(); } ///< 获取维度列表
const ValueCounter& getInitValues() const { return initValues; } ///< 获取初始值
};
@ -1529,13 +1545,12 @@ class Module {
return result.first->second.get();
} ///< 创建外部函数
///< 变量创建伴随着符号表的更新
GlobalValue* createGlobalValue(const std::string &name, Type *type, const std::vector<Value *> &dims = {},
const ValueCounter &init = {}) {
GlobalValue* createGlobalValue(const std::string &name, Type *type, const ValueCounter &init = {}) {
bool isFinished = variableTable.isCurNodeNull();
if (isFinished) {
variableTable.enterGlobalScope();
}
auto result = variableTable.addVariable(name, new GlobalValue(this, type, name, dims, init));
auto result = variableTable.addVariable(name, new GlobalValue(this, type, name, init));
if (isFinished) {
variableTable.leaveScope();
}
@ -1544,9 +1559,8 @@ class Module {
}
return dynamic_cast<GlobalValue *>(result);
} ///< 创建全局变量
ConstantVariable* createConstVar(const std::string &name, Type *type, const ValueCounter &init,
const std::vector<Value *> &dims = {}) {
auto result = variableTable.addVariable(name, new ConstantVariable(this, type, name, init, dims));
ConstantVariable* createConstVar(const std::string &name, Type *type, const ValueCounter &init) {
auto result = variableTable.addVariable(name, new ConstantVariable(this, type, name, init));
if (result == nullptr) {
return nullptr;
}

View File

@ -239,31 +239,30 @@ class IRBuilder {
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建return指令
UncondBrInst * createUncondBrInst(BasicBlock *thenBlock, const std::vector<Value *> &args) {
auto inst = new UncondBrInst(thenBlock, args, block);
UncondBrInst * createUncondBrInst(BasicBlock *thenBlock) {
auto inst = new UncondBrInst(thenBlock, block);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建无条件指令
CondBrInst * createCondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock,
const std::vector<Value *> &thenArgs, const std::vector<Value *> &elseArgs) {
auto inst = new CondBrInst(condition, thenBlock, elseBlock, thenArgs, elseArgs, block);
CondBrInst * createCondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock) {
auto inst = new CondBrInst(condition, thenBlock, elseBlock, block);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建条件跳转指令
AllocaInst * createAllocaInst(Type *type, const std::vector<Value *> &dims = {}, const std::string &name = "") {
auto inst = new AllocaInst(type, dims, block, name);
UnreachableInst * createUnreachableInst(const std::string &name = "") {
auto inst = new UnreachableInst(name, block);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建不可达指令
AllocaInst * createAllocaInst(Type *type, const std::string &name = "") {
auto inst = new AllocaInst(type, block, name);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建分配指令
AllocaInst * createAllocaInstWithoutInsert(Type *type, const std::vector<Value *> &dims = {}, BasicBlock *parent = nullptr,
const std::string &name = "") {
auto inst = new AllocaInst(type, dims, parent, name);
assert(inst);
return inst;
} ///< 创建不插入指令列表的分配指令[仅用于phi指令]
LoadInst * createLoadInst(Value *pointer, const std::vector<Value *> &indices = {}, const std::string &name = "") {
std::string newName;
if (name.empty()) {
@ -275,7 +274,7 @@ class IRBuilder {
newName = name;
}
auto inst = new LoadInst(pointer, indices, block, newName);
auto inst = new LoadInst(pointer, block, newName);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
@ -286,9 +285,8 @@ class IRBuilder {
block->getInstructions().emplace(position, inst);
return inst;
} ///< 创建memset指令
StoreInst * createStoreInst(Value *value, Value *pointer, const std::vector<Value *> &indices = {},
const std::string &name = "") {
auto inst = new StoreInst(value, pointer, indices, block, name);
StoreInst * createStoreInst(Value *value, Value *pointer, const std::string &name = "") {
auto inst = new StoreInst(value, pointer, block, name);
assert(inst);
block->getInstructions().emplace(position, inst);
return inst;
@ -308,24 +306,6 @@ class IRBuilder {
block->getInstructions().emplace(block->begin(), inst);
return inst;
} ///< 创建Phi指令
// GetElementPtrInst* createGetElementPtrInst(Value *basePointer,
// const std::vector<Value *> &indices = {},
// const std::string &name = "") {
// std::string newName;
// if (name.empty()) {
// std::stringstream ss;
// ss << tmpIndex;
// newName = ss.str();
// tmpIndex++;
// } else {
// newName = name;
// }
// auto inst = new GetElementPtrInst(basePointer, indices, block, newName);
// assert(inst);
// block->getInstructions().emplace(position, inst);
// return inst;
// }
/**
* @brief 根据 LLVM 设计模式创建 GEP 指令。
* 它会自动推断返回类型,无需手动指定。

View File

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

View File

@ -2,6 +2,7 @@
#include "IR.h"
extern int DEBUG;
namespace sysy {
// 优化工具类,包含一些通用的优化方法
@ -10,12 +11,87 @@ namespace sysy {
class SysYIROptUtils{
public:
// 仅仅删除use关系
static void usedelete(Instruction *instr) {
for (auto &use : instr->getOperands()) {
Value* val = use->getValue();
val->removeUse(use);
struct PairHash {
template <class T1, class T2>
std::size_t operator () (const std::pair<T1, T2>& p) const {
auto h1 = std::hash<T1>{}(p.first);
auto h2 = std::hash<T2>{}(p.second);
// 简单的组合哈希值,可以更复杂以减少冲突
// 使用 boost::hash_combine 的简化版本
return h1 ^ (h2 << 1);
}
};
static void RemoveUserOperandUses(User *user) {
if (!user) {
return;
}
// 遍历 User 的 operands 列表。
// 由于 operands 是 protected 成员,我们需要一个临时方法来访问它,
// 或者在 User 类中添加一个 friend 声明。
// 假设 User 内部有一个像 getOperands() 这样的公共方法返回 operands 的引用,
// 或者将 SysYIROptUtils 声明为 User 的 friend。
// 为了示例,我将假设可以直接访问 user->operands 或通过一个getter。
// 如果无法直接访问,请在 IR.h 的 User 类中添加:
// public: const std::vector<std::shared_ptr<Use>>& getOperands() const { return operands; }
// 迭代 copies of shared_ptr to avoid issues if removeUse modifies the list
// (though remove should handle it, iterating a copy is safer or reverse iteration).
// Since we'll clear the vector at the end, iterating forward is fine.
for (const auto& use_ptr : user->getOperands()) { // 假设 getOperands() 可用
if (use_ptr) {
Value *val = use_ptr->getValue(); // 获取 Use 指向的 Value (如 AllocaInst)
if (val) {
val->removeUse(use_ptr); // 通知 Value 从其 uses 列表中移除此 Use 关系
}
}
}
// 清空 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);
}
// 判断是否是全局变量
@ -26,7 +102,17 @@ public:
// 判断是否是数组
static bool isArr(Value *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());
}
};

View File

@ -10,6 +10,7 @@ add_library(midend_lib STATIC
Pass/Optimize/Mem2Reg.cpp
Pass/Optimize/Reg2Mem.cpp
Pass/Optimize/SysYIRCFGOpt.cpp
Pass/Optimize/SCCP.cpp
)
# 包含中端模块所需的头文件路径

View File

@ -227,12 +227,13 @@ Function * Function::clone(const std::string &suffix) const {
auto oldAllocInst = dynamic_cast<AllocaInst *>(value);
if (oldAllocInst != nullptr) {
std::vector<Value *> dims;
for (const auto &dim : oldAllocInst->getDims()) {
dims.emplace_back(dim->getValue());
}
// TODO: 这里的dims用type推断
// for (const auto &dim : oldAllocInst->getDims()) {
// dims.emplace_back(dim->getValue());
// }
ss << oldAllocInst->getName() << suffix;
auto newAllocInst =
new AllocaInst(oldAllocInst->getType(), dims, oldNewBlockMap.at(oldAllocInst->getParent()), ss.str());
new AllocaInst(oldAllocInst->getType(), oldNewBlockMap.at(oldAllocInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldAllocInst, newAllocInst);
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()) {
auto oldAllocInst = dynamic_cast<AllocaInst *>(inst.get());
std::vector<Value *> dims;
for (const auto &dim : oldAllocInst->getDims()) {
dims.emplace_back(dim->getValue());
}
// TODO: 这里的dims用type推断
// for (const auto &dim : oldAllocInst->getDims()) {
// dims.emplace_back(dim->getValue());
// }
ss << oldAllocInst->getName() << suffix;
auto newAllocInst =
new AllocaInst(oldAllocInst->getType(), dims, oldNewBlockMap.at(oldAllocInst->getParent()), ss.str());
new AllocaInst(oldAllocInst->getType(), oldNewBlockMap.at(oldAllocInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldAllocInst, newAllocInst);
if (isAddedToCreate.find(oldAllocInst) == isAddedToCreate.end()) {
@ -422,7 +424,7 @@ Function * Function::clone(const std::string &suffix) const {
Value *newCond;
newCond = oldNewValueMap.at(oldCond);
auto newCondBrInst = new CondBrInst(newCond, oldNewBlockMap.at(oldCondBrInst->getThenBlock()),
oldNewBlockMap.at(oldCondBrInst->getElseBlock()), {}, {},
oldNewBlockMap.at(oldCondBrInst->getElseBlock()),
oldNewBlockMap.at(oldCondBrInst->getParent()));
oldNewValueMap.emplace(oldCondBrInst, newCondBrInst);
break;
@ -431,7 +433,7 @@ Function * Function::clone(const std::string &suffix) const {
case Instruction::kBr: {
auto oldBrInst = dynamic_cast<UncondBrInst *>(inst);
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);
break;
}
@ -460,11 +462,12 @@ Function * Function::clone(const std::string &suffix) const {
newPointer = oldNewValueMap.at(oldPointer);
std::vector<Value *> newIndices;
for (const auto &index : oldLoadInst->getIndices()) {
newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
}
// for (const auto &index : oldLoadInst->getIndices()) {
// newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
// }
ss << oldLoadInst->getName() << suffix;
auto newLoadInst = new LoadInst(newPointer, newIndices, oldNewBlockMap.at(oldLoadInst->getParent()), ss.str());
// TODO : 这里的newLoadInst的类型需要根据oldLoadInst的类型来推断
auto newLoadInst = new LoadInst(newPointer, oldNewBlockMap.at(oldLoadInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldLoadInst, newLoadInst);
break;
@ -479,10 +482,11 @@ Function * Function::clone(const std::string &suffix) const {
std::vector<Value *> newIndices;
newPointer = oldNewValueMap.at(oldPointer);
newValue = oldNewValueMap.at(oldValue);
for (const auto &index : oldStoreInst->getIndices()) {
newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
}
auto newStoreInst = new StoreInst(newValue, newPointer, newIndices,
// TODO: 这里的newIndices需要根据oldStoreInst的类型来推断
// for (const auto &index : oldStoreInst->getIndices()) {
// newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
// }
auto newStoreInst = new StoreInst(newValue, newPointer,
oldNewBlockMap.at(oldStoreInst->getParent()), oldStoreInst->getName());
oldNewValueMap.emplace(oldStoreInst, newStoreInst);
break;
@ -615,11 +619,13 @@ void PhiInst::delBlk(BasicBlock* blk){
void PhiInst::replaceBlk(BasicBlock* newBlk, unsigned k){
refreshB2VMap();
Value* val = blk2val.at(getBlock(k));
BasicBlock* oldBlk = getBlock(k);
Value* val = blk2val.at(oldBlk);
// Value* val = blk2val.at(getBlock(k));
// 替换基本块
setOperand(2 * k + 1, newBlk);
// 替换blk2val映射
blk2val.erase(getBlock(k));
blk2val.erase(oldBlk);
blk2val.emplace(newBlk, val);
}

View File

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

View File

@ -240,10 +240,11 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr
// loadInst->getPointer() 返回 AllocaInst*
// 将 LoadInst 的所有用途替换为当前 alloca 值栈顶部的 SSA 值
assert(!allocaToValueStackMap[alloca].empty() && "Value stack empty for alloca during load replacement!");
if(DEBUG){
std::cout << "Mem2Reg: Replacing load " << loadInst->getPointer()->getName() << " with SSA value." << std::endl;
}
loadInst->replaceAllUsesWith(allocaToValueStackMap[alloca].top());
// instIter = currentBB->force_delete_inst(loadInst); // 删除 LoadInst
SysYIROptUtils::usedelete(loadInst); // 仅删除 use 关系
instIter = currentBB->getInstructions().erase(instIter); // 删除 LoadInst
instIter = SysYIROptUtils::usedelete(instIter);
instDeleted = true;
// std::cerr << "Mem2Reg: Replaced load " << loadInst->name() << " with SSA value." << std::endl;
break;
@ -257,10 +258,12 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr
if (storeInst->getPointer() == alloca) {
// 假设 storeInst->getPointer() 返回 AllocaInst*
// 将 StoreInst 存储的值作为新的 SSA 值,压入值栈
if(DEBUG){
std::cout << "Mem2Reg: Replacing store to " << storeInst->getPointer()->getName() << " with SSA value." << std::endl;
}
allocaToValueStackMap[alloca].push(storeInst->getValue());
localStackPushed.push(storeInst->getValue()); // 记录以便弹出
SysYIROptUtils::usedelete(storeInst);
instIter = currentBB->getInstructions().erase(instIter); // 删除 StoreInst
instIter = SysYIROptUtils::usedelete(instIter);
instDeleted = true;
// std::cerr << "Mem2Reg: Replaced store to " << storeInst->ptr()->name() << " with SSA value." << std::endl;
break;
@ -298,7 +301,9 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr
if(dominatedBlocks){
for (auto dominatedBB : *dominatedBlocks) {
if (dominatedBB) {
if(DEBUG){
std::cout << "Mem2Reg: Recursively renaming variables in dominated block: " << dominatedBB->getName() << std::endl;
}
renameVariables(currentAlloca, dominatedBB);
}
}
@ -327,7 +332,6 @@ void Mem2RegContext::cleanup() {
if (alloca && alloca->getParent()) {
// 删除 alloca 指令本身
SysYIROptUtils::usedelete(alloca);
alloca->getParent()->removeInst(alloca); // 从基本块中删除 alloca
// std::cerr << "Mem2Reg: Deleted alloca " << alloca->name() << std::endl;
}

View File

@ -74,7 +74,7 @@ void Reg2MemContext::allocateMemoryForSSAValues(Function *func) {
// 默认情况下,将所有参数是提升到内存
if (isPromotableToMemory(arg)) {
// 参数的类型就是 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 逆转的关键一步)
valueToAllocaMap[arg] = alloca;
@ -103,7 +103,7 @@ void Reg2MemContext::allocateMemoryForSSAValues(Function *func) {
// AllocaInst 应该在入口块,而不是当前指令所在块
// 这里我们只是创建,并稍后调整其位置
// 通常的做法是在循环结束后统一将 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;
}
}
@ -181,8 +181,7 @@ void Reg2MemContext::rewritePhis(Function *func) {
// 实际删除 Phi 指令
for (auto phi : phisToErase) {
if (phi && phi->getParent()) {
SysYIROptUtils::usedelete(phi); // 清理 use-def 链
phi->getParent()->removeInst(phi); // 从基本块中删除
SysYIROptUtils::usedelete(phi);
}
}
}

View 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 返回 pairsecond 为 true 表示插入成功
if (DEBUG) {
std::cout << "Marking block " << block->getName() << " as executable." << std::endl;
}
// 将新可执行块中的所有指令添加到指令工作列表
for (auto &inst_ptr : block->getInstructions()) {
instWorkList.push(inst_ptr.get());
}
}
}
// 辅助函数:对二元操作进行常量折叠
SSAPValue SCCPContext::ComputeConstant(BinaryInst *binaryInst, SSAPValue lhsVal, SSAPValue rhsVal) {
// 确保操作数是常量
if (lhsVal.state != LatticeVal::Constant || rhsVal.state != LatticeVal::Constant) {
return SSAPValue(LatticeVal::Bottom); // 如果不是常量,则不能折叠
}
// 处理整数运算 (kAdd, kSub, kMul, kDiv, kRem, kICmp*, kAnd, kOr)
if (lhsVal.constant_type == ValueType::Integer && rhsVal.constant_type == ValueType::Integer) {
int lhs = std::get<int>(lhsVal.constantVal);
int rhs = std::get<int>(rhsVal.constantVal);
int result = 0;
switch (binaryInst->getKind()) {
case Instruction::kAdd:
result = lhs + rhs;
break;
case Instruction::kSub:
result = lhs - rhs;
break;
case Instruction::kMul:
result = lhs * rhs;
break;
case Instruction::kDiv:
if (rhs == 0)
return SSAPValue(LatticeVal::Bottom); // 除零
result = lhs / rhs;
break;
case Instruction::kRem:
if (rhs == 0)
return SSAPValue(LatticeVal::Bottom); // 模零
result = lhs % rhs;
break;
case Instruction::kICmpEQ:
result = (lhs == rhs);
break;
case Instruction::kICmpNE:
result = (lhs != rhs);
break;
case Instruction::kICmpLT:
result = (lhs < rhs);
break;
case Instruction::kICmpGT:
result = (lhs > rhs);
break;
case Instruction::kICmpLE:
result = (lhs <= rhs);
break;
case Instruction::kICmpGE:
result = (lhs >= rhs);
break;
case Instruction::kAnd:
result = (lhs && rhs);
break;
case Instruction::kOr:
result = (lhs || rhs);
break;
default:
return SSAPValue(LatticeVal::Bottom); // 未知或不匹配的二元操作
}
return SSAPValue(result);
}
// 处理浮点运算 (kFAdd, kFSub, kFMul, kFDiv, kFCmp*)
else if (lhsVal.constant_type == ValueType::Float && rhsVal.constant_type == ValueType::Float) {
float lhs = std::get<float>(lhsVal.constantVal);
float rhs = std::get<float>(rhsVal.constantVal);
float f_result = 0.0f;
int i_result = 0; // For comparison results
switch (binaryInst->getKind()) {
case Instruction::kFAdd:
f_result = lhs + rhs;
break;
case Instruction::kFSub:
f_result = lhs - rhs;
break;
case Instruction::kFMul:
f_result = lhs * rhs;
break;
case Instruction::kFDiv:
if (rhs == 0.0f)
return SSAPValue(LatticeVal::Bottom); // 除零
f_result = lhs / rhs;
break;
// kRem 不支持浮点数,但如果你的 IR 定义了浮点模运算,需要使用 std::fmod
case Instruction::kFCmpEQ:
i_result = (lhs == rhs);
return SSAPValue(i_result);
case Instruction::kFCmpNE:
i_result = (lhs != rhs);
return SSAPValue(i_result);
case Instruction::kFCmpLT:
i_result = (lhs < rhs);
return SSAPValue(i_result);
case Instruction::kFCmpGT:
i_result = (lhs > rhs);
return SSAPValue(i_result);
case Instruction::kFCmpLE:
i_result = (lhs <= rhs);
return SSAPValue(i_result);
case Instruction::kFCmpGE:
i_result = (lhs >= rhs);
return SSAPValue(i_result);
default:
return SSAPValue(LatticeVal::Bottom); // 未知或不匹配的浮点二元操作
}
return SSAPValue(f_result);
}
return SSAPValue(LatticeVal::Bottom); // 类型不匹配或不支持的类型组合
}
// 辅助函数:对一元操作进行常量折叠
SSAPValue SCCPContext::ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVal) {
if (operandVal.state != LatticeVal::Constant) {
return SSAPValue(LatticeVal::Bottom);
}
if (operandVal.constant_type == ValueType::Integer) {
int val = std::get<int>(operandVal.constantVal);
switch (unaryInst->getKind()) {
case Instruction::kAdd:
return SSAPValue(val);
case Instruction::kNeg:
return SSAPValue(-val);
case Instruction::kNot:
return SSAPValue(!val);
default:
return SSAPValue(LatticeVal::Bottom);
}
} else if (operandVal.constant_type == ValueType::Float) {
float val = std::get<float>(operandVal.constantVal);
switch (unaryInst->getKind()) {
case Instruction::kAdd:
return SSAPValue(val);
case Instruction::kFNeg:
return SSAPValue(-val);
case Instruction::kFNot:
return SSAPValue(static_cast<int>(val == 0.0f)); // 浮点数非0.0f 为真,其他为假
default:
return SSAPValue(LatticeVal::Bottom);
}
}
return SSAPValue(LatticeVal::Bottom);
}
// 辅助函数:处理单条指令
void SCCPContext::ProcessInstruction(Instruction *inst) {
SSAPValue oldState = GetValueState(inst);
SSAPValue newState;
if (!executableBlocks.count(inst->getParent())) {
// 如果指令所在的块不可执行,其值应保持 Top
// 除非它之前已经是 Bottom因为 Bottom 是单调的
if (oldState.state != LatticeVal::Bottom) {
newState = SSAPValue(); // Top
} else {
newState = oldState; // 保持 Bottom
}
UpdateState(inst, newState);
return; // 不处理不可达块中的指令的实际值
}
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

View File

@ -91,13 +91,11 @@ bool SysYCFGOptUtils::SysYBlockMerge(Function *func) {
auto thelastinstinst = block->end();
(--thelastinstinst);
if (thelastinstinst->get()->isUnconditional()) {
SysYIROptUtils::usedelete(thelastinstinst->get());
thelastinstinst = block->getInstructions().erase(thelastinstinst);
thelastinstinst = SysYIROptUtils::usedelete(thelastinstinst);
} else if (thelastinstinst->get()->isConditional()) {
// 如果是条件分支,判断条件是否相同,主要优化相同布尔表达式
if (thelastinstinst->get()->getOperand(1)->getName() == thelastinstinst->get()->getOperand(1)->getName()) {
SysYIROptUtils::usedelete(thelastinstinst->get());
thelastinstinst = block->getInstructions().erase(thelastinstinst);
thelastinstinst = SysYIROptUtils::usedelete(thelastinstinst);
}
}
}
@ -164,8 +162,7 @@ bool SysYCFGOptUtils::SysYDelNoPreBLock(Function *func) {
if (!blockIter->get()->getreachable()) {
for (auto instIter = blockIter->get()->getInstructions().begin();
instIter != blockIter->get()->getInstructions().end();) {
SysYIROptUtils::usedelete(instIter->get());
instIter = blockIter->get()->getInstructions().erase(instIter);
instIter = SysYIROptUtils::usedelete(instIter);
}
}
}
@ -306,10 +303,9 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder) {
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);
thelastinst = SysYIROptUtils::usedelete(thelastinst);
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(thebrBlock, {});
pBuilder->createUncondBrInst(thebrBlock);
changed = true; // 标记IR被修改
continue;
}
@ -345,10 +341,9 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder) {
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);
thelastinst = SysYIROptUtils::usedelete(thelastinst);
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(thebrBlock, {});
pBuilder->createUncondBrInst(thebrBlock);
changed = true; // 标记IR被修改
continue;
}
@ -425,9 +420,7 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder) {
for (auto instIter = iter->get()->getInstructions().begin();
instIter != iter->get()->getInstructions().end();) {
SysYIROptUtils::usedelete(instIter->get()); // 仅删除 use 关系
// 显式地从基本块中删除指令并更新迭代器
instIter = iter->get()->getInstructions().erase(instIter);
instIter = SysYIROptUtils::usedelete(instIter);
}
// 删除不可达基本块的phi指令的操作数
for (auto &succ : iter->get()->getSuccessors()) {
@ -523,12 +516,11 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) {
auto thenBlock = dynamic_cast<BasicBlock *>(thelast->get()->getOperand(1));
auto elseBlock = dynamic_cast<BasicBlock *>(thelast->get()->getOperand(2));
SysYIROptUtils::usedelete(thelast->get());
thelast = basicblock->getInstructions().erase(thelast);
thelast = SysYIROptUtils::usedelete(thelast);
if ((constfloat_Use && constfloat == 1.0F) || (constint_Use && constint == 1)) {
// cond为true或非0
pBuilder->setPosition(basicblock.get(), basicblock->end());
pBuilder->createUncondBrInst(thenBlock, {});
pBuilder->createUncondBrInst(thenBlock);
// 更新CFG关系
basicblock->removeSuccessor(elseBlock);
@ -546,7 +538,7 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) {
} else { // cond为false或0
pBuilder->setPosition(basicblock.get(), basicblock->end());
pBuilder->createUncondBrInst(elseBlock, {});
pBuilder->createUncondBrInst(elseBlock);
// 更新CFG关系
basicblock->removeSuccessor(thenBlock);

View File

@ -5,6 +5,7 @@
#include "DCE.h"
#include "Mem2Reg.h"
#include "Reg2Mem.h"
#include "SCCP.h"
#include "Pass.h"
#include <iostream>
#include <queue>
@ -50,6 +51,8 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
registerOptimizationPass<Mem2Reg>(builderIR);
registerOptimizationPass<Reg2Mem>(builderIR);
registerOptimizationPass<SCCP>(builderIR);
if (optLevel >= 1) {
//经过设计安排优化遍的执行顺序以及执行逻辑
if (DEBUG) std::cout << "Applying -O1 optimizations.\n";
@ -87,6 +90,15 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
printPasses();
}
this->clearPasses();
this->addPass(&SCCP::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After SCCP Optimizations ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&Reg2Mem::ID);
this->run();

View File

@ -98,7 +98,7 @@ std::any SysYIRGenerator::visitGlobalConstDecl(SysYParser::GlobalConstDeclContex
if (!dims.empty()) { // 如果有维度,说明是数组
variableType = buildArrayType(type, dims); // 构建完整的 ArrayType
}
module->createConstVar(name, Type::getPointerType(variableType), values, dims);
module->createConstVar(name, Type::getPointerType(variableType), values);
}
return std::any();
}
@ -127,7 +127,7 @@ std::any SysYIRGenerator::visitGlobalVarDecl(SysYParser::GlobalVarDeclContext *c
if (!dims.empty()) { // 如果有维度,说明是数组
variableType = buildArrayType(type, dims); // 构建完整的 ArrayType
}
module->createGlobalValue(name, Type::getPointerType(variableType), dims, values);
module->createGlobalValue(name, Type::getPointerType(variableType), values);
}
return std::any();
}
@ -151,7 +151,7 @@ std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext *ctx) {
// 显式地为局部常量在栈上分配空间
// 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));
ValueCounter values;
@ -272,7 +272,7 @@ std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx) {
// 对于数组alloca 的类型将是指针指向数组类型,例如 `int[2][3]*`
// 对于标量alloca 的类型将是指针指向标量类型,例如 `int*`
AllocaInst* alloca =
builder.createAllocaInst(Type::getPointerType(variableType), {}, name);
builder.createAllocaInst(Type::getPointerType(variableType), name);
if (varDef->initVal() != nullptr) {
ValueCounter values;
@ -510,7 +510,7 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
auto funcArgs = function->getArguments();
std::vector<AllocaInst *> allocas;
for (int i = 0; i < paramActualTypes.size(); ++i) {
AllocaInst *alloca = builder.createAllocaInst(Type::getPointerType(paramActualTypes[i]), {}, paramNames[i]);
AllocaInst *alloca = builder.createAllocaInst(Type::getPointerType(paramActualTypes[i]), paramNames[i]);
allocas.push_back(alloca);
module->addVariable(paramNames[i], alloca);
}
@ -525,7 +525,7 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
BasicBlock* funcBodyEntry = function->addBasicBlock("funcBodyEntry_" + name);
// 从 entryBB 无条件跳转到 funcBodyEntry
builder.createUncondBrInst(funcBodyEntry, {});
builder.createUncondBrInst(funcBodyEntry);
builder.setPosition(funcBodyEntry,funcBodyEntry->end()); // 将插入点设置到 funcBodyEntry
for (auto item : ctx->blockStmt()->blockItem()) {
@ -690,7 +690,7 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
ctx->stmt(0)->accept(this);
module->leaveScope();
}
builder.createUncondBrInst(exitBlock, {});
builder.createUncondBrInst(exitBlock);
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
labelstring << "if_else.L" << builder.getLabelIndex();
@ -707,7 +707,7 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
ctx->stmt(1)->accept(this);
module->leaveScope();
}
builder.createUncondBrInst(exitBlock, {});
builder.createUncondBrInst(exitBlock);
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
labelstring << "if_exit.L" << builder.getLabelIndex();
@ -737,7 +737,7 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
ctx->stmt(0)->accept(this);
module->leaveScope();
}
builder.createUncondBrInst(exitBlock, {});
builder.createUncondBrInst(exitBlock);
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
labelstring << "if_exit.L" << builder.getLabelIndex();
@ -759,7 +759,7 @@ std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
labelstring << "while_head.L" << builder.getLabelIndex();
BasicBlock *headBlock = function->addBasicBlock(labelstring.str());
labelstring.str("");
builder.createUncondBrInst(headBlock, {});
builder.createUncondBrInst(headBlock);
BasicBlock::conectBlocks(curBlock, headBlock);
builder.setPosition(headBlock, headBlock->end());
@ -792,7 +792,7 @@ std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
module->leaveScope();
}
builder.createUncondBrInst(headBlock, {});
builder.createUncondBrInst(headBlock);
BasicBlock::conectBlocks(builder.getBasicBlock(), exitBlock);
builder.popBreakBlock();
builder.popContinueBlock();
@ -808,14 +808,14 @@ std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
std::any SysYIRGenerator::visitBreakStmt(SysYParser::BreakStmtContext *ctx) {
BasicBlock* breakBlock = builder.getBreakBlock();
builder.createUncondBrInst(breakBlock, {});
builder.createUncondBrInst(breakBlock);
BasicBlock::conectBlocks(builder.getBasicBlock(), breakBlock);
return std::any();
}
std::any SysYIRGenerator::visitContinueStmt(SysYParser::ContinueStmtContext *ctx) {
BasicBlock* continueBlock = builder.getContinueBlock();
builder.createUncondBrInst(continueBlock, {});
builder.createUncondBrInst(continueBlock);
BasicBlock::conectBlocks(builder.getBasicBlock(), continueBlock);
return std::any();
}
@ -1504,7 +1504,7 @@ std::any SysYIRGenerator::visitLAndExp(SysYParser::LAndExpContext *ctx){
labelstring.str("");
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, falseBlock);
@ -1514,7 +1514,7 @@ std::any SysYIRGenerator::visitLAndExp(SysYParser::LAndExpContext *ctx){
}
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, falseBlock);
@ -1631,7 +1631,7 @@ void Utils::createExternalFunction(
for (int i = 0; i < paramTypes.size(); ++i) {
auto arg = new Argument(paramTypes[i], function, i, paramNames[i]);
auto alloca = pBuilder->createAllocaInst(
Type::getPointerType(paramTypes[i]), {}, paramNames[i]);
Type::getPointerType(paramTypes[i]), paramNames[i]);
function->insertArgument(arg);
auto store = pBuilder->createStoreInst(arg, alloca);
pModule->addVariable(paramNames[i], alloca);

View File

@ -401,6 +401,11 @@ void SysYPrinter::printInst(Instruction *pInst) {
std::cout << std::endl;
} break;
case Kind::kUnreachable: {
std::cout << "Unreachable" << std::endl;
} break;
case Kind::kAlloca: {
auto allocaInst = dynamic_cast<AllocaInst *>(pInst);
std::cout << "%" << allocaInst->getName() << " = alloca ";
@ -411,17 +416,6 @@ void SysYPrinter::printInst(Instruction *pInst) {
auto allocatedType = allocaInst->getAllocatedType();
printType(allocatedType);
// 仍然打印维度信息,如果存在的话
if (allocaInst->getNumDims() > 0) {
std::cout << ", ";
for (size_t i = 0; i < allocaInst->getNumDims(); i++) {
if (i > 0) std::cout << ", ";
printType(Type::getIntType()); // 维度大小通常是 i32 类型
std::cout << " ";
printValue(allocaInst->getDim(i));
}
}
std::cout << ", align 4" << std::endl;
} break;
@ -434,17 +428,6 @@ void SysYPrinter::printInst(Instruction *pInst) {
std::cout << " ";
printValue(loadInst->getPointer()); // 要加载的地址
// 仍然打印索引信息,如果存在的话
if (loadInst->getNumIndices() > 0) {
std::cout << ", indices "; // 或者其他分隔符,取决于你期望的格式
for (size_t i = 0; i < loadInst->getNumIndices(); i++) {
if (i > 0) std::cout << ", ";
printType(loadInst->getIndex(i)->getType());
std::cout << " ";
printValue(loadInst->getIndex(i));
}
}
std::cout << ", align 4" << std::endl;
} break;
@ -459,16 +442,6 @@ void SysYPrinter::printInst(Instruction *pInst) {
std::cout << " ";
printValue(storeInst->getPointer()); // 目标地址
// 仍然打印索引信息,如果存在的话
if (storeInst->getNumIndices() > 0) {
std::cout << ", indices "; // 或者其他分隔符
for (size_t i = 0; i < storeInst->getNumIndices(); i++) {
if (i > 0) std::cout << ", ";
printType(storeInst->getIndex(i)->getType());
std::cout << " ";
printValue(storeInst->getIndex(i));
}
}
std::cout << ", align 4" << std::endl;
} break;