From 206a0af424627e0feb398d70d5204df916d9d745 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Wed, 30 Jul 2025 16:33:56 +0800 Subject: [PATCH 01/16] =?UTF-8?q?[midend-SCCP]=E6=9A=82=E5=AD=981?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Pass_ID_List.md | 154 +++++ src/include/midend/Pass/Optimize/SCCP.h | 317 ++++----- src/midend/Pass/Optimize/ SCCP.cpp | 872 ++++++++++++++++++++++++ 3 files changed, 1161 insertions(+), 182 deletions(-) create mode 100644 src/midend/Pass/Optimize/ SCCP.cpp diff --git a/Pass_ID_List.md b/Pass_ID_List.md index 5618060..009a0dd 100644 --- a/Pass_ID_List.md +++ b/Pass_ID_List.md @@ -18,6 +18,160 @@ Mem2Reg 遍的主要目标是将那些不必要的、只用于局部标量变量 我们的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(变量、指令结果等)的当前 SCCP Lattice 状态。 + +*ExecutableBlocks (set):** 存储在分析过程中被确定为可执行的基本块。 + +工作列表 (Worklists): + +cfgWorkList (queue>):** 存储待处理的控制流图(CFG)边。当一个块被标记为可执行时,它的后继边会被添加到这个列表。 + +*ssaWorkList (queue):** 存储待处理的 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 或独立的浮点常量存储来处理浮点数。 + # 后续优化可能涉及的改动 diff --git a/src/include/midend/Pass/Optimize/SCCP.h b/src/include/midend/Pass/Optimize/SCCP.h index 7db0a7b..8a16eb1 100644 --- a/src/include/midend/Pass/Optimize/SCCP.h +++ b/src/include/midend/Pass/Optimize/SCCP.h @@ -1,196 +1,149 @@ #pragma once -#include "IR.h" +#include "IR.h" // 假设这是你的 SysY IR 定义,包含 Value, Instruction, BasicBlock, Function, Module 等 +#include "Pass.h" // 包含 Pass 的基类定义,以及 AnalysisManager, IRBuilder +#include "SysYIROptUtils.h" // 假设包含 SysYIROptUtils::usedelete 等辅助函数 +#include   // For assert +#include // 引入 std::function 用于辅助函数 +#include // For DEBUG output +#include +#include +#include +#include +#include +#include // 引入 std::variant 用于 ConstVal + +using ConstVal = std::variant; // 定义一个变体类型,用于存储整数或浮点数常量 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 // 值->状态映射 - 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 Worklist; -static std::unordered_set Executable_Blocks; -static std::queue > Executable_Edges; -static std::map valueState; +// 用于表示 SSA 值的具体状态(包含格值和常量值) +// 新增枚举来区分常量的实际类型 +enum class ValueType { + Integer, + Float, + Unknown // 用于 Top 和 Bottom 状态 +}; -class SCCP { +struct SSAPValue { + LatticeVal state; + ConstVal 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 instWorkList; + // 存储需要重新评估的控制流边 (pair: from_block, to_block) + std::queue> edgeWorkList; + + // 格值映射:SSA Value 到其当前状态 + std::map valueState; + // 可执行基本块集合 + std::unordered_set executableBlocks; + // 追踪已访问的CFG边,防止重复添加 + std::unordered_set, 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); + // 辅助函数:对类型转换进行常量折叠 + SSAPValue ComputeConstant(CastInst *castInst, SSAPValue operandVal); + + // 主要优化阶段 + // 阶段1: 常量传播与折叠 + // 返回值表示在此阶段IR是否被修改 + bool PropagateConstants(Function *func); + // 阶段2: 控制流简化 + // 返回值表示在此阶段IR是否被修改 + bool SimplifyControlFlow(Function *func); + + // 辅助函数:处理单条指令(这包含了原来 computeLatticeValue 的大部分逻辑) + void ProcessInstruction(Instruction *inst); + // 辅助函数:处理单条控制流边 + void ProcessEdge(const std::pair &edge); + + // 控制流简化辅助函数 + // 查找所有可达的基本块 (基于常量条件) + std::unordered_set FindReachableBlocks(Function *func); + // 移除死块 + void RemoveDeadBlock(BasicBlock *bb, Function *func); + // 简化分支(将条件分支替换为无条件分支) + void SimplifyBranch(BranchInst *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 &edge); - void RemoveDeadBlock(BasicBlock *bb); - void UpdateState(Value *v, LatticeValue newState); - LatticeValue Meet(LatticeValue a, LatticeValue b); - LatticeValue GetValueState(Value *v); + // 运行 SCCP 优化 + // func: 当前要优化的函数 + // AM: 分析管理器,在 SCCP 中通常不需要获取其他分析结果,但可能需要使分析结果失效。 + // 返回值: 如果对函数进行了修改,则为 true + void run(Function *func, AnalysisManager &AM); }; -} // 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 &analysisDependencies, std::set &analysisInvalidations) const override; + void *getPassID() const override { return &ID; } +}; + +} // namespace sysy \ No newline at end of file diff --git a/src/midend/Pass/Optimize/ SCCP.cpp b/src/midend/Pass/Optimize/ SCCP.cpp new file mode 100644 index 0000000..d591765 --- /dev/null +++ b/src/midend/Pass/Optimize/ SCCP.cpp @@ -0,0 +1,872 @@ +#include "SCCP.h" +#include +#include +#include // For std::fmod, std::fabs +#include // 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(v)) { + if (constVal->getType()->isInt()) { + return SSAPValue(constVal->getInt()); + } else if (constVal->getType()->isFloat()) { + return SSAPValue(constVal->getFloat()); + } else { + 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(" << std::get(oldState.constantVal) << ")"; + else + std::cout << "Const(" << std::get(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(" << std::get(newState.constantVal) << ")"; + else + std::cout << "Const(" << std::get(newState.constantVal) << ")"; + } else + std::cout << "Bottom"; + std::cout << ")" << std::endl; + } + + valueState[v] = newState; + // 如果状态发生变化,将所有使用者添加到指令工作列表 + for (auto &use_ptr : v->getUses()) { + if (auto userInst = dynamic_cast(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); // 如果不是常量,则不能折叠 + } + + // 处理整数运算 + if (lhsVal.constant_type == ValueType::Integer && rhsVal.constant_type == ValueType::Integer) { + int lhs = std::get(lhsVal.constantVal); + int rhs = std::get(rhsVal.constantVal); + int result = 0; + bool is_comparison = false; + + 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: + is_comparison = true; + result = (lhs == rhs); + break; + case Instruction::kICmpNE: + is_comparison = true; + result = (lhs != rhs); + break; + case Instruction::kICmpGT: + is_comparison = true; + result = (lhs > rhs); + break; + case Instruction::kICmpGE: + is_comparison = true; + result = (lhs >= rhs); + break; + case Instruction::kICmpLT: + is_comparison = true; + result = (lhs < rhs); + break; + case Instruction::kICmpLE: + is_comparison = true; + 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); + } + // 处理浮点运算 + else if (lhsVal.constant_type == ValueType::Float && rhsVal.constant_type == ValueType::Float) { + float lhs = std::get(lhsVal.constantVal); + float rhs = std::get(rhsVal.constantVal); + float f_result = 0.0f; + int i_result = 0; // For comparison results + + switch (binaryInst->getKind()) { + case Instruction::kAdd: + f_result = lhs + rhs; + break; + case Instruction::kSub: + f_result = lhs - rhs; + break; + case Instruction::kMul: + f_result = lhs * rhs; + break; + case Instruction::kDiv: + if (rhs == 0.0f) + return SSAPValue(LatticeVal::Bottom); // 除零 + f_result = lhs / rhs; + break; + case Instruction::kRem: + if (rhs == 0.0f) + return SSAPValue(LatticeVal::Bottom); // 模零 + f_result = std::fmod(lhs, rhs); + break; // 浮点数取模 + case Instruction::kFCmpEQ: + i_result = (lhs == rhs); + return SSAPValue(i_result); + case Instruction::kFCmpNE: + i_result = (lhs != rhs); + return SSAPValue(i_result); + case Instruction::kFCmpGT: + i_result = (lhs > rhs); + return SSAPValue(i_result); + case Instruction::kFCmpGE: + i_result = (lhs >= rhs); + return SSAPValue(i_result); + case Instruction::kFCmpLT: + i_result = (lhs < rhs); + return SSAPValue(i_result); + case Instruction::kFCmpLE: + 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(operandVal.constantVal); + switch (unaryInst->getKind()) { + 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(operandVal.constantVal); + switch (unaryInst->getKind()) { + case Instruction::kFNeg: + return SSAPValue(-val); + case Instruction::kFNot: + return SSAPValue(static_cast(val == 0.0f)); // 浮点数非,0.0f 为真,其他为假 + default: + return SSAPValue(LatticeVal::Bottom); + } + } + return SSAPValue(LatticeVal::Bottom); +} + +// 辅助函数:对类型转换进行常量折叠 +SSAPValue SCCPContext::ComputeConstant(CastInst *castInst, SSAPValue operandVal) { + if (operandVal.state != LatticeVal::Constant) { + return SSAPValue(LatticeVal::Bottom); + } + + Type *destType = castInst->getType(); + + switch (castInst->getKind()) { + case Instruction::kZExt: + case Instruction::kSExt: + case Instruction::kTrunc: + // 这些通常是整数之间的转换,或者位模式转换。 + // 对于常量,如果操作数是整数,直接返回其值(假设IR正确处理了范围/截断) + if (operandVal.constant_type == ValueType::Integer && destType->isInt()) { + return SSAPValue(std::get(operandVal.constantVal)); + } + return SSAPValue(LatticeVal::Bottom); // 否则,保守处理 + case Instruction::kFtoI: + if (operandVal.constant_type == ValueType::Float && destType->isInt()) { + return SSAPValue(static_cast(std::get(operandVal.constantVal))); + } + return SSAPValue(LatticeVal::Bottom); + case Instruction::kItoF: + if (operandVal.constant_type == ValueType::Integer && destType->isFloat()) { + return SSAPValue(static_cast(std::get(operandVal.constantVal))); + } + return SSAPValue(LatticeVal::Bottom); + case Instruction::kBitFtoI: + if (operandVal.constant_type == ValueType::Float && destType->isInt()) { + // 执行浮点数到整数的位模式转换,需要重新解释内存 + float fval = std::get(operandVal.constantVal); + return SSAPValue(*reinterpret_cast(&fval)); + } + return SSAPValue(LatticeVal::Bottom); + case Instruction::kBitItoF: + if (operandVal.constant_type == ValueType::Integer && destType->isFloat()) { + // 执行整数到浮点数的位模式转换,需要重新解释内存 + int ival = std::get(operandVal.constantVal); + return SSAPValue(*reinterpret_cast(&ival)); + } + return SSAPValue(LatticeVal::Bottom); + default: + 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::kICmpGT: + case Instruction::kICmpGE: + case Instruction::kICmpLT: + case Instruction::kICmpLE: + case Instruction::kFCmpEQ: + case Instruction::kFCmpNE: + case Instruction::kFCmpGT: + case Instruction::kFCmpGE: + case Instruction::kFCmpLT: + case Instruction::kFCmpLE: + case Instruction::kAnd: + case Instruction::kOr: { + BinaryInst *binaryInst = static_cast(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(inst); + SSAPValue operand = GetValueState(unaryInst->getOperand(0)); + 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: + case Instruction::kItoF: + case Instruction::kZExt: + case Instruction::kSExt: + case Instruction::kTrunc: + case Instruction::kBitFtoI: + case Instruction::kBitItoF: { + CastInst *castInst = static_cast(inst); + SSAPValue operand = GetValueState(castInst->getOperand(0)); + if (operand.state == LatticeVal::Bottom) { + newState = SSAPValue(LatticeVal::Bottom); + } else if (operand.state == LatticeVal::Top) { + newState = SSAPValue(); // Top + } else { // 是常量 + newState = ComputeConstant(castInst, operand); + } + break; + } + case Instruction::kLoad: { + // 对于 Load 指令,除非我们有特殊的别名分析,否则假定为 Bottom + // 或者如果它加载的是一个已知常量地址的全局常量 + Value *ptr = inst->getOperand(0); + if (auto globalVal = dynamic_cast(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(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::kAlloc: + // Alloca 分配内存,返回一个指针,其内容是 Bottom + newState = SSAPValue(LatticeVal::Bottom); + break; + case Instruction::kBranch: + case Instruction::kReturn: + // 终结符指令不产生值 + newState = SSAPValue(); // 保持 Top + 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 (auto branchInst = dynamic_cast(inst)) { + if (branchInst->isCondBr()) { + 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(condVal.constantVal) != 0); + } else if (condVal.constant_type == ValueType::Float) { + condition_is_true = (std::get(condVal.constantVal) != 0.0f); + } + + if (condition_is_true) { + AddEdgeToWorkList(branchInst->getParent(), branchInst->getTrueBlock()); + } else { + AddEdgeToWorkList(branchInst->getParent(), branchInst->getFalseBlock()); + } + } else { // 条件是 Top 或 Bottom,两条路径都可能 + AddEdgeToWorkList(branchInst->getParent(), branchInst->getTrueBlock()); + AddEdgeToWorkList(branchInst->getParent(), branchInst->getFalseBlock()); + } + } else { // 无条件分支 + AddEdgeToWorkList(branchInst->getParent(), branchInst->getTrueBlock()); + } + } + } +} + +// 辅助函数:处理单条控制流边 +void SCCPContext::ProcessEdge(const std::pair &edge) { + BasicBlock *fromBB = edge.first; + BasicBlock *toBB = edge.second; + + MarkBlockExecutable(toBB); + + // 对于目标块中的所有 Phi 指令,重新评估其值,因为可能有新的前驱被激活 + for (auto &inst_ptr : toBB->getInstructions()) { + if (dynamic_cast(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 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(ssaPVal.constantVal)); + } else if (ssaPVal.constant_type == ValueType::Float) { + constVal = ConstantFloating::get(std::get(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(ssaPVal.constantVal); + else + std::cout << std::get(ssaPVal.constantVal); + std::cout << std::endl; + } + inst->replaceAllUsesWith(constVal); + instsToDelete.push_back(inst); + it = bb->removeInst(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(opVal.constantVal)); + } else if (opVal.constant_type == ValueType::Float) { + constOp = ConstantFloating::get(std::get(opVal.constantVal)); + } else { + constOp = UndefinedValue::get(operand->getType()); + } + + if (constOp != operand) { + inst->setOperand(i, constOp); + changed = true; + } + } + } + ++it; + } + } + } + + // 实际删除指令 + for (Instruction *inst : instsToDelete) { + if (inst->getParent() && !SysYIROptUtils::usedelete(inst)) { + // 如果 still in parent and not deleted by usedelete, implies issues or non-instruction values. + // For SCCP, if replaced, it should have no uses. + if (DEBUG) { + std::cerr << "Warning: Instruction " << inst->getName() << " was not fully deleted." << std::endl; + } + } + } + return changed; +} + +// 阶段2: 控制流简化 +bool SCCPContext::SimplifyControlFlow(Function *func) { + bool changed = false; + + // 重新确定可达块,因为 PropagateConstants 可能改变了分支条件 + std::unordered_set newReachableBlocks = FindReachableBlocks(func); + + // 移除不可达块 + std::vector 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 (auto branchInst = dynamic_cast(terminator)) { + if (branchInst->isCondBr()) { + 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(condVal.constantVal) != 0); + } else if (condVal.constant_type == ValueType::Float) { + condition_is_true = (std::get(condVal.constantVal) != 0.0f); + } + SimplifyBranch(branchInst, condition_is_true); + changed = true; + } + } + } + } + + return changed; +} + +// 查找所有可达的基本块 (基于常量条件) +std::unordered_set SCCPContext::FindReachableBlocks(Function *func) { + std::unordered_set reachable; + std::queue 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 (auto branchInst = dynamic_cast(terminator)) { + if (branchInst->isCondBr()) { + 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(condVal.constantVal) != 0); + } else if (condVal.constant_type == ValueType::Float) { + condition_is_true = (std::get(condVal.constantVal) != 0.0f); + } + + if (condition_is_true) { + BasicBlock *trueBlock = branchInst->getTrueBlock(); + if (reachable.find(trueBlock) == reachable.end()) { + reachable.insert(trueBlock); + q.push(trueBlock); + } + } else { + BasicBlock *falseBlock = branchInst->getFalseBlock(); + 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 { // 无条件分支 + BasicBlock *targetBlock = branchInst->getTrueBlock(); + if (reachable.find(targetBlock) == reachable.end()) { + reachable.insert(targetBlock); + q.push(targetBlock); + } + } + } else if (auto retInst = dynamic_cast(terminator)) { + // ReturnInst 没有后继,不需要处理 + } + } + return reachable; +} + +// 移除死块 +void SCCPContext::RemoveDeadBlock(BasicBlock *bb, Function *func) { + if (DEBUG) { + std::cout << "Removing dead block: " << bb->getName() << std::endl; + } + // 首先更新其所有前驱的终结指令,移除指向死块的边 + std::vector preds_to_remove; + for (auto &pred_weak_ptr : bb->getPredecessors()) { + if (auto pred = pred_weak_ptr.lock()) { // 确保前驱块仍然存在 + preds_to_remove.push_back(pred.get()); + } + } + for (BasicBlock *pred : preds_to_remove) { + UpdateTerminator(pred, bb); + } + + // 移除其后继的 Phi 节点的入边 + for (auto succ : bb->getSuccessors()) { + RemovePhiIncoming(succ, bb); + } + + func->removeBasicBlock(bb); +} + +// 简化分支(将条件分支替换为无条件分支) +void SCCPContext::SimplifyBranch(BranchInst *brInst, bool condVal) { + BasicBlock *parentBB = brInst->getParent(); + BasicBlock *trueBlock = brInst->getTrueBlock(); + BasicBlock *falseBlock = brInst->getFalseBlock(); + + if (DEBUG) { + std::cout << "Simplifying branch in " << parentBB->getName() << ": cond is " << (condVal ? "true" : "false") + << std::endl; + } + + builder->setInsertPoint(parentBB, brInst->getIterator()); + if (condVal) { // 条件为真,跳转到真分支 + builder->createBranchInst(trueBlock); + // 移除旧的条件分支指令 + SysYIROptUtils::usedelete(brInst); + // 移除与假分支的连接 + parentBB->removeSuccessor(falseBlock); + falseBlock->removePredecessor(parentBB); + // 移除假分支中 Phi 节点的来自当前块的入边 + RemovePhiIncoming(falseBlock, parentBB); + } else { // 条件为假,跳转到假分支 + builder->createBranchInst(falseBlock); + // 移除旧的条件分支指令 + SysYIROptUtils::usedelete(brInst); + // 移除与真分支的连接 + parentBB->removeSuccessor(trueBlock); + trueBlock->removePredecessor(parentBB); + // 移除真分支中 Phi 节点的来自当前块的入边 + RemovePhiIncoming(trueBlock, parentBB); + } +} + +// 更新前驱块的终结指令(当一个后继块被移除时) +void SCCPContext::UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc) { + Instruction *terminator = predBB->terminator().get(); + if (!terminator) + return; + + // 对于 BranchInst,如果其某个目标是 removedSucc,则需要更新它 + if (auto branchInst = dynamic_cast(terminator)) { + if (branchInst->isCondBr()) { + // 如果 removedSucc 是真分支,则条件分支应指向假分支 + if (branchInst->getTrueBlock() == removedSucc) { + // 如果另一个分支也死了,则整个分支是死代码,由其他阶段移除 + // 这里我们简化为无条件跳转到另一个仍然可达的分支 + builder->setInsertPoint(predBB, branchInst->getIterator()); + builder->createBranchInst(branchInst->getFalseBlock()); + SysYIROptUtils::usedelete(branchInst); + predBB->removeSuccessor(removedSucc); // 从前驱的后继列表中移除 + } + // 如果 removedSucc 是假分支,则条件分支应指向真分支 + else if (branchInst->getFalseBlock() == removedSucc) { + builder->setInsertPoint(predBB, branchInst->getIterator()); + builder->createBranchInst(branchInst->getTrueBlock()); + SysYIROptUtils::usedelete(branchInst); + predBB->removeSuccessor(removedSucc); // 从前驱的后继列表中移除 + } + } else { // 无条件分支 + // 如果目标是 removedSucc,这通常意味着整个 predBB 也是死块 + // 或者需要一个 unreachable 指令 + if (branchInst->getTrueBlock() == removedSucc) { + // 暂时不创建 unreachable,因为可能死块会被整个移除 + // 或者留待后续简化。只移除后继连接。 + SysYIROptUtils::usedelete(branchInst); // 先删除指令 + predBB->removeSuccessor(removedSucc); + builder->setInsertPoint(predBB, predBB->end()); // 在块末尾插入 + builder->createUnreachableInst(); // 插入一个不可达指令,标记代码路径结束 + } + } + } + // ReturnInst 和其他指令不受影响 +} + +// 移除 Phi 节点的入边(当其前驱块被移除时) +void SCCPContext::RemovePhiIncoming(BasicBlock *phiParentBB, BasicBlock *removedPred) { + for (auto &inst_ptr : phiParentBB->getInstructions()) { + if (auto phi = dynamic_cast(inst_ptr.get())) { + phi->removeIncomingValue(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); + // SCCPContext::run 内部负责管理 changed 状态并执行优化。 + // 这里我们无法直接返回 context.run 的 `changed` 值, + // 因为 run 是 void。通常会通过 context 的一个成员来跟踪。 + // 或者,runOnFunction 负责判断是否发生了变化。 + // 目前,为简单起见,假设 SCCPContext::run 确实执行了修改,并总是返回 true, + // 这在实际编译器中可能需要更精确的追踪。 + // 更好的做法是让 run 返回 bool. + // 由于用户提供的run是void, 且外部无法直接访问context的changed变量,我们暂时保守返回true。 + return true; +} + +void SCCP::getAnalysisUsage(std::set &analysisDependencies, std::set &analysisInvalidations) const { + // SCCP 不依赖其他分析,但它会改变 IR,因此会使许多分析失效 + // 例如:DominatorTree, CFG analysis, LI, ... + analysisInvalidations.insert(nullptr); // 表示使所有默认分析失效 +} + +} // namespace sysy \ No newline at end of file From 6868f638d73d56a5dd7c906cab2758169d228472 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 31 Jul 2025 16:57:47 +0800 Subject: [PATCH 02/16] =?UTF-8?q?[midend-SCCP]=E5=A2=9E=E5=8A=A0=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E5=9D=97=E5=AF=B9=E7=9A=84=E5=93=88=E5=B8=8C=E5=80=BC?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=88=A0=E9=99=A4use=E5=85=B3=E7=B3=BB=E5=92=8C=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E7=9A=84=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Pass_ID_List.md | 10 ++++++++- .../midend/Pass/Optimize/SysYIROptUtils.h | 21 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/Pass_ID_List.md b/Pass_ID_List.md index 009a0dd..12cee1d 100644 --- a/Pass_ID_List.md +++ b/Pass_ID_List.md @@ -179,4 +179,12 @@ Branch 和 Return 指令: 这些是终结符指令,不产生一个可用于其 好处:优化友好性,方便mem2reg提升 目前没有实现这个机制,如果想要实现首先解决同一函数不同域的同名变量命名区分 -需要保证符号表能正确维护域中的局部变量 \ No newline at end of file +需要保证符号表能正确维护域中的局部变量 + + +# 关于中端优化提升编译器性能的TODO + +## usedelete_withinstdelte方法 + +这个方法删除了use关系并移除了指令,逻辑是根据Instruction* inst去find对应的迭代器并erase +有些情况下外部持有迭代器和inst,可以省略find过程 \ No newline at end of file diff --git a/src/include/midend/Pass/Optimize/SysYIROptUtils.h b/src/include/midend/Pass/Optimize/SysYIROptUtils.h index 1b764ec..1ee1ddc 100644 --- a/src/include/midend/Pass/Optimize/SysYIROptUtils.h +++ b/src/include/midend/Pass/Optimize/SysYIROptUtils.h @@ -10,6 +10,18 @@ namespace sysy { class SysYIROptUtils{ public: + struct PairHash { + template + std::size_t operator () (const std::pair& p) const { + auto h1 = std::hash{}(p.first); + auto h2 = std::hash{}(p.second); + + // 简单的组合哈希值,可以更复杂以减少冲突 + // 使用 boost::hash_combine 的简化版本 + return h1 ^ (h2 << 1); + } + }; + // 仅仅删除use关系 static void usedelete(Instruction *instr) { for (auto &use : instr->getOperands()) { @@ -18,6 +30,15 @@ public: } } + // 删除use关系并删除指令 + static void usedelete_withinstdelte(Instruction *instr) { + for (auto &use : instr->getOperands()) { + Value* val = use->getValue(); + val->removeUse(use); + } + instr->getParent()->removeInst(instr); + } + // 判断是否是全局变量 static bool isGlobal(Value *val) { auto gval = dynamic_cast(val); From 520ebd96f0dce957517da573dc6f8c01b5e8c684 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 31 Jul 2025 16:59:22 +0800 Subject: [PATCH 03/16] =?UTF-8?q?[midend-SCCP]=E5=A2=9E=E5=8A=A0=E4=B8=8D?= =?UTF-8?q?=E5=8F=AF=E8=BE=BE=E6=8C=87=E4=BB=A4=EF=BC=8C=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E8=B7=B3=E8=BD=AC=E6=8C=87=E4=BB=A4=E5=8F=82=E6=95=B0=EF=BC=88?= =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E5=9D=97args=E5=B7=B2=E5=BC=83=E7=94=A8?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E4=B8=BA{}=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/midend/IR.h | 26 ++++++++++++++++++-------- src/include/midend/IRBuilder.h | 10 ++++++++-- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/include/midend/IR.h b/src/include/midend/IR.h index 901a3b7..91d7f72 100644 --- a/src/include/midend/IR.h +++ b/src/include/midend/IR.h @@ -695,15 +695,13 @@ class Instruction : public User { kCondBr = 0x1UL << 30, kBr = 0x1UL << 31, kReturn = 0x1UL << 32, + kUnreachable = 0x1UL << 32, ///< Unreachable instruction, used for optimization purposes // 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, @@ -852,6 +850,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; } @@ -894,6 +893,9 @@ class PhiInst : public Instruction { public: Value* getValue(unsigned k) const {return getOperand(2 * k);} ///< 获取位置为k的值 BasicBlock* getBlock(unsigned k) const {return dynamic_cast(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(getOperand(2 * k + 1));} auto& getincomings() const {return blk2val;} ///< 获取所有的基本块和对应的值 @@ -1117,6 +1119,14 @@ public: }; // 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; diff --git a/src/include/midend/IRBuilder.h b/src/include/midend/IRBuilder.h index 760ef85..f761d57 100644 --- a/src/include/midend/IRBuilder.h +++ b/src/include/midend/IRBuilder.h @@ -239,19 +239,25 @@ class IRBuilder { block->getInstructions().emplace(position, inst); return inst; } ///< 创建return指令 - UncondBrInst * createUncondBrInst(BasicBlock *thenBlock, const std::vector &args) { + UncondBrInst * createUncondBrInst(BasicBlock *thenBlock, const std::vector &args = {}) { auto inst = new UncondBrInst(thenBlock, args, block); assert(inst); block->getInstructions().emplace(position, inst); return inst; } ///< 创建无条件指令 CondBrInst * createCondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock, - const std::vector &thenArgs, const std::vector &elseArgs) { + const std::vector &thenArgs = {}, const std::vector &elseArgs = {}) { auto inst = new CondBrInst(condition, thenBlock, elseBlock, thenArgs, elseArgs, block); assert(inst); block->getInstructions().emplace(position, inst); return inst; } ///< 创建条件跳转指令 + 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::vector &dims = {}, const std::string &name = "") { auto inst = new AllocaInst(type, dims, block, name); assert(inst); From 61768fa180dd89591b10eb285b26829231f4c179 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 31 Jul 2025 17:00:02 +0800 Subject: [PATCH 04/16] =?UTF-8?q?[midend-SCCP]=E5=A4=B4=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=9E=84=E6=9E=B6=E5=AE=8C=E6=AF=95=EF=BC=8Ccpp=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E9=83=A8=E5=88=86=E6=8A=A5=E9=94=99=E6=9A=82=E6=97=B6?= =?UTF-8?q?=E4=B8=8Dcommit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/midend/Pass/Optimize/SCCP.h | 50 ++++++++++--------------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/src/include/midend/Pass/Optimize/SCCP.h b/src/include/midend/Pass/Optimize/SCCP.h index 8a16eb1..667ee51 100644 --- a/src/include/midend/Pass/Optimize/SCCP.h +++ b/src/include/midend/Pass/Optimize/SCCP.h @@ -1,30 +1,27 @@ #pragma once -#include "IR.h" // 假设这是你的 SysY IR 定义,包含 Value, Instruction, BasicBlock, Function, Module 等 -#include "Pass.h" // 包含 Pass 的基类定义,以及 AnalysisManager, IRBuilder -#include "SysYIROptUtils.h" // 假设包含 SysYIROptUtils::usedelete 等辅助函数 -#include   // For assert -#include // 引入 std::function 用于辅助函数 -#include // For DEBUG output +#include "IR.h" +#include "Pass.h" +#include "SysYIROptUtils.h" +#include +#include #include #include #include #include #include -#include // 引入 std::variant 用于 ConstVal - -using ConstVal = std::variant; // 定义一个变体类型,用于存储整数或浮点数常量 +#include +#include namespace sysy { // 定义三值格 (Three-valued Lattice) 的状态 enum class LatticeVal { -Top, // ⊤ (未知 / 未初始化) -Constant, // c (常量) -Bottom// ⊥ (不确定 / 变化 / 未定义) + Top, // ⊤ (未知 / 未初始化) + Constant, // c (常量) + Bottom // ⊥ (不确定 / 变化 / 未定义) }; -// 用于表示 SSA 值的具体状态(包含格值和常量值) // 新增枚举来区分常量的实际类型 enum class ValueType { Integer, @@ -32,10 +29,11 @@ enum class ValueType { Unknown // 用于 Top 和 Bottom 状态 }; +// 用于表示 SSA 值的具体状态(包含格值和常量值) struct SSAPValue { LatticeVal state; - ConstVal constantVal; // 使用 std::variant 存储 int 或 float - ValueType constant_type; // 记录常量是整数还是浮点数 + std::variant constantVal; // 使用 std::variant 存储 int 或 float + ValueType constant_type; // 记录常量是整数还是浮点数 // 默认构造函数,初始化为 Top SSAPValue() : state(LatticeVal::Top), constantVal(0), constant_type(ValueType::Unknown) {} @@ -53,9 +51,8 @@ struct SSAPValue { if (state != other.state) return false; if (state == LatticeVal::Constant) { - if (constant_type != other.constant_type) - return false; // 类型必须匹配 - return constantVal == other.constantVal; // std::variant 会比较内部值 + if (constant_type != other.constant_type) return false; // 类型必须匹配 + return constantVal == other.constantVal; // std::variant 会比较内部值 } return true; // Top == Top, Bottom == Bottom } @@ -77,8 +74,8 @@ private: std::map valueState; // 可执行基本块集合 std::unordered_set executableBlocks; - // 追踪已访问的CFG边,防止重复添加 - std::unordered_set, SysYIROptUtils::PairHash> visitedCFGEdges; + // 追踪已访问的CFG边,防止重复添加,使用 SysYIROptUtils::PairHash + std::unordered_set, SysYIROptUtils::PairHash> visitedCFGEdges; // 辅助函数:格操作 Meet SSAPValue Meet(const SSAPValue &a, const SSAPValue &b); @@ -89,24 +86,20 @@ private: // 辅助函数:将边加入边工作列表,并更新可执行块 void AddEdgeToWorkList(BasicBlock *fromBB, BasicBlock *toBB); // 辅助函数:标记一个块为可执行 - void MarkBlockExecutable(BasicBlock *block); + void MarkBlockExecutable(BasicBlock* block); // 辅助函数:对二元操作进行常量折叠 SSAPValue ComputeConstant(BinaryInst *binaryinst, SSAPValue lhsVal, SSAPValue rhsVal); // 辅助函数:对一元操作进行常量折叠 SSAPValue ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVal); - // 辅助函数:对类型转换进行常量折叠 - SSAPValue ComputeConstant(CastInst *castInst, SSAPValue operandVal); // 主要优化阶段 // 阶段1: 常量传播与折叠 - // 返回值表示在此阶段IR是否被修改 bool PropagateConstants(Function *func); // 阶段2: 控制流简化 - // 返回值表示在此阶段IR是否被修改 bool SimplifyControlFlow(Function *func); - // 辅助函数:处理单条指令(这包含了原来 computeLatticeValue 的大部分逻辑) + // 辅助函数:处理单条指令 void ProcessInstruction(Instruction *inst); // 辅助函数:处理单条控制流边 void ProcessEdge(const std::pair &edge); @@ -117,7 +110,7 @@ private: // 移除死块 void RemoveDeadBlock(BasicBlock *bb, Function *func); // 简化分支(将条件分支替换为无条件分支) - void SimplifyBranch(BranchInst *brInst, bool condVal); // 修改为 BranchInst,更通用 + void SimplifyBranch(CondBrInst*brInst, bool condVal); // 保持 BranchInst // 更新前驱块的终结指令(当一个后继块被移除时) void UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc); // 移除 Phi 节点的入边(当其前驱块被移除时) @@ -127,9 +120,6 @@ public: SCCPContext(IRBuilder *builder) : builder(builder) {} // 运行 SCCP 优化 - // func: 当前要优化的函数 - // AM: 分析管理器,在 SCCP 中通常不需要获取其他分析结果,但可能需要使分析结果失效。 - // 返回值: 如果对函数进行了修改,则为 true void run(Function *func, AnalysisManager &AM); }; From 35691ab7bce555cb40608fef4f08a9edaefacae6 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 31 Jul 2025 17:19:57 +0800 Subject: [PATCH 05/16] =?UTF-8?q?[midend-SCCP]=E4=B8=BA=E8=B7=B3=E8=BD=AC?= =?UTF-8?q?=E6=8C=87=E4=BB=A4=E5=A2=9E=E5=8A=A0getSuccessors=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/midend/IR.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/include/midend/IR.h b/src/include/midend/IR.h index 91d7f72..2902c64 100644 --- a/src/include/midend/IR.h +++ b/src/include/midend/IR.h @@ -1074,6 +1074,16 @@ public: auto getArguments() const { return make_range(std::next(operand_begin()), operand_end()); } + std::vector getSuccessors() const { + std::vector succs; + // 假设无条件分支的目标块是它的第一个操作数 + if (getNumOperands() > 0) { + if (auto target_bb = dynamic_cast(getOperand(0))) { + succs.push_back(target_bb); + } + } + return succs; + } }; // class UncondBrInst @@ -1105,6 +1115,20 @@ public: BasicBlock* getElseBlock() const { return dynamic_cast(getOperand(2)); } + std::vector getSuccessors() const { + std::vector 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; + } // auto getThenArguments() const { // auto begin = std::next(operand_begin(), 3); // // auto end = std::next(begin, getThenBlock()->getNumArguments()); From de0f8422e97256e2d201ae039499bfd63973347c Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 31 Jul 2025 17:29:34 +0800 Subject: [PATCH 06/16] =?UTF-8?q?[midend-SCCP]=E6=B2=A1=E6=9C=89=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E6=8A=A5=E9=94=99=E4=BD=86=E6=98=AFSegmemtation=20fal?= =?UTF-8?q?ut?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/midend/CMakeLists.txt | 1 + .../Pass/Optimize/{ SCCP.cpp => SCCP.cpp} | 389 +++++++++--------- src/midend/Pass/Pass.cpp | 6 +- 3 files changed, 200 insertions(+), 196 deletions(-) rename src/midend/Pass/Optimize/{ SCCP.cpp => SCCP.cpp} (72%) diff --git a/src/midend/CMakeLists.txt b/src/midend/CMakeLists.txt index 4830893..3532818 100644 --- a/src/midend/CMakeLists.txt +++ b/src/midend/CMakeLists.txt @@ -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 ) # 包含中端模块所需的头文件路径 diff --git a/src/midend/Pass/Optimize/ SCCP.cpp b/src/midend/Pass/Optimize/SCCP.cpp similarity index 72% rename from src/midend/Pass/Optimize/ SCCP.cpp rename to src/midend/Pass/Optimize/SCCP.cpp index d591765..6c492dc 100644 --- a/src/midend/Pass/Optimize/ SCCP.cpp +++ b/src/midend/Pass/Optimize/SCCP.cpp @@ -32,18 +32,25 @@ SSAPValue SCCPContext::Meet(const SSAPValue &a, const SSAPValue &b) { SSAPValue SCCPContext::GetValueState(Value *v) { if (auto constVal = dynamic_cast(v)) { + // 特殊处理 UndefinedValue:将其视为 Bottom + if (dynamic_cast(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 { - return SSAPValue(LatticeVal::Bottom); // 其他类型常量,如指针,暂时不传播 + // 对于其他 ConstantValue 类型(例如,ConstantArray 等), + // 如果它们的具体值不能用于标量常量传播,则保守地视为 Bottom。 + return SSAPValue(LatticeVal::Bottom); } } if (valueState.count(v)) { return valueState[v]; } - return SSAPValue(); // 默认构造函数初始化为 Top + return SSAPValue(); // 默认初始化为 Top } void SCCPContext::UpdateState(Value *v, SSAPValue newState) { @@ -115,12 +122,11 @@ SSAPValue SCCPContext::ComputeConstant(BinaryInst *binaryInst, SSAPValue lhsVal, 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(lhsVal.constantVal); int rhs = std::get(rhsVal.constantVal); int result = 0; - bool is_comparison = false; switch (binaryInst->getKind()) { case Instruction::kAdd: @@ -143,29 +149,23 @@ SSAPValue SCCPContext::ComputeConstant(BinaryInst *binaryInst, SSAPValue lhsVal, result = lhs % rhs; break; case Instruction::kICmpEQ: - is_comparison = true; result = (lhs == rhs); break; case Instruction::kICmpNE: - is_comparison = true; result = (lhs != rhs); break; - case Instruction::kICmpGT: - is_comparison = true; - result = (lhs > rhs); - break; - case Instruction::kICmpGE: - is_comparison = true; - result = (lhs >= rhs); - break; case Instruction::kICmpLT: - is_comparison = true; result = (lhs < rhs); break; + case Instruction::kICmpGT: + result = (lhs > rhs); + break; case Instruction::kICmpLE: - is_comparison = true; result = (lhs <= rhs); break; + case Instruction::kICmpGE: + result = (lhs >= rhs); + break; case Instruction::kAnd: result = (lhs && rhs); break; @@ -173,11 +173,11 @@ SSAPValue SCCPContext::ComputeConstant(BinaryInst *binaryInst, SSAPValue lhsVal, result = (lhs || rhs); break; default: - return SSAPValue(LatticeVal::Bottom); // 未知二元操作 + 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(lhsVal.constantVal); float rhs = std::get(rhsVal.constantVal); @@ -185,45 +185,41 @@ SSAPValue SCCPContext::ComputeConstant(BinaryInst *binaryInst, SSAPValue lhsVal, int i_result = 0; // For comparison results switch (binaryInst->getKind()) { - case Instruction::kAdd: + case Instruction::kFAdd: f_result = lhs + rhs; break; - case Instruction::kSub: + case Instruction::kFSub: f_result = lhs - rhs; break; - case Instruction::kMul: + case Instruction::kFMul: f_result = lhs * rhs; break; - case Instruction::kDiv: + case Instruction::kFDiv: if (rhs == 0.0f) return SSAPValue(LatticeVal::Bottom); // 除零 f_result = lhs / rhs; break; - case Instruction::kRem: - if (rhs == 0.0f) - return SSAPValue(LatticeVal::Bottom); // 模零 - f_result = std::fmod(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::kFCmpGT: - i_result = (lhs > rhs); - return SSAPValue(i_result); - case Instruction::kFCmpGE: - 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(LatticeVal::Bottom); // 未知或不匹配的浮点二元操作 } return SSAPValue(f_result); } @@ -261,53 +257,6 @@ SSAPValue SCCPContext::ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVa return SSAPValue(LatticeVal::Bottom); } -// 辅助函数:对类型转换进行常量折叠 -SSAPValue SCCPContext::ComputeConstant(CastInst *castInst, SSAPValue operandVal) { - if (operandVal.state != LatticeVal::Constant) { - return SSAPValue(LatticeVal::Bottom); - } - - Type *destType = castInst->getType(); - - switch (castInst->getKind()) { - case Instruction::kZExt: - case Instruction::kSExt: - case Instruction::kTrunc: - // 这些通常是整数之间的转换,或者位模式转换。 - // 对于常量,如果操作数是整数,直接返回其值(假设IR正确处理了范围/截断) - if (operandVal.constant_type == ValueType::Integer && destType->isInt()) { - return SSAPValue(std::get(operandVal.constantVal)); - } - return SSAPValue(LatticeVal::Bottom); // 否则,保守处理 - case Instruction::kFtoI: - if (operandVal.constant_type == ValueType::Float && destType->isInt()) { - return SSAPValue(static_cast(std::get(operandVal.constantVal))); - } - return SSAPValue(LatticeVal::Bottom); - case Instruction::kItoF: - if (operandVal.constant_type == ValueType::Integer && destType->isFloat()) { - return SSAPValue(static_cast(std::get(operandVal.constantVal))); - } - return SSAPValue(LatticeVal::Bottom); - case Instruction::kBitFtoI: - if (operandVal.constant_type == ValueType::Float && destType->isInt()) { - // 执行浮点数到整数的位模式转换,需要重新解释内存 - float fval = std::get(operandVal.constantVal); - return SSAPValue(*reinterpret_cast(&fval)); - } - return SSAPValue(LatticeVal::Bottom); - case Instruction::kBitItoF: - if (operandVal.constant_type == ValueType::Integer && destType->isFloat()) { - // 执行整数到浮点数的位模式转换,需要重新解释内存 - int ival = std::get(operandVal.constantVal); - return SSAPValue(*reinterpret_cast(&ival)); - } - return SSAPValue(LatticeVal::Bottom); - default: - return SSAPValue(LatticeVal::Bottom); - } -} - // 辅助函数:处理单条指令 void SCCPContext::ProcessInstruction(Instruction *inst) { SSAPValue oldState = GetValueState(inst); @@ -333,16 +282,20 @@ void SCCPContext::ProcessInstruction(Instruction *inst) { case Instruction::kRem: case Instruction::kICmpEQ: case Instruction::kICmpNE: - case Instruction::kICmpGT: - case Instruction::kICmpGE: 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::kFCmpGT: - case Instruction::kFCmpGE: case Instruction::kFCmpLT: + case Instruction::kFCmpGT: case Instruction::kFCmpLE: + case Instruction::kFCmpGE: case Instruction::kAnd: case Instruction::kOr: { BinaryInst *binaryInst = static_cast(inst); @@ -363,7 +316,7 @@ void SCCPContext::ProcessInstruction(Instruction *inst) { case Instruction::kFNeg: case Instruction::kFNot: { UnaryInst *unaryInst = static_cast(inst); - SSAPValue operand = GetValueState(unaryInst->getOperand(0)); + SSAPValue operand = GetValueState(unaryInst->getOperand()); if (operand.state == LatticeVal::Bottom) { newState = SSAPValue(LatticeVal::Bottom); } else if (operand.state == LatticeVal::Top) { @@ -373,21 +326,50 @@ void SCCPContext::ProcessInstruction(Instruction *inst) { } break; } - case Instruction::kFtoI: - case Instruction::kItoF: - case Instruction::kZExt: - case Instruction::kSExt: - case Instruction::kTrunc: - case Instruction::kBitFtoI: - case Instruction::kBitItoF: { - CastInst *castInst = static_cast(inst); - SSAPValue operand = GetValueState(castInst->getOperand(0)); - if (operand.state == LatticeVal::Bottom) { + // 直接处理类型转换指令 + case Instruction::kFtoI: { + SSAPValue operand = GetValueState(inst->getOperand(0)); + if (operand.state == LatticeVal::Constant && operand.constant_type == ValueType::Float) { + newState = SSAPValue(static_cast(std::get(operand.constantVal))); + } else if (operand.state == LatticeVal::Bottom) { newState = SSAPValue(LatticeVal::Bottom); - } else if (operand.state == LatticeVal::Top) { - newState = SSAPValue(); // Top - } else { // 是常量 - newState = ComputeConstant(castInst, operand); + } 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(std::get(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(operand.constantVal); + newState = SSAPValue(*reinterpret_cast(&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(operand.constantVal); + newState = SSAPValue(*reinterpret_cast(&ival)); + } else if (operand.state == LatticeVal::Bottom) { + newState = SSAPValue(LatticeVal::Bottom); + } else { // Top + newState = SSAPValue(); } break; } @@ -444,15 +426,20 @@ void SCCPContext::ProcessInstruction(Instruction *inst) { newState = phiResult; break; } - case Instruction::kAlloc: + case Instruction::kAlloca: // 对应 kAlloca // Alloca 分配内存,返回一个指针,其内容是 Bottom newState = SSAPValue(LatticeVal::Bottom); break; - case Instruction::kBranch: - case Instruction::kReturn: + case Instruction::kBr: // 对应 kBr + case Instruction::kCondBr: // 对应 kCondBr + case Instruction::kReturn: // 对应 kReturn // 终结符指令不产生值 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; @@ -464,8 +451,8 @@ void SCCPContext::ProcessInstruction(Instruction *inst) { // 特殊处理终结符指令,影响 CFG 边的可达性 if (inst->isTerminator()) { - if (auto branchInst = dynamic_cast(inst)) { - if (branchInst->isCondBr()) { + if (auto branchInst = dynamic_cast(inst)) { + if (branchInst->isCondBr()) { // 使用 kCondBr SSAPValue condVal = GetValueState(branchInst->getOperand(0)); if (condVal.state == LatticeVal::Constant) { bool condition_is_true = false; @@ -476,16 +463,16 @@ void SCCPContext::ProcessInstruction(Instruction *inst) { } if (condition_is_true) { - AddEdgeToWorkList(branchInst->getParent(), branchInst->getTrueBlock()); + AddEdgeToWorkList(branchInst->getParent(), branchInst->getThenBlock()); } else { - AddEdgeToWorkList(branchInst->getParent(), branchInst->getFalseBlock()); + AddEdgeToWorkList(branchInst->getParent(), branchInst->getElseBlock()); } } else { // 条件是 Top 或 Bottom,两条路径都可能 - AddEdgeToWorkList(branchInst->getParent(), branchInst->getTrueBlock()); - AddEdgeToWorkList(branchInst->getParent(), branchInst->getFalseBlock()); + AddEdgeToWorkList(branchInst->getParent(), branchInst->getThenBlock()); + AddEdgeToWorkList(branchInst->getParent(), branchInst->getElseBlock()); } - } else { // 无条件分支 - AddEdgeToWorkList(branchInst->getParent(), branchInst->getTrueBlock()); + } else { // 无条件分支 (kBr) + AddEdgeToWorkList(branchInst->getParent(), branchInst->getThenBlock()); } } } @@ -549,7 +536,6 @@ bool SCCPContext::PropagateConstants(Function *func) { changed = true; continue; } - for (auto it = bb->begin(); it != bb->end();) { Instruction *inst = it->get(); SSAPValue ssaPVal = GetValueState(inst); @@ -574,7 +560,8 @@ bool SCCPContext::PropagateConstants(Function *func) { } inst->replaceAllUsesWith(constVal); instsToDelete.push_back(inst); - it = bb->removeInst(it); // 从块中移除指令 + // it = bb->removeInst(it); // 从块中移除指令 + it = bb->getInstructions().erase(it); changed = true; } else { // 如果操作数是常量,直接替换为常量值(常量折叠) @@ -604,12 +591,24 @@ bool SCCPContext::PropagateConstants(Function *func) { // 实际删除指令 for (Instruction *inst : instsToDelete) { - if (inst->getParent() && !SysYIROptUtils::usedelete(inst)) { - // 如果 still in parent and not deleted by usedelete, implies issues or non-instruction values. - // For SCCP, if replaced, it should have no uses. - if (DEBUG) { - std::cerr << "Warning: Instruction " << inst->getName() << " was not fully deleted." << std::endl; - } + // 在尝试删除之前,先检查指令是否仍然附加到其父基本块。 + // 如果它已经没有父块,可能说明它已被其他方式处理或已处于无效状态。 + if (inst->getParent() != nullptr) { + // 调用负责完整删除的函数,该函数应负责清除uses并将其从父块中移除。 + SysYIROptUtils::usedelete_withinstdelte(inst); + if (inst->getParent() != nullptr) { + // 如果执行到这里,说明 usedelete_withinstdelte 没有成功将其从父块中移除。 + if (DEBUG) { + std::cerr << "Warning: Instruction " << inst->getName() + << " was not fully deleted by usedelete_withinstdelte and is still in parent." << std::endl; + } + } + } + else { + // 指令已不属于任何父块,无需再次删除。 + if (DEBUG) { + std::cerr << "Info: Instruction " << inst->getName() << " was already detached or is not in a parent block." << std::endl; + } } } return changed; @@ -642,9 +641,9 @@ bool SCCPContext::SimplifyControlFlow(Function *func) { if (!newReachableBlocks.count(bb)) continue; // 只处理可达块 - Instruction *terminator = bb->terminator().get(); - if (auto branchInst = dynamic_cast(terminator)) { - if (branchInst->isCondBr()) { + Instruction *terminator = bb->terminator()->get(); + if (auto branchInst = dynamic_cast(terminator)) { + if (branchInst->isCondBr()) { // 检查是否是条件分支 (kCondBr) SSAPValue condVal = GetValueState(branchInst->getOperand(0)); if (condVal.state == LatticeVal::Constant) { bool condition_is_true = false; @@ -677,12 +676,12 @@ std::unordered_set SCCPContext::FindReachableBlocks(Function *func BasicBlock *currentBB = q.front(); q.pop(); - Instruction *terminator = currentBB->terminator().get(); + Instruction *terminator = currentBB->terminator()->get(); if (!terminator) continue; - if (auto branchInst = dynamic_cast(terminator)) { - if (branchInst->isCondBr()) { + if (auto branchInst = dynamic_cast(terminator)) { + if (branchInst->isCondBr()) { // 检查是否是条件分支 (kCondBr) SSAPValue condVal = GetValueState(branchInst->getOperand(0)); if (condVal.state == LatticeVal::Constant) { bool condition_is_true = false; @@ -693,13 +692,13 @@ std::unordered_set SCCPContext::FindReachableBlocks(Function *func } if (condition_is_true) { - BasicBlock *trueBlock = branchInst->getTrueBlock(); + BasicBlock *trueBlock = branchInst->getThenBlock(); if (reachable.find(trueBlock) == reachable.end()) { reachable.insert(trueBlock); q.push(trueBlock); } } else { - BasicBlock *falseBlock = branchInst->getFalseBlock(); + BasicBlock *falseBlock = branchInst->getElseBlock(); if (reachable.find(falseBlock) == reachable.end()) { reachable.insert(falseBlock); q.push(falseBlock); @@ -713,8 +712,8 @@ std::unordered_set SCCPContext::FindReachableBlocks(Function *func } } } - } else { // 无条件分支 - BasicBlock *targetBlock = branchInst->getTrueBlock(); + } else { // 无条件分支 (kBr) + BasicBlock *targetBlock = branchInst->getThenBlock(); if (reachable.find(targetBlock) == reachable.end()) { reachable.insert(targetBlock); q.push(targetBlock); @@ -733,103 +732,113 @@ void SCCPContext::RemoveDeadBlock(BasicBlock *bb, Function *func) { std::cout << "Removing dead block: " << bb->getName() << std::endl; } // 首先更新其所有前驱的终结指令,移除指向死块的边 - std::vector preds_to_remove; - for (auto &pred_weak_ptr : bb->getPredecessors()) { - if (auto pred = pred_weak_ptr.lock()) { // 确保前驱块仍然存在 - preds_to_remove.push_back(pred.get()); + std::vector preds_to_update; + for (auto &pred : bb->getPredecessors()) { + if (pred != nullptr) { // 检查是否为空指针 + preds_to_update.push_back(pred); } } - for (BasicBlock *pred : preds_to_remove) { - UpdateTerminator(pred, bb); + for (BasicBlock *pred : preds_to_update) { + if (executableBlocks.count(pred)) { + UpdateTerminator(pred, bb); + } } // 移除其后继的 Phi 节点的入边 + std::vector succs_to_update; for (auto succ : bb->getSuccessors()) { + succs_to_update.push_back(succ); + } + for (BasicBlock *succ : succs_to_update) { RemovePhiIncoming(succ, bb); } - func->removeBasicBlock(bb); + func->removeBasicBlock(bb); // 从函数中移除基本块 } // 简化分支(将条件分支替换为无条件分支) -void SCCPContext::SimplifyBranch(BranchInst *brInst, bool condVal) { +void SCCPContext::SimplifyBranch(CondBrInst *brInst, bool condVal) { BasicBlock *parentBB = brInst->getParent(); - BasicBlock *trueBlock = brInst->getTrueBlock(); - BasicBlock *falseBlock = brInst->getFalseBlock(); + 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->setInsertPoint(parentBB, brInst->getIterator()); - if (condVal) { // 条件为真,跳转到真分支 - builder->createBranchInst(trueBlock); - // 移除旧的条件分支指令 - SysYIROptUtils::usedelete(brInst); - // 移除与假分支的连接 + builder->setPosition(parentBB, parentBB->findInstIterator(brInst)); + if (condVal) { // 条件为真,跳转到真分支 + builder->createUncondBrInst(trueBlock); // 插入无条件分支 kBr + SysYIROptUtils::usedelete(brInst); // 移除旧的条件分支指令 + // TODO now: 移出指令 + parentBB->removeSuccessor(falseBlock); falseBlock->removePredecessor(parentBB); - // 移除假分支中 Phi 节点的来自当前块的入边 RemovePhiIncoming(falseBlock, parentBB); - } else { // 条件为假,跳转到假分支 - builder->createBranchInst(falseBlock); - // 移除旧的条件分支指令 - SysYIROptUtils::usedelete(brInst); - // 移除与真分支的连接 + } else { // 条件为假,跳转到假分支 + builder->createUncondBrInst(falseBlock); // 插入无条件分支 kBr + SysYIROptUtils::usedelete(brInst); // 移除旧的条件分支指令 + // TODO now: 移出指令 + parentBB->removeSuccessor(trueBlock); trueBlock->removePredecessor(parentBB); - // 移除真分支中 Phi 节点的来自当前块的入边 RemovePhiIncoming(trueBlock, parentBB); } } // 更新前驱块的终结指令(当一个后继块被移除时) void SCCPContext::UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc) { - Instruction *terminator = predBB->terminator().get(); + Instruction *terminator = predBB->terminator()->get(); if (!terminator) return; - // 对于 BranchInst,如果其某个目标是 removedSucc,则需要更新它 - if (auto branchInst = dynamic_cast(terminator)) { - if (branchInst->isCondBr()) { - // 如果 removedSucc 是真分支,则条件分支应指向假分支 - if (branchInst->getTrueBlock() == removedSucc) { - // 如果另一个分支也死了,则整个分支是死代码,由其他阶段移除 - // 这里我们简化为无条件跳转到另一个仍然可达的分支 - builder->setInsertPoint(predBB, branchInst->getIterator()); - builder->createBranchInst(branchInst->getFalseBlock()); - SysYIROptUtils::usedelete(branchInst); - predBB->removeSuccessor(removedSucc); // 从前驱的后继列表中移除 - } - // 如果 removedSucc 是假分支,则条件分支应指向真分支 - else if (branchInst->getFalseBlock() == removedSucc) { - builder->setInsertPoint(predBB, branchInst->getIterator()); - builder->createBranchInst(branchInst->getTrueBlock()); - SysYIROptUtils::usedelete(branchInst); - predBB->removeSuccessor(removedSucc); // 从前驱的后继列表中移除 - } - } else { // 无条件分支 - // 如果目标是 removedSucc,这通常意味着整个 predBB 也是死块 - // 或者需要一个 unreachable 指令 - if (branchInst->getTrueBlock() == removedSucc) { - // 暂时不创建 unreachable,因为可能死块会被整个移除 - // 或者留待后续简化。只移除后继连接。 - SysYIROptUtils::usedelete(branchInst); // 先删除指令 + if (auto branchInst = dynamic_cast(terminator)) { + if (branchInst->isCondBr()) { // 如果是条件分支 + 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_withinstdelte(branchInst); predBB->removeSuccessor(removedSucc); - builder->setInsertPoint(predBB, predBB->end()); // 在块末尾插入 - builder->createUnreachableInst(); // 插入一个不可达指令,标记代码路径结束 + } 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_withinstdelte(branchInst); + predBB->removeSuccessor(removedSucc); + } + } else { // 无条件分支 (kBr) + if (branchInst->getThenBlock() == removedSucc) { + if (DEBUG) { + std::cout << "Updating unconditional br in " << predBB->getName() << ": Target block (" + << removedSucc->getName() << ") removed. Replacing with Unreachable." << std::endl; + } + SysYIROptUtils::usedelete_withinstdelte(branchInst); + predBB->removeSuccessor(removedSucc); + builder->setPosition(predBB, predBB->end()); + builder->createUnreachableInst(); } } } - // ReturnInst 和其他指令不受影响 } // 移除 Phi 节点的入边(当其前驱块被移除时) -void SCCPContext::RemovePhiIncoming(BasicBlock *phiParentBB, BasicBlock *removedPred) { +void SCCPContext::RemovePhiIncoming(BasicBlock *phiParentBB, BasicBlock *removedPred) { // 修正 removedPred 类型 + std::vector insts_to_check; for (auto &inst_ptr : phiParentBB->getInstructions()) { - if (auto phi = dynamic_cast(inst_ptr.get())) { - phi->removeIncomingValue(removedPred); // 移除来自已删除前驱的入边 + insts_to_check.push_back(inst_ptr.get()); + } + + for (Instruction *inst : insts_to_check) { + if (auto phi = dynamic_cast(inst)) { + phi->delBlk(removedPred); } } } @@ -852,20 +861,10 @@ bool SCCP::runOnFunction(Function *F, AnalysisManager &AM) { } SCCPContext context(builder); context.run(F, AM); - // SCCPContext::run 内部负责管理 changed 状态并执行优化。 - // 这里我们无法直接返回 context.run 的 `changed` 值, - // 因为 run 是 void。通常会通过 context 的一个成员来跟踪。 - // 或者,runOnFunction 负责判断是否发生了变化。 - // 目前,为简单起见,假设 SCCPContext::run 确实执行了修改,并总是返回 true, - // 这在实际编译器中可能需要更精确的追踪。 - // 更好的做法是让 run 返回 bool. - // 由于用户提供的run是void, 且外部无法直接访问context的changed变量,我们暂时保守返回true。 return true; } void SCCP::getAnalysisUsage(std::set &analysisDependencies, std::set &analysisInvalidations) const { - // SCCP 不依赖其他分析,但它会改变 IR,因此会使许多分析失效 - // 例如:DominatorTree, CFG analysis, LI, ... analysisInvalidations.insert(nullptr); // 表示使所有默认分析失效 } diff --git a/src/midend/Pass/Pass.cpp b/src/midend/Pass/Pass.cpp index d6087fe..8fbaeec 100644 --- a/src/midend/Pass/Pass.cpp +++ b/src/midend/Pass/Pass.cpp @@ -5,6 +5,7 @@ #include "DCE.h" #include "Mem2Reg.h" #include "Reg2Mem.h" +#include "SCCP.h" #include "Pass.h" #include #include @@ -50,6 +51,8 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR registerOptimizationPass(builderIR); registerOptimizationPass(builderIR); + registerOptimizationPass(builderIR); + if (optLevel >= 1) { //经过设计安排优化遍的执行顺序以及执行逻辑 if (DEBUG) std::cout << "Applying -O1 optimizations.\n"; @@ -80,10 +83,11 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR this->clearPasses(); this->addPass(&Mem2Reg::ID); + this->addPass(&SCCP::ID); this->run(); if(DEBUG) { - std::cout << "=== IR After Mem2Reg Optimizations ===\n"; + std::cout << "=== IR After Mem2Reg And SCCP Optimizations ===\n"; printPasses(); } From f3f603a0326ff517391441ad2d1a331e15d20108 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 31 Jul 2025 19:36:39 +0800 Subject: [PATCH 07/16] =?UTF-8?q?[midend]=E6=B6=88=E9=99=A4=E5=86=97?= =?UTF-8?q?=E4=BD=99=E7=BB=B4=E5=BA=A6=E4=BF=A1=E6=81=AF=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=EF=BC=8C=E9=80=82=E9=85=8DIR=E7=94=9F=E6=88=90=E5=99=A8?= =?UTF-8?q?=EF=BC=8CTODO=EF=BC=9A=E5=85=B6=E4=BB=96=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=81=8D=E7=94=9F=E6=88=90=E6=8C=87=E4=BB=A4=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=EF=BC=8C=E6=88=96=E8=80=85=E5=90=8E=E7=AB=AF=E7=9A=84=E8=AE=BF?= =?UTF-8?q?=E9=97=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/midend/IR.h | 80 +++++++++++----------------------- src/include/midend/IRBuilder.h | 44 ++++--------------- src/midend/IR.cpp | 28 +++++++----- src/midend/SysYIRGenerator.cpp | 32 +++++++------- 4 files changed, 66 insertions(+), 118 deletions(-) diff --git a/src/include/midend/IR.h b/src/include/midend/IR.h index 2902c64..1335e97 100644 --- a/src/include/midend/IR.h +++ b/src/include/midend/IR.h @@ -1061,12 +1061,10 @@ class UncondBrInst : public Instruction { friend class Function; protected: - UncondBrInst(BasicBlock *block, std::vector args, + UncondBrInst(BasicBlock *block, BasicBlock *parent = nullptr) : Instruction(kBr, Type::getVoidType(), parent, "") { - // assert(block->getNumArguments() == args.size()); addOperand(block); - addOperands(args); } public: @@ -1095,17 +1093,12 @@ class CondBrInst : public Instruction { friend class Function; protected: - CondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock, - const std::vector &thenArgs, - const std::vector &elseArgs, BasicBlock *parent = nullptr) + CondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock, + BasicBlock *parent = nullptr) : Instruction(kCondBr, Type::getVoidType(), parent, "") { - // assert(thenBlock->getNumArguments() == thenArgs.size() and - // elseBlock->getNumArguments() == elseArgs.size()); addOperand(condition); addOperand(thenBlock); addOperand(elseBlock); - addOperands(thenArgs); - addOperands(elseArgs); } public: Value* getCondition() const { return getOperand(0); } @@ -1129,17 +1122,6 @@ public: } return succs; } - // 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); - // } }; // class CondBrInst @@ -1156,10 +1138,9 @@ class AllocaInst : public Instruction { friend class IRBuilder; friend class Function; protected: - AllocaInst(Type *type, const std::vector &dims = {}, + AllocaInst(Type *type, BasicBlock *parent = nullptr, const std::string &name = "") : Instruction(kAlloca, type, parent, name) { - addOperands(dims); } public: @@ -1168,8 +1149,6 @@ public: return getType()->as()->getBaseType(); } ///< 获取分配的类型 int getNumDims() const { return getNumOperands(); } - auto getDims() const { return getOperands(); } - Value* getDim(int index) { return getOperand(index); } }; // class AllocaInst @@ -1216,12 +1195,11 @@ class LoadInst : public Instruction { friend class Function; protected: - LoadInst(Value *pointer, const std::vector &indices = {}, + LoadInst(Value *pointer, BasicBlock *parent = nullptr, const std::string &name = "") : Instruction(kLoad, pointer->getType()->as()->getBaseType(), parent, name) { addOperand(pointer); - addOperands(indices); } public: @@ -1241,22 +1219,15 @@ class StoreInst : public Instruction { protected: StoreInst(Value *value, Value *pointer, - const std::vector &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 @@ -1395,20 +1366,18 @@ protected: protected: GlobalValue(Module *parent, Type *type, const std::string &name, - const std::vector &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(dims[i]); - assert(dim_val && "GlobalValue dims must be constant integers"); - num *= dim_val->getInt(); + auto arrayType = type->as(); + while (arrayType) { + numDims++; + num *= arrayType->getNumElements(); + arrayType = arrayType->getElementType()->as(); } if (dynamic_cast(type)->getBaseType() == Type::getFloatType()) { init.push_back(ConstantFloating::get(0.0F), num); // Use new constant factory @@ -1420,9 +1389,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; } ///< 获取维度数量 @@ -1464,13 +1430,19 @@ class ConstantVariable : public Value { ValueCounter initValues; ///< 值 protected: - ConstantVariable(Module *parent, Type *type, const std::string &name, const ValueCounter &init, - const std::vector &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()->getBaseType()->isArray()) { + auto arrayType = type->as(); + while (arrayType) { + numDims++; + arrayType = arrayType->getElementType()->as(); + } + } initValues = init; - // addOperands(dims); 同GlobalValue,维度信息已经被记录到Type中,dim只是为了方便初始化 } public: @@ -1563,13 +1535,12 @@ class Module { return result.first->second.get(); } ///< 创建外部函数 ///< 变量创建伴随着符号表的更新 - GlobalValue* createGlobalValue(const std::string &name, Type *type, const std::vector &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(); } @@ -1578,9 +1549,8 @@ class Module { } return dynamic_cast(result); } ///< 创建全局变量 - ConstantVariable* createConstVar(const std::string &name, Type *type, const ValueCounter &init, - const std::vector &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; } diff --git a/src/include/midend/IRBuilder.h b/src/include/midend/IRBuilder.h index f761d57..5cbf096 100644 --- a/src/include/midend/IRBuilder.h +++ b/src/include/midend/IRBuilder.h @@ -239,15 +239,14 @@ class IRBuilder { block->getInstructions().emplace(position, inst); return inst; } ///< 创建return指令 - UncondBrInst * createUncondBrInst(BasicBlock *thenBlock, const std::vector &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 &thenArgs = {}, const std::vector &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; @@ -258,18 +257,12 @@ class IRBuilder { block->getInstructions().emplace(position, inst); return inst; } ///< 创建不可达指令 - AllocaInst * createAllocaInst(Type *type, const std::vector &dims = {}, const std::string &name = "") { - auto inst = new AllocaInst(type, dims, block, name); + 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 &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 &indices = {}, const std::string &name = "") { std::string newName; if (name.empty()) { @@ -281,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; @@ -292,9 +285,8 @@ class IRBuilder { block->getInstructions().emplace(position, inst); return inst; } ///< 创建memset指令 - StoreInst * createStoreInst(Value *value, Value *pointer, const std::vector &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; @@ -314,24 +306,6 @@ class IRBuilder { block->getInstructions().emplace(block->begin(), inst); return inst; } ///< 创建Phi指令 - // GetElementPtrInst* createGetElementPtrInst(Value *basePointer, - // const std::vector &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 指令。 * 它会自动推断返回类型,无需手动指定。 diff --git a/src/midend/IR.cpp b/src/midend/IR.cpp index 1b32eaf..2cc34dc 100644 --- a/src/midend/IR.cpp +++ b/src/midend/IR.cpp @@ -227,9 +227,10 @@ Function * Function::clone(const std::string &suffix) const { auto oldAllocInst = dynamic_cast(value); if (oldAllocInst != nullptr) { std::vector 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()); @@ -252,9 +253,10 @@ Function * Function::clone(const std::string &suffix) const { if (oldNewValueMap.find(inst.get()) == oldNewValueMap.end()) { auto oldAllocInst = dynamic_cast(inst.get()); std::vector 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()); @@ -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(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; } @@ -464,7 +466,8 @@ Function * Function::clone(const std::string &suffix) const { 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,9 +482,10 @@ Function * Function::clone(const std::string &suffix) const { std::vector newIndices; newPointer = oldNewValueMap.at(oldPointer); newValue = oldNewValueMap.at(oldValue); - for (const auto &index : oldStoreInst->getIndices()) { - newIndices.emplace_back(oldNewValueMap.at(index->getValue())); - } + // TODO: 这里的newIndices需要根据oldStoreInst的类型来推断 + // for (const auto &index : oldStoreInst->getIndices()) { + // newIndices.emplace_back(oldNewValueMap.at(index->getValue())); + // } auto newStoreInst = new StoreInst(newValue, newPointer, newIndices, oldNewBlockMap.at(oldStoreInst->getParent()), oldStoreInst->getName()); oldNewValueMap.emplace(oldStoreInst, newStoreInst); diff --git a/src/midend/SysYIRGenerator.cpp b/src/midend/SysYIRGenerator.cpp index 03f382b..64d0d92 100644 --- a/src/midend/SysYIRGenerator.cpp +++ b/src/midend/SysYIRGenerator.cpp @@ -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(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 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(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(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); From 35b421b60b2e03bb46b2d316ade11fa712362323 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 31 Jul 2025 19:38:43 +0800 Subject: [PATCH 08/16] =?UTF-8?q?[midend]=E4=BF=AE=E6=94=B9=E5=8E=9F?= =?UTF-8?q?=E5=9B=A0=E5=90=8C=E4=B8=8A=E4=B8=80=E6=AC=A1commit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/midend/IR.cpp | 6 +++--- src/midend/Pass/Optimize/Reg2Mem.cpp | 4 ++-- src/midend/Pass/Optimize/SysYIRCFGOpt.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/midend/IR.cpp b/src/midend/IR.cpp index 2cc34dc..e434ced 100644 --- a/src/midend/IR.cpp +++ b/src/midend/IR.cpp @@ -233,7 +233,7 @@ Function * Function::clone(const std::string &suffix) const { // } 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()) { @@ -259,7 +259,7 @@ Function * Function::clone(const std::string &suffix) const { // } 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()) { @@ -486,7 +486,7 @@ Function * Function::clone(const std::string &suffix) const { // 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()); oldNewValueMap.emplace(oldStoreInst, newStoreInst); break; diff --git a/src/midend/Pass/Optimize/Reg2Mem.cpp b/src/midend/Pass/Optimize/Reg2Mem.cpp index b2034c0..42316a5 100644 --- a/src/midend/Pass/Optimize/Reg2Mem.cpp +++ b/src/midend/Pass/Optimize/Reg2Mem.cpp @@ -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; } } diff --git a/src/midend/Pass/Optimize/SysYIRCFGOpt.cpp b/src/midend/Pass/Optimize/SysYIRCFGOpt.cpp index 94381f4..99c06aa 100644 --- a/src/midend/Pass/Optimize/SysYIRCFGOpt.cpp +++ b/src/midend/Pass/Optimize/SysYIRCFGOpt.cpp @@ -309,7 +309,7 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder) { SysYIROptUtils::usedelete(thelastinst->get()); thelastinst = basicBlock->getInstructions().erase(thelastinst); pBuilder->setPosition(basicBlock.get(), basicBlock->end()); - pBuilder->createUncondBrInst(thebrBlock, {}); + pBuilder->createUncondBrInst(thebrBlock); changed = true; // 标记IR被修改 continue; } @@ -348,7 +348,7 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder) { SysYIROptUtils::usedelete(thelastinst->get()); thelastinst = basicBlock->getInstructions().erase(thelastinst); pBuilder->setPosition(basicBlock.get(), basicBlock->end()); - pBuilder->createUncondBrInst(thebrBlock, {}); + pBuilder->createUncondBrInst(thebrBlock); changed = true; // 标记IR被修改 continue; } @@ -528,7 +528,7 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) { 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 +546,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); From aed4577490dd4034caf864fb62328586368f9cac Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 31 Jul 2025 19:57:19 +0800 Subject: [PATCH 09/16] =?UTF-8?q?[midend]=E5=90=8C=E4=B8=8A,=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E4=BA=86=E6=89=93=E5=8D=B0=E5=87=BD=E6=95=B0=E5=AF=B9?= =?UTF-8?q?=E7=BB=B4=E5=BA=A6=E4=BF=A1=E6=81=AF=E7=9A=84=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E8=AE=BF=E9=97=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/midend/IR.h | 9 --------- src/midend/IR.cpp | 6 +++--- src/midend/SysYIRPrinter.cpp | 32 -------------------------------- 3 files changed, 3 insertions(+), 44 deletions(-) diff --git a/src/include/midend/IR.h b/src/include/midend/IR.h index 1335e97..43a3a89 100644 --- a/src/include/midend/IR.h +++ b/src/include/midend/IR.h @@ -1148,7 +1148,6 @@ public: Type* getAllocatedType() const { return getType()->as()->getBaseType(); } ///< 获取分配的类型 - int getNumDims() const { return getNumOperands(); } }; // class AllocaInst @@ -1203,12 +1202,7 @@ protected: } 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 @@ -1474,9 +1468,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; } ///< 获取初始值 }; diff --git a/src/midend/IR.cpp b/src/midend/IR.cpp index e434ced..bee9968 100644 --- a/src/midend/IR.cpp +++ b/src/midend/IR.cpp @@ -462,9 +462,9 @@ Function * Function::clone(const std::string &suffix) const { newPointer = oldNewValueMap.at(oldPointer); std::vector 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; // TODO : 这里的newLoadInst的类型需要根据oldLoadInst的类型来推断 auto newLoadInst = new LoadInst(newPointer, oldNewBlockMap.at(oldLoadInst->getParent()), ss.str()); diff --git a/src/midend/SysYIRPrinter.cpp b/src/midend/SysYIRPrinter.cpp index e2c5e17..61b9a6f 100644 --- a/src/midend/SysYIRPrinter.cpp +++ b/src/midend/SysYIRPrinter.cpp @@ -411,17 +411,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 +423,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 +437,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; From ef09bc70d4e77d64213415084476fa3564f0dbc5 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 31 Jul 2025 21:10:20 +0800 Subject: [PATCH 10/16] =?UTF-8?q?[midend]=E4=BF=AE=E6=94=B9=E4=BA=86remove?= =?UTF-8?q?inst=E6=96=B9=E6=B3=95=EF=BC=8C=E5=BA=94=E5=AF=B9=E4=B8=8D?= =?UTF-8?q?=E5=90=8C=E7=9A=84=E4=BD=BF=E7=94=A8=E6=83=85=E5=86=B5=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0user=E6=9E=90=E6=9E=84=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E4=BD=BF=E5=BE=97user=E5=AF=B9=E8=B1=A1=E9=94=80=E6=AF=81?= =?UTF-8?q?=E9=A1=BA=E5=B8=A6=E9=94=80=E6=AF=81=E5=85=B6use=E5=85=B3?= =?UTF-8?q?=E7=B3=BB=E9=94=80=E6=AF=81=EF=BC=8C=E9=87=8D=E6=9E=84usedelete?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E5=B0=81=E8=A3=85=E6=8C=87=E4=BB=A4=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E5=92=8Cuse=E5=85=B3=E7=B3=BB=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/midend/IR.h | 17 +++- .../midend/Pass/Optimize/SysYIROptUtils.h | 83 ++++++++++++++++--- 2 files changed, 86 insertions(+), 14 deletions(-) diff --git a/src/include/midend/IR.h b/src/include/midend/IR.h index 43a3a89..ab430f3 100644 --- a/src/include/midend/IR.h +++ b/src/include/midend/IR.h @@ -599,7 +599,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 &i) { return i.get() == inst; }); @@ -626,6 +626,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>, + // 在此析构函数结束后,operands 向量会被销毁,其内部的 shared_ptr 也会被释放, + // 如果 shared_ptr 引用计数降为0,Use 对象本身也会被销毁。 + } unsigned getNumOperands() const { return operands.size(); } ///< 获取操作数数量 auto operand_begin() const { return operands.begin(); } ///< 返回操作数列表的开头迭代器 auto operand_end() const { return operands.end(); } ///< 返回操作数列表的结尾迭代器 diff --git a/src/include/midend/Pass/Optimize/SysYIROptUtils.h b/src/include/midend/Pass/Optimize/SysYIROptUtils.h index 1ee1ddc..a5a757d 100644 --- a/src/include/midend/Pass/Optimize/SysYIROptUtils.h +++ b/src/include/midend/Pass/Optimize/SysYIROptUtils.h @@ -22,23 +22,70 @@ public: } }; - // 仅仅删除use关系 - static void usedelete(Instruction *instr) { - for (auto &use : instr->getOperands()) { - Value* val = use->getValue(); - val->removeUse(use); + static void __internal_handle_instruction_deletion_uses(Instruction *inst_to_delete) { + assert(inst_to_delete && "Instruction to delete cannot be null."); + // 确保指令有一个父基本块,才能进行后续的物理删除 + BasicBlock *parentBlock = inst_to_delete->getParent(); + assert(parentBlock && "Instruction must have a parent BasicBlock to be deleted."); + + // 如果指令定义了一个值并且仍然有使用者(即它的 getUses() 不为空), + // 那么将其所有用途替换为对应类型的 UndefinedValue。 + // 这是一种安全的做法,避免悬空指针,同时表示这些值是未定义的。 + // 如果指令本身不产生值(如 StoreInst, BranchInst 等),或者没有用户, + // getUses().empty() 会为 true,replaceAllUsesWith 将是一个空操作,这也是正确的。 + if (!inst_to_delete->getUses().empty()) { + // UndefinedValue::get(Type*) 需要一个 Type* 参数,确保类型匹配。 + // 例如,如果 inst_to_delete 是 alloca i32,那么它的类型是 PointerType (i32*)。 + // UndefinedValue::get 的参数应是 i32* 类型。 + std::cout << "Replacing uses of instruction " << inst_to_delete->getName() + << " with UndefinedValue." << std::endl; + inst_to_delete->replaceAllUsesWith(UndefinedValue::get(inst_to_delete->getType())); } + // 至此,inst_to_delete 在语义上已不再被其他活跃指令使用。 } - // 删除use关系并删除指令 - static void usedelete_withinstdelte(Instruction *instr) { - for (auto &use : instr->getOperands()) { - Value* val = use->getValue(); - val->removeUse(use); - } - instr->getParent()->removeInst(instr); + // 版本1: 传入 Instruction* + static void usedelete(Instruction *inst) { + __internal_handle_instruction_deletion_uses(inst); + + // 物理删除指令。BasicBlock::removeInst(Instruction*) 会在内部查找指令。 + // 这行调用会触发 inst 指针所指向的 Instruction 对象的析构。 + inst->getParent()->removeInst(inst); } + // 版本2: 传入 BasicBlock::iterator + static BasicBlock::iterator usedelete(BasicBlock::iterator inst_it) { + // 获取 unique_ptr 中的原始 Instruction 指针。 + // 必须在物理删除操作之前获取,因为物理删除后迭代器和unique_ptr可能失效。 + Instruction *inst_to_delete = inst_it->get(); + + __internal_handle_instruction_deletion_uses(inst_to_delete); + + // 物理删除指令。BasicBlock::removeInst(iterator pos) 更适合 std::list, + // 并且会返回一个新的迭代器,指向被删除元素之后的位置。 + // 这行调用会触发 inst_to_delete 指向的 Instruction 对象的析构。 + BasicBlock *parentBlock = inst_to_delete->getParent(); // 再次获取父块,以防万一 + // 这里调用的是 BasicBlock 中修改后的 removeInst(iterator pos) 版本 + return parentBlock->removeInst(inst_it); + } + + // 仅仅删除use关系 + // static void usedelete(Instruction *instr) { + // for (auto &use : instr->getOperands()) { + // Value* val = use->getValue(); + // val->removeUse(use); + // } + // } + + // // 删除use关系并删除指令 + // static void usedelete_withinstdelte(Instruction *instr) { + // for (auto &use : instr->getOperands()) { + // Value* val = use->getValue(); + // val->removeUse(use); + // } + // instr->getParent()->removeInst(instr); + // } + // 判断是否是全局变量 static bool isGlobal(Value *val) { auto gval = dynamic_cast(val); @@ -47,7 +94,17 @@ public: // 判断是否是数组 static bool isArr(Value *val) { auto aval = dynamic_cast(val); - return aval != nullptr && aval->getNumDims() != 0; + // 如果是 AllocaInst 且通过Type::isArray()判断为数组类型 + return aval && aval->getType()->as()->getBaseType()->isArray(); + } + // 判断是否是指向数组的指针 + static bool isArrPointer(Value *val) { + auto aval = dynamic_cast(val); + // 如果是 AllocaInst 且通过Type::isPointer()判断为指针; + auto baseType = aval->getType()->as()->getBaseType(); + // 在sysy中,函数的数组参数会退化成指针 + // 所以当AllocaInst的basetype是PointerType时(一维数组)或者是指向ArrayType的PointerType(多位数组)时,返回true + return aval && (baseType->isPointer() || baseType->as()->getBaseType()->isArray()); } }; From 9a53e1b91727842173d49f62057764e38110cf7a Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 31 Jul 2025 21:10:59 +0800 Subject: [PATCH 11/16] =?UTF-8?q?[midend]=E9=80=82=E5=BA=94=E4=B8=8A?= =?UTF-8?q?=E4=B8=80=E6=AC=A1commit=E4=BF=AE=E6=94=B9=E5=B7=B2=E6=9C=89?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=81=8D=E4=B8=AD=E7=9B=B8=E5=85=B3=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E5=88=A0=E9=99=A4=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/midend/Pass/Optimize/DCE.cpp | 4 +--- src/midend/Pass/Optimize/Mem2Reg.cpp | 10 ++++------ src/midend/Pass/Optimize/Reg2Mem.cpp | 3 +-- src/midend/Pass/Optimize/SysYIRCFGOpt.cpp | 22 +++++++--------------- 4 files changed, 13 insertions(+), 26 deletions(-) diff --git a/src/midend/Pass/Optimize/DCE.cpp b/src/midend/Pass/Optimize/DCE.cpp index db5d966..2da1873 100644 --- a/src/midend/Pass/Optimize/DCE.cpp +++ b/src/midend/Pass/Optimize/DCE.cpp @@ -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; // 指令活跃,移动到下一个 } diff --git a/src/midend/Pass/Optimize/Mem2Reg.cpp b/src/midend/Pass/Optimize/Mem2Reg.cpp index c6e856f..2447b97 100644 --- a/src/midend/Pass/Optimize/Mem2Reg.cpp +++ b/src/midend/Pass/Optimize/Mem2Reg.cpp @@ -240,10 +240,9 @@ 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!"); + 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 +256,10 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr if (storeInst->getPointer() == alloca) { // 假设 storeInst->getPointer() 返回 AllocaInst* // 将 StoreInst 存储的值作为新的 SSA 值,压入值栈 + 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; @@ -327,7 +326,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; } diff --git a/src/midend/Pass/Optimize/Reg2Mem.cpp b/src/midend/Pass/Optimize/Reg2Mem.cpp index 42316a5..199153b 100644 --- a/src/midend/Pass/Optimize/Reg2Mem.cpp +++ b/src/midend/Pass/Optimize/Reg2Mem.cpp @@ -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); } } } diff --git a/src/midend/Pass/Optimize/SysYIRCFGOpt.cpp b/src/midend/Pass/Optimize/SysYIRCFGOpt.cpp index 99c06aa..a589453 100644 --- a/src/midend/Pass/Optimize/SysYIRCFGOpt.cpp +++ b/src/midend/Pass/Optimize/SysYIRCFGOpt.cpp @@ -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,8 +303,7 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder) { if (dynamic_cast(thelastinst->get()->getOperand(1)) == dynamic_cast(thelastinst->get()->getOperand(2))) { auto thebrBlock = dynamic_cast(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); changed = true; // 标记IR被修改 @@ -345,8 +341,7 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder) { if (dynamic_cast(thelastinst->get()->getOperand(1)) == dynamic_cast(thelastinst->get()->getOperand(2))) { auto thebrBlock = dynamic_cast(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); changed = true; // 标记IR被修改 @@ -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,8 +516,7 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) { auto thenBlock = dynamic_cast(thelast->get()->getOperand(1)); auto elseBlock = dynamic_cast(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()); From c5af4f1c494fe6877b690e9d8f173e7b26b12935 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 31 Jul 2025 22:03:35 +0800 Subject: [PATCH 12/16] =?UTF-8?q?[midend-SCCP]bug=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E4=B8=8D=E5=8F=AF=E8=BE=BE=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=EF=BC=88=E7=90=86=E8=AE=BA=E6=9D=A5=E8=AF=B4=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E4=B8=8D=E4=BC=9A=E5=87=BA=E7=8E=B0=E8=BF=99=E6=9D=A1?= =?UTF-8?q?=E6=8C=87=E4=BB=A4=EF=BC=8C=E5=8F=AA=E6=98=AF=E4=B8=BA=E4=BA=86?= =?UTF-8?q?IR=E5=AE=8C=E6=95=B4=E6=80=A7=E6=B7=BB=E5=8A=A0=EF=BC=89?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E7=9B=B8=E5=85=B3=E6=96=B9=E6=B3=95?= =?UTF-8?q?=EF=BC=8Cphi=E6=8C=87=E4=BB=A4=E6=96=B9=E6=B3=95=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=EF=BC=9B=E7=9B=AE=E5=89=8D=E8=83=BD=E5=A4=9F=E8=B7=91?= =?UTF-8?q?=E5=AE=8C=E6=89=80=E6=9C=89=E4=BC=98=E5=8C=96=EF=BC=8C=E4=BD=86?= =?UTF-8?q?=E6=98=AFUser=E7=9A=84=E6=9E=90=E6=9E=84=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E9=87=8D=E5=AE=9A=E4=B9=89=E5=AF=BC=E8=87=B4=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E6=9E=90=E6=9E=84=E4=B8=8D=E8=83=BD=E6=AD=A3=E7=A1=AE=E5=AE=8C?= =?UTF-8?q?=E6=88=90=EF=BC=8C=E9=9C=80=E8=A6=81=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/midend/IR.h | 5 +- .../midend/Pass/Optimize/SysYIROptUtils.h | 74 ++++++------------- src/midend/IR.cpp | 8 +- src/midend/Pass/Optimize/SCCP.cpp | 57 +++++++------- src/midend/Pass/Pass.cpp | 10 ++- src/midend/SysYIRPrinter.cpp | 7 +- 6 files changed, 73 insertions(+), 88 deletions(-) diff --git a/src/include/midend/IR.h b/src/include/midend/IR.h index ab430f3..ec5ef5d 100644 --- a/src/include/midend/IR.h +++ b/src/include/midend/IR.h @@ -710,7 +710,7 @@ class Instruction : public User { kCondBr = 0x1UL << 30, kBr = 0x1UL << 31, kReturn = 0x1UL << 32, - kUnreachable = 0x1UL << 32, ///< Unreachable instruction, used for optimization purposes + kUnreachable = 0x1UL << 33, // mem op kAlloca = 0x1UL << 34, kLoad = 0x1UL << 35, @@ -845,7 +845,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 { @@ -874,6 +874,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; diff --git a/src/include/midend/Pass/Optimize/SysYIROptUtils.h b/src/include/midend/Pass/Optimize/SysYIROptUtils.h index a5a757d..b4c6bbb 100644 --- a/src/include/midend/Pass/Optimize/SysYIROptUtils.h +++ b/src/include/midend/Pass/Optimize/SysYIROptUtils.h @@ -2,6 +2,7 @@ #include "IR.h" +extern int DEBUG; namespace sysy { // 优化工具类,包含一些通用的优化方法 @@ -22,70 +23,39 @@ public: } }; - static void __internal_handle_instruction_deletion_uses(Instruction *inst_to_delete) { - assert(inst_to_delete && "Instruction to delete cannot be null."); - // 确保指令有一个父基本块,才能进行后续的物理删除 - BasicBlock *parentBlock = inst_to_delete->getParent(); + 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."); - // 如果指令定义了一个值并且仍然有使用者(即它的 getUses() 不为空), - // 那么将其所有用途替换为对应类型的 UndefinedValue。 - // 这是一种安全的做法,避免悬空指针,同时表示这些值是未定义的。 - // 如果指令本身不产生值(如 StoreInst, BranchInst 等),或者没有用户, - // getUses().empty() 会为 true,replaceAllUsesWith 将是一个空操作,这也是正确的。 - if (!inst_to_delete->getUses().empty()) { - // UndefinedValue::get(Type*) 需要一个 Type* 参数,确保类型匹配。 - // 例如,如果 inst_to_delete 是 alloca i32,那么它的类型是 PointerType (i32*)。 - // UndefinedValue::get 的参数应是 i32* 类型。 - std::cout << "Replacing uses of instruction " << inst_to_delete->getName() - << " with UndefinedValue." << std::endl; - inst_to_delete->replaceAllUsesWith(UndefinedValue::get(inst_to_delete->getType())); + // 直接在此处执行 replaceAllUsesWith + if (!inst->getUses().empty()) { + if(DEBUG) { + std::cout << "Replacing all uses of instruction " << inst->getName() << " with UndefinedValue." << std::endl; + } + // 替换所有使用该指令的地方为未定义值 + inst->replaceAllUsesWith(UndefinedValue::get(inst->getType())); } - // 至此,inst_to_delete 在语义上已不再被其他活跃指令使用。 - } - - // 版本1: 传入 Instruction* - static void usedelete(Instruction *inst) { - __internal_handle_instruction_deletion_uses(inst); - - // 物理删除指令。BasicBlock::removeInst(Instruction*) 会在内部查找指令。 - // 这行调用会触发 inst 指针所指向的 Instruction 对象的析构。 + // 物理删除指令 inst->getParent()->removeInst(inst); } - // 版本2: 传入 BasicBlock::iterator static BasicBlock::iterator usedelete(BasicBlock::iterator inst_it) { - // 获取 unique_ptr 中的原始 Instruction 指针。 - // 必须在物理删除操作之前获取,因为物理删除后迭代器和unique_ptr可能失效。 Instruction *inst_to_delete = inst_it->get(); + BasicBlock *parentBlock = inst_to_delete->getParent(); + assert(parentBlock && "Instruction must have a parent BasicBlock for iterator deletion."); - __internal_handle_instruction_deletion_uses(inst_to_delete); - - // 物理删除指令。BasicBlock::removeInst(iterator pos) 更适合 std::list, - // 并且会返回一个新的迭代器,指向被删除元素之后的位置。 - // 这行调用会触发 inst_to_delete 指向的 Instruction 对象的析构。 - BasicBlock *parentBlock = inst_to_delete->getParent(); // 再次获取父块,以防万一 - // 这里调用的是 BasicBlock 中修改后的 removeInst(iterator pos) 版本 + // 直接在此处执行 replaceAllUsesWith + if (!inst_to_delete->getUses().empty()) { + if(DEBUG) { + std::cout << "Replacing all uses of instruction " << inst_to_delete->getName() << " with UndefinedValue." << std::endl; + } + inst_to_delete->replaceAllUsesWith(UndefinedValue::get(inst_to_delete->getType())); + } + // 物理删除指令 return parentBlock->removeInst(inst_it); } - // 仅仅删除use关系 - // static void usedelete(Instruction *instr) { - // for (auto &use : instr->getOperands()) { - // Value* val = use->getValue(); - // val->removeUse(use); - // } - // } - - // // 删除use关系并删除指令 - // static void usedelete_withinstdelte(Instruction *instr) { - // for (auto &use : instr->getOperands()) { - // Value* val = use->getValue(); - // val->removeUse(use); - // } - // instr->getParent()->removeInst(instr); - // } - // 判断是否是全局变量 static bool isGlobal(Value *val) { auto gval = dynamic_cast(val); diff --git a/src/midend/IR.cpp b/src/midend/IR.cpp index bee9968..0fd6198 100644 --- a/src/midend/IR.cpp +++ b/src/midend/IR.cpp @@ -569,7 +569,7 @@ void User::replaceOperand(unsigned index, Value *value) { * phi相关函数 */ - Value* PhiInst::getvalfromBlk(BasicBlock* blk){ +Value* PhiInst::getvalfromBlk(BasicBlock* blk){ refreshB2VMap(); if( blk2val.find(blk) != blk2val.end()) { return blk2val.at(blk); @@ -619,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); } diff --git a/src/midend/Pass/Optimize/SCCP.cpp b/src/midend/Pass/Optimize/SCCP.cpp index 6c492dc..3cc2d48 100644 --- a/src/midend/Pass/Optimize/SCCP.cpp +++ b/src/midend/Pass/Optimize/SCCP.cpp @@ -433,6 +433,7 @@ void SCCPContext::ProcessInstruction(Instruction *inst) { case Instruction::kBr: // 对应 kBr case Instruction::kCondBr: // 对应 kCondBr case Instruction::kReturn: // 对应 kReturn + case Instruction::kUnreachable: // 对应 kUnreachable // 终结符指令不产生值 newState = SSAPValue(); // 保持 Top break; @@ -451,8 +452,10 @@ void SCCPContext::ProcessInstruction(Instruction *inst) { // 特殊处理终结符指令,影响 CFG 边的可达性 if (inst->isTerminator()) { - if (auto branchInst = dynamic_cast(inst)) { - if (branchInst->isCondBr()) { // 使用 kCondBr + if (inst->isBranch()) { + + if (inst->isCondBr()) { // 使用 kCondBr + CondBrInst *branchInst = static_cast(inst); SSAPValue condVal = GetValueState(branchInst->getOperand(0)); if (condVal.state == LatticeVal::Constant) { bool condition_is_true = false; @@ -472,7 +475,8 @@ void SCCPContext::ProcessInstruction(Instruction *inst) { AddEdgeToWorkList(branchInst->getParent(), branchInst->getElseBlock()); } } else { // 无条件分支 (kBr) - AddEdgeToWorkList(branchInst->getParent(), branchInst->getThenBlock()); + UncondBrInst *branchInst = static_cast(inst); + AddEdgeToWorkList(branchInst->getParent(), branchInst->getBlock()); } } } @@ -560,8 +564,7 @@ bool SCCPContext::PropagateConstants(Function *func) { } inst->replaceAllUsesWith(constVal); instsToDelete.push_back(inst); - // it = bb->removeInst(it); // 从块中移除指令 - it = bb->getInstructions().erase(it); + ++it; changed = true; } else { // 如果操作数是常量,直接替换为常量值(常量折叠) @@ -595,14 +598,7 @@ bool SCCPContext::PropagateConstants(Function *func) { // 如果它已经没有父块,可能说明它已被其他方式处理或已处于无效状态。 if (inst->getParent() != nullptr) { // 调用负责完整删除的函数,该函数应负责清除uses并将其从父块中移除。 - SysYIROptUtils::usedelete_withinstdelte(inst); - if (inst->getParent() != nullptr) { - // 如果执行到这里,说明 usedelete_withinstdelte 没有成功将其从父块中移除。 - if (DEBUG) { - std::cerr << "Warning: Instruction " << inst->getName() - << " was not fully deleted by usedelete_withinstdelte and is still in parent." << std::endl; - } - } + SysYIROptUtils::usedelete(inst); } else { // 指令已不属于任何父块,无需再次删除。 @@ -642,8 +638,10 @@ bool SCCPContext::SimplifyControlFlow(Function *func) { continue; // 只处理可达块 Instruction *terminator = bb->terminator()->get(); - if (auto branchInst = dynamic_cast(terminator)) { - if (branchInst->isCondBr()) { // 检查是否是条件分支 (kCondBr) + if (terminator->isBranch()) { + + if (terminator->isCondBr()) { // 检查是否是条件分支 (kCondBr) + CondBrInst *branchInst = static_cast(terminator); SSAPValue condVal = GetValueState(branchInst->getOperand(0)); if (condVal.state == LatticeVal::Constant) { bool condition_is_true = false; @@ -680,8 +678,9 @@ std::unordered_set SCCPContext::FindReachableBlocks(Function *func if (!terminator) continue; - if (auto branchInst = dynamic_cast(terminator)) { - if (branchInst->isCondBr()) { // 检查是否是条件分支 (kCondBr) + if (terminator->isBranch()) { + if (terminator->isCondBr()) { // 检查是否是条件分支 (kCondBr) + CondBrInst *branchInst = static_cast(terminator); SSAPValue condVal = GetValueState(branchInst->getOperand(0)); if (condVal.state == LatticeVal::Constant) { bool condition_is_true = false; @@ -713,14 +712,16 @@ std::unordered_set SCCPContext::FindReachableBlocks(Function *func } } } else { // 无条件分支 (kBr) - BasicBlock *targetBlock = branchInst->getThenBlock(); + UncondBrInst *branchInst = static_cast(terminator); + BasicBlock *targetBlock = branchInst->getBlock(); if (reachable.find(targetBlock) == reachable.end()) { reachable.insert(targetBlock); q.push(targetBlock); } } - } else if (auto retInst = dynamic_cast(terminator)) { + } else if (terminator->isReturn() || terminator->isUnreachable()) { // ReturnInst 没有后继,不需要处理 + // UnreachableInst 也没有后继,不需要处理 } } return reachable; @@ -771,16 +772,12 @@ void SCCPContext::SimplifyBranch(CondBrInst *brInst, bool condVal) { if (condVal) { // 条件为真,跳转到真分支 builder->createUncondBrInst(trueBlock); // 插入无条件分支 kBr SysYIROptUtils::usedelete(brInst); // 移除旧的条件分支指令 - // TODO now: 移出指令 - parentBB->removeSuccessor(falseBlock); falseBlock->removePredecessor(parentBB); RemovePhiIncoming(falseBlock, parentBB); } else { // 条件为假,跳转到假分支 builder->createUncondBrInst(falseBlock); // 插入无条件分支 kBr SysYIROptUtils::usedelete(brInst); // 移除旧的条件分支指令 - // TODO now: 移出指令 - parentBB->removeSuccessor(trueBlock); trueBlock->removePredecessor(parentBB); RemovePhiIncoming(trueBlock, parentBB); @@ -793,8 +790,9 @@ void SCCPContext::UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc) if (!terminator) return; - if (auto branchInst = dynamic_cast(terminator)) { - if (branchInst->isCondBr()) { // 如果是条件分支 + if (terminator->isBranch()) { + if (terminator->isCondBr()) { // 如果是条件分支 + CondBrInst *branchInst = static_cast(terminator); if (branchInst->getThenBlock() == removedSucc) { if (DEBUG) { std::cout << "Updating cond br in " << predBB->getName() << ": True block (" << removedSucc->getName() @@ -802,7 +800,7 @@ void SCCPContext::UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc) } builder->setPosition(predBB, predBB->findInstIterator(branchInst)); builder->createUncondBrInst(branchInst->getElseBlock()); - SysYIROptUtils::usedelete_withinstdelte(branchInst); + SysYIROptUtils::usedelete(branchInst); predBB->removeSuccessor(removedSucc); } else if (branchInst->getElseBlock() == removedSucc) { if (DEBUG) { @@ -811,16 +809,17 @@ void SCCPContext::UpdateTerminator(BasicBlock *predBB, BasicBlock *removedSucc) } builder->setPosition(predBB, predBB->findInstIterator(branchInst)); builder->createUncondBrInst(branchInst->getThenBlock()); - SysYIROptUtils::usedelete_withinstdelte(branchInst); + SysYIROptUtils::usedelete(branchInst); predBB->removeSuccessor(removedSucc); } } else { // 无条件分支 (kBr) - if (branchInst->getThenBlock() == removedSucc) { + UncondBrInst *branchInst = static_cast(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_withinstdelte(branchInst); + SysYIROptUtils::usedelete(branchInst); predBB->removeSuccessor(removedSucc); builder->setPosition(predBB, predBB->end()); builder->createUnreachableInst(); diff --git a/src/midend/Pass/Pass.cpp b/src/midend/Pass/Pass.cpp index 8fbaeec..f4ec5ab 100644 --- a/src/midend/Pass/Pass.cpp +++ b/src/midend/Pass/Pass.cpp @@ -83,11 +83,19 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR this->clearPasses(); this->addPass(&Mem2Reg::ID); + this->run(); + + if(DEBUG) { + std::cout << "=== IR After Mem2Reg Optimizations ===\n"; + printPasses(); + } + + this->clearPasses(); this->addPass(&SCCP::ID); this->run(); if(DEBUG) { - std::cout << "=== IR After Mem2Reg And SCCP Optimizations ===\n"; + std::cout << "=== IR After SCCP Optimizations ===\n"; printPasses(); } diff --git a/src/midend/SysYIRPrinter.cpp b/src/midend/SysYIRPrinter.cpp index 61b9a6f..a673613 100644 --- a/src/midend/SysYIRPrinter.cpp +++ b/src/midend/SysYIRPrinter.cpp @@ -400,7 +400,12 @@ 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(pInst); std::cout << "%" << allocaInst->getName() << " = alloca "; From 0f1fcc835dbd0f31e1e130f0209fa9aefa7cc678 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 31 Jul 2025 22:32:04 +0800 Subject: [PATCH 13/16] =?UTF-8?q?[midend-SCCP]=E5=88=A0=E9=99=A4User?= =?UTF-8?q?=E7=9A=84=E6=9E=90=E6=9E=84=E5=87=BD=E6=95=B0=EF=BC=8Cusedelete?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=80=BB=E8=BE=91=E9=80=9A=E7=9F=A5inst?= =?UTF-8?q?=E6=89=80=E4=BD=BF=E7=94=A8=E7=9A=84value=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E5=AF=B9=E5=BA=94=E7=9A=84use=E5=85=B3=E7=B3=BB=EF=BC=88?= =?UTF-8?q?=E4=B8=80=E8=88=AC=E5=9C=A8=E8=BF=99=E4=B9=8B=E5=89=8D=E4=BC=9A?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E4=BD=BF=E7=94=A8inst=E7=9A=84uses=E4=B8=BA?= =?UTF-8?q?=E5=85=B6=E4=BB=96=E5=80=BC=EF=BC=89,TODO:=E4=BB=8D=E7=84=B6?= =?UTF-8?q?=E5=AD=98=E5=9C=A8bug=E9=9C=80=E8=A6=81=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Pass_ID_List.md | 56 +++++++++++++++ src/include/midend/IR.h | 30 ++++---- .../midend/Pass/Optimize/SysYIROptUtils.h | 70 ++++++++++++++----- 3 files changed, 125 insertions(+), 31 deletions(-) diff --git a/Pass_ID_List.md b/Pass_ID_List.md index 12cee1d..c5d2803 100644 --- a/Pass_ID_List.md +++ b/Pass_ID_List.md @@ -14,6 +14,62 @@ 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_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 形式。 diff --git a/src/include/midend/IR.h b/src/include/midend/IR.h index ec5ef5d..5ecb32b 100644 --- a/src/include/midend/IR.h +++ b/src/include/midend/IR.h @@ -626,21 +626,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>, - // 在此析构函数结束后,operands 向量会被销毁,其内部的 shared_ptr 也会被释放, - // 如果 shared_ptr 引用计数降为0,Use 对象本身也会被销毁。 - } + // ~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>, + // // 在此析构函数结束后,operands 向量会被销毁,其内部的 shared_ptr 也会被释放, + // // 如果 shared_ptr 引用计数降为0,Use 对象本身也会被销毁。 + // } unsigned getNumOperands() const { return operands.size(); } ///< 获取操作数数量 auto operand_begin() const { return operands.begin(); } ///< 返回操作数列表的开头迭代器 auto operand_end() const { return operands.end(); } ///< 返回操作数列表的结尾迭代器 diff --git a/src/include/midend/Pass/Optimize/SysYIROptUtils.h b/src/include/midend/Pass/Optimize/SysYIROptUtils.h index b4c6bbb..1265059 100644 --- a/src/include/midend/Pass/Optimize/SysYIROptUtils.h +++ b/src/include/midend/Pass/Optimize/SysYIROptUtils.h @@ -23,38 +23,76 @@ public: } }; + 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>& 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 的引用计数。 + // 当引用计数降为 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."); - // 直接在此处执行 replaceAllUsesWith + // 步骤1: 处理所有使用者,将他们从使用 inst 变为使用 UndefinedValue + // 这将清理 inst 作为 Value 时的 uses 列表 if (!inst->getUses().empty()) { - if(DEBUG) { - std::cout << "Replacing all uses of instruction " << inst->getName() << " with UndefinedValue." << std::endl; - } - // 替换所有使用该指令的地方为未定义值 - inst->replaceAllUsesWith(UndefinedValue::get(inst->getType())); + inst->replaceAllUsesWith(UndefinedValue::get(inst->getType())); } - // 物理删除指令 - inst->getParent()->removeInst(inst); - } + + // 步骤2: 清理 inst 作为 User 时的操作数关系 + // 通知 inst 所使用的所有 Value (如 AllocaInst),移除对应的 Use 关系。 + // 这里的 inst 实际上是一个 User*,所以可以安全地向下转型。 + RemoveUserOperandUses(static_cast(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."); - // 直接在此处执行 replaceAllUsesWith + // 步骤1: 处理所有使用者 if (!inst_to_delete->getUses().empty()) { - if(DEBUG) { - std::cout << "Replacing all uses of instruction " << inst_to_delete->getName() << " with UndefinedValue." << std::endl; - } - inst_to_delete->replaceAllUsesWith(UndefinedValue::get(inst_to_delete->getType())); + inst_to_delete->replaceAllUsesWith(UndefinedValue::get(inst_to_delete->getType())); } - // 物理删除指令 + + // 步骤2: 清理操作数关系 + RemoveUserOperandUses(static_cast(inst_to_delete)); + + // 步骤3: 物理删除指令并返回下一个迭代器 return parentBlock->removeInst(inst_it); - } +} // 判断是否是全局变量 static bool isGlobal(Value *val) { From c268191826a3b346bdf5a174d36de7514ad4d5ff Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Fri, 1 Aug 2025 01:44:33 +0800 Subject: [PATCH 14/16] =?UTF-8?q?[midend-SCCP]=E4=BF=AE=E6=94=B9BaiscBlock?= =?UTF-8?q?=E7=9A=84=E6=9E=90=E6=9E=84=E9=80=BB=E8=BE=91=EF=BC=8C=E5=B0=86?= =?UTF-8?q?CFG=E4=BF=AE=E6=94=B9=E7=9A=84=E8=81=8C=E8=B4=A3=E4=BA=A4?= =?UTF-8?q?=E7=BB=99=E4=BC=98=E5=8C=96=E9=81=8D,=E6=B3=A8=E9=87=8AMem2Reg?= =?UTF-8?q?=E7=9A=84=E8=B0=83=E8=AF=95=E4=BF=A1=E6=81=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/midend/IR.h | 15 +++++++++------ src/midend/Pass/Optimize/Mem2Reg.cpp | 12 +++++++++--- src/midend/Pass/Optimize/SCCP.cpp | 12 +++++++++++- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/include/midend/IR.h b/src/include/midend/IR.h index 5ecb32b..6c1bbf4 100644 --- a/src/include/midend/IR.h +++ b/src/include/midend/IR.h @@ -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: diff --git a/src/midend/Pass/Optimize/Mem2Reg.cpp b/src/midend/Pass/Optimize/Mem2Reg.cpp index 2447b97..89b66af 100644 --- a/src/midend/Pass/Optimize/Mem2Reg.cpp +++ b/src/midend/Pass/Optimize/Mem2Reg.cpp @@ -240,7 +240,9 @@ 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!"); - std::cout << "Mem2Reg: Replacing load " << loadInst->getPointer()->getName() << " with SSA value." << std::endl; + if(DEBUG){ + std::cout << "Mem2Reg: Replacing load " << loadInst->getPointer()->getName() << " with SSA value." << std::endl; + } loadInst->replaceAllUsesWith(allocaToValueStackMap[alloca].top()); instIter = SysYIROptUtils::usedelete(instIter); instDeleted = true; @@ -256,7 +258,9 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr if (storeInst->getPointer() == alloca) { // 假设 storeInst->getPointer() 返回 AllocaInst* // 将 StoreInst 存储的值作为新的 SSA 值,压入值栈 - std::cout << "Mem2Reg: Replacing store to " << storeInst->getPointer()->getName() << " with SSA value." << std::endl; + 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()); // 记录以便弹出 instIter = SysYIROptUtils::usedelete(instIter); @@ -297,7 +301,9 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr if(dominatedBlocks){ for (auto dominatedBB : *dominatedBlocks) { if (dominatedBB) { - std::cout << "Mem2Reg: Recursively renaming variables in dominated block: " << dominatedBB->getName() << std::endl; + if(DEBUG){ + std::cout << "Mem2Reg: Recursively renaming variables in dominated block: " << dominatedBB->getName() << std::endl; + } renameVariables(currentAlloca, dominatedBB); } } diff --git a/src/midend/Pass/Optimize/SCCP.cpp b/src/midend/Pass/Optimize/SCCP.cpp index 3cc2d48..33d716f 100644 --- a/src/midend/Pass/Optimize/SCCP.cpp +++ b/src/midend/Pass/Optimize/SCCP.cpp @@ -1,4 +1,6 @@ #include "SCCP.h" +#include "Dom.h" +#include "Liveness.h" #include #include #include // For std::fmod, std::fabs @@ -236,6 +238,8 @@ SSAPValue SCCPContext::ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVa if (operandVal.constant_type == ValueType::Integer) { int val = std::get(operandVal.constantVal); switch (unaryInst->getKind()) { + case Instruction::kAdd: + return SSAPValue(val); case Instruction::kNeg: return SSAPValue(-val); case Instruction::kNot: @@ -246,6 +250,8 @@ SSAPValue SCCPContext::ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVa } else if (operandVal.constant_type == ValueType::Float) { float val = std::get(operandVal.constantVal); switch (unaryInst->getKind()) { + case Instruction::kAdd: + return SSAPValue(val); case Instruction::kFNeg: return SSAPValue(-val); case Instruction::kFNot: @@ -593,6 +599,7 @@ bool SCCPContext::PropagateConstants(Function *func) { } // 实际删除指令 + // TODO: 删除的逻辑需要考虑修改 for (Instruction *inst : instsToDelete) { // 在尝试删除之前,先检查指令是否仍然附加到其父基本块。 // 如果它已经没有父块,可能说明它已被其他方式处理或已处于无效状态。 @@ -752,6 +759,7 @@ void SCCPContext::RemoveDeadBlock(BasicBlock *bb, Function *func) { } for (BasicBlock *succ : succs_to_update) { RemovePhiIncoming(succ, bb); + succ->removePredecessor(bb); } func->removeBasicBlock(bb); // 从函数中移除基本块 @@ -864,7 +872,9 @@ bool SCCP::runOnFunction(Function *F, AnalysisManager &AM) { } void SCCP::getAnalysisUsage(std::set &analysisDependencies, std::set &analysisInvalidations) const { - analysisInvalidations.insert(nullptr); // 表示使所有默认分析失效 + // analysisInvalidations.insert(nullptr); // 表示使所有默认分析失效 + analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树可能受影响 + analysisInvalidations.insert(&LivenessAnalysisPass::ID); // 活跃性分析很可能失效 } } // namespace sysy \ No newline at end of file From a0b69f20fbd491b96f97909f8b54765649e8e573 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Fri, 1 Aug 2025 15:18:33 +0800 Subject: [PATCH 15/16] =?UTF-8?q?[midend]=E5=90=88=E5=B9=B6=E4=BA=86SCCP?= =?UTF-8?q?=E5=92=8Cbackend,=E4=BF=AE=E5=A4=8D=E4=BA=86=E6=94=AF=E9=85=8D?= =?UTF-8?q?=E6=A0=91=E7=9A=84=E9=94=99=E8=AF=AF=E6=B1=82=E8=A7=A3=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86Mem2Reg=E7=9A=84=E9=87=8D=E5=91=BD?= =?UTF-8?q?=E5=90=8Dalloca=E7=9A=84=E6=A0=88=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/midend/Pass/Optimize/Mem2Reg.h | 6 +- src/midend/Pass/Analysis/Dom.cpp | 215 +++++++++++++++------ src/midend/Pass/Optimize/Mem2Reg.cpp | 116 +++++++---- 3 files changed, 232 insertions(+), 105 deletions(-) diff --git a/src/include/midend/Pass/Optimize/Mem2Reg.h b/src/include/midend/Pass/Optimize/Mem2Reg.h index 52a64fd..451509e 100644 --- a/src/include/midend/Pass/Optimize/Mem2Reg.h +++ b/src/include/midend/Pass/Optimize/Mem2Reg.h @@ -75,11 +75,7 @@ private: // -------------------------------------------------------------------- // 对支配树进行深度优先遍历,重命名变量并替换 load/store 指令 - // alloca: 当前正在处理的 AllocaInst - // currentBB: 当前正在遍历的基本块 - // dt: 支配树分析结果 - // valueStack: 存储当前 AllocaInst 在当前路径上可见的 SSA 值栈 - void renameVariables(AllocaInst* alloca, BasicBlock* currentBB); + void renameVariables(BasicBlock* currentBB); // -------------------------------------------------------------------- // 阶段4: 清理 diff --git a/src/midend/Pass/Analysis/Dom.cpp b/src/midend/Pass/Analysis/Dom.cpp index 73726c5..77b2bba 100644 --- a/src/midend/Pass/Analysis/Dom.cpp +++ b/src/midend/Pass/Analysis/Dom.cpp @@ -1,5 +1,7 @@ #include "Dom.h" -#include // for std::numeric_limits +#include // for std::set_intersection, std::set_difference, std::set_union +#include // for debug output +#include // for std::numeric_limits #include namespace sysy { @@ -38,45 +40,80 @@ const std::set *DominatorTree::getDominanceFrontier(BasicBlock *BB return nullptr; } -const std::set* DominatorTree::getDominatorTreeChildren(BasicBlock* BB) const { - auto it = DominatorTreeChildren.find(BB); - if (it != DominatorTreeChildren.end()) { - return &(it->second); - } - return nullptr; +const std::set *DominatorTree::getDominatorTreeChildren(BasicBlock *BB) const { + auto it = DominatorTreeChildren.find(BB); + if (it != DominatorTreeChildren.end()) { + return &(it->second); + } + return nullptr; +} + +// 辅助函数:打印 BasicBlock 集合 +void printBBSet(const std::string &prefix, const std::set &s) { + if (!DEBUG) + return; + std::cout << prefix << "{"; + bool first = true; + for (const auto &bb : s) { + if (!first) + std::cout << ", "; + std::cout << bb->getName(); + first = false; + } + std::cout << "}" << std::endl; } void DominatorTree::computeDominators(Function *F) { - // 经典的迭代算法计算支配者集合 - // TODO: 可以替换为更高效的算法,如 Lengauer-Tarjan 算法 - BasicBlock *entryBlock = F->getEntryBlock(); + if (DEBUG) + std::cout << "--- Computing Dominators ---" << std::endl; + BasicBlock *entryBlock = F->getEntryBlock(); + std::vector bbs_in_order; // 用于确定遍历顺序,如果需要的话 + + // 初始化:入口块只被自己支配,其他块被所有块支配 for (const auto &bb_ptr : F->getBasicBlocks()) { BasicBlock *bb = bb_ptr.get(); + bbs_in_order.push_back(bb); // 收集所有块 if (bb == entryBlock) { Dominators[bb].insert(bb); + if (DEBUG) + std::cout << "Init Dominators[" << bb->getName() << "]: {" << bb->getName() << "}" << std::endl; } else { for (const auto &all_bb_ptr : F->getBasicBlocks()) { Dominators[bb].insert(all_bb_ptr.get()); } + if (DEBUG) { + std::cout << "Init Dominators[" << bb->getName() << "]: "; + printBBSet("", Dominators[bb]); + } } } bool changed = true; + int iteration = 0; while (changed) { changed = false; - for (const auto &bb_ptr : F->getBasicBlocks()) { + iteration++; + if (DEBUG) + std::cout << "Iteration " << iteration << std::endl; + + // 确保遍历顺序一致性,例如可以按照DFS或BFS顺序,或者简单的迭代器顺序 + // 如果Function::getBasicBlocks()返回的迭代器顺序稳定,则无需bbs_in_order + for (const auto &bb_ptr : F->getBasicBlocks()) { // 假设这个迭代器顺序稳定 BasicBlock *bb = bb_ptr.get(); if (bb == entryBlock) continue; + // 计算所有前驱的支配者集合的交集 std::set newDom; - bool firstPred = true; + bool firstPredProcessed = false; + for (BasicBlock *pred : bb->getPredecessors()) { + // 确保前驱的支配者集合已经计算过 if (Dominators.count(pred)) { - if (firstPred) { + if (!firstPredProcessed) { newDom = Dominators[pred]; - firstPred = false; + firstPredProcessed = true; } else { std::set intersection; std::set_intersection(newDom.begin(), newDom.end(), Dominators[pred].begin(), Dominators[pred].end(), @@ -85,21 +122,32 @@ void DominatorTree::computeDominators(Function *F) { } } } - newDom.insert(bb); + newDom.insert(bb); // BB 永远支配自己 if (newDom != Dominators[bb]) { + if (DEBUG) { + std::cout << " Dominators[" << bb->getName() << "] changed from "; + printBBSet("", Dominators[bb]); + std::cout << " to "; + printBBSet("", newDom); + } Dominators[bb] = newDom; changed = true; } } } + if (DEBUG) + std::cout << "--- Dominators Computation Finished ---" << std::endl; } void DominatorTree::computeIDoms(Function *F) { - // 采用与之前类似的简化实现。TODO:Lengauer-Tarjan等算法。 - BasicBlock *entryBlock = F->getEntryBlock(); - IDoms[entryBlock] = nullptr; + if (DEBUG) + std::cout << "--- Computing Immediate Dominators (IDoms) ---" << std::endl; + BasicBlock *entryBlock = F->getEntryBlock(); + IDoms[entryBlock] = nullptr; // 入口块没有即时支配者 + + // 遍历所有非入口块 for (const auto &bb_ptr : F->getBasicBlocks()) { BasicBlock *bb = bb_ptr.get(); if (bb == entryBlock) @@ -107,91 +155,138 @@ void DominatorTree::computeIDoms(Function *F) { BasicBlock *currentIDom = nullptr; const std::set *domsOfBB = getDominators(bb); - if (!domsOfBB) + if (!domsOfBB) { + if (DEBUG) + std::cerr << "Warning: Dominators for " << bb->getName() << " not found!" << std::endl; continue; + } - for (BasicBlock *D : *domsOfBB) { - if (D == bb) - continue; + // 遍历bb的所有严格支配者 D (即 bb 的支配者中除了 bb 自身) + for (BasicBlock *D_candidate : *domsOfBB) { + if (D_candidate == bb) + continue; // 跳过bb自身 - bool isCandidateIDom = true; - for (BasicBlock *candidate : *domsOfBB) { - if (candidate == bb || candidate == D) - continue; - const std::set *domsOfCandidate = getDominators(candidate); - if (domsOfCandidate && domsOfCandidate->count(D) == 0 && domsOfBB->count(candidate)) { - isCandidateIDom = false; + bool D_candidate_is_IDom = true; + // 检查是否存在另一个块 X,使得 D_candidate 严格支配 X 且 X 严格支配 bb + // 或者更直接的,检查 D_candidate 是否被 bb 的所有其他严格支配者所支配 + for (BasicBlock *X_other_dom : *domsOfBB) { + if (X_other_dom == bb || X_other_dom == D_candidate) + continue; // 跳过bb自身和D_candidate + + // 如果 X_other_dom 严格支配 bb (它在 domsOfBB 中且不是bb自身) + // 并且 X_other_dom 不被 D_candidate 支配,那么 D_candidate 就不是 IDom + const std::set *domsOfX_other_dom = getDominators(X_other_dom); + if (domsOfX_other_dom && domsOfX_other_dom->count(D_candidate)) { // X_other_dom 支配 D_candidate + // D_candidate 被另一个支配者 X_other_dom 支配 + // 这说明 D_candidate 位于 X_other_dom 的“下方”,X_other_dom 更接近 bb + // 因此 D_candidate 不是 IDom + D_candidate_is_IDom = false; break; } } - if (isCandidateIDom) { - currentIDom = D; - break; + if (D_candidate_is_IDom) { + currentIDom = D_candidate; + break; // 找到即时支配者,可以退出循环,因为它是唯一的 } } IDoms[bb] = currentIDom; + if (DEBUG) { + std::cout << " IDom[" << bb->getName() << "] = " << (currentIDom ? currentIDom->getName() : "nullptr") + << std::endl; + } } + if (DEBUG) + std::cout << "--- Immediate Dominators Computation Finished ---" << std::endl; } +/* +for each node n in a postorder traversal of the dominator tree: + df[n] = empty set + // compute DF_local(n) + for each child y of n in the CFG: + if idom[y] != n: + df[n] = df[n] U {y} + // compute DF_up(n) + for each child c of n in the dominator tree: + for each element w in df[c]: + if idom[w] != n: + df[n] = df[n] U {w} +*/ + void DominatorTree::computeDominanceFrontiers(Function *F) { - // 经典的支配边界计算算法 + if (DEBUG) + std::cout << "--- Computing Dominance Frontiers ---" << std::endl; + for (const auto &bb_ptr_X : F->getBasicBlocks()) { BasicBlock *X = bb_ptr_X.get(); DominanceFrontiers[X].clear(); - for (BasicBlock *Y : X->getSuccessors()) { - const std::set *domsOfY = getDominators(Y); - if (domsOfY && domsOfY->find(X) == domsOfY->end()) { - DominanceFrontiers[X].insert(Y); - } - } - - const std::set *domsOfX = getDominators(X); - if (!domsOfX) - continue; + // 遍历所有可能的 Z (X支配Z,或者Z就是X) for (const auto &bb_ptr_Z : F->getBasicBlocks()) { BasicBlock *Z = bb_ptr_Z.get(); - if (Z == X) - continue; const std::set *domsOfZ = getDominators(Z); - if (domsOfZ && domsOfZ->count(X) && Z != X) { - for (BasicBlock *Y : Z->getSuccessors()) { - const std::set *domsOfY = getDominators(Y); - if (domsOfY && domsOfY->find(X) == domsOfY->end()) { - DominanceFrontiers[X].insert(Y); - } + // 如果 X 不支配 Z,则 Z 与 DF(X) 无关 + if (!domsOfZ || domsOfZ->find(X) == domsOfZ->end()) { + continue; + } + + // 遍历 Z 的所有后继 Y + for (BasicBlock *Y : Z->getSuccessors()) { + // 如果 Y 不被 X 严格支配,则 Y 在 DF(X) 中 + // Y 不被 X 严格支配意味着 (Y不被X支配) 或 (Y就是X) + const std::set *domsOfY = getDominators(Y); + if (Y == X || (domsOfY && domsOfY->find(X) == domsOfY->end())) { + DominanceFrontiers[X].insert(Y); } } } + if (DEBUG) { + std::cout << " DF(" << X->getName() << "): "; + printBBSet("", DominanceFrontiers[X]); + } } + if (DEBUG) + std::cout << "--- Dominance Frontiers Computation Finished ---" << std::endl; } void DominatorTree::computeDominatorTreeChildren(Function *F) { + if (DEBUG) + std::cout << "--- Computing Dominator Tree Children ---" << std::endl; + // 首先清空,确保重新计算时是空的 + for (auto &bb_ptr : F->getBasicBlocks()) { + DominatorTreeChildren[bb_ptr.get()].clear(); + } + for (auto &bb_ptr : F->getBasicBlocks()) { BasicBlock *B = bb_ptr.get(); - auto it = getImmediateDominator(B); - if (it != nullptr) { - BasicBlock *A = it; - if (A) { - DominatorTreeChildren[A].insert(B); + BasicBlock *A = getImmediateDominator(B); // A 是 B 的即时支配者 + + if (A) { // 如果 B 有即时支配者 A (即 B 不是入口块) + DominatorTreeChildren[A].insert(B); + if (DEBUG) { + std::cout << " " << B->getName() << " is child of " << A->getName() << std::endl; } } } + if (DEBUG) + std::cout << "--- Dominator Tree Children Computation Finished ---" << std::endl; } // ============================================================== // DominatorTreeAnalysisPass 的实现 // ============================================================== - -bool DominatorTreeAnalysisPass::runOnFunction(Function* F, AnalysisManager &AM) { +bool DominatorTreeAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) { + // 每次运行时清空旧数据,确保重新计算 CurrentDominatorTree = std::make_unique(F); + // 不需要手动清空map,unique_ptr会创建新的DominatorTree对象,其map是空的 + CurrentDominatorTree->computeDominators(F); - CurrentDominatorTree->computeIDoms(F); + CurrentDominatorTree->computeIDoms(F); // 修正后的IDoms算法 CurrentDominatorTree->computeDominanceFrontiers(F); CurrentDominatorTree->computeDominatorTreeChildren(F); - return false; + return false; // 分析遍通常返回 false,表示不修改 IR } std::unique_ptr DominatorTreeAnalysisPass::getResult() { diff --git a/src/midend/Pass/Optimize/Mem2Reg.cpp b/src/midend/Pass/Optimize/Mem2Reg.cpp index 89b66af..7570b30 100644 --- a/src/midend/Pass/Optimize/Mem2Reg.cpp +++ b/src/midend/Pass/Optimize/Mem2Reg.cpp @@ -60,7 +60,7 @@ void Mem2RegContext::run(Function *func, AnalysisManager *AM) { } // 从入口基本块开始,对支配树进行 DFS 遍历,进行变量重命名 - renameVariables(nullptr, func->getEntryBlock()); // 第一个参数 alloca 在这里不使用,因为是递归入口点 + renameVariables(func->getEntryBlock()); // 第一个参数 alloca 在这里不使用,因为是递归入口点 // -------------------------------------------------------------------- // 阶段4: 清理 @@ -209,16 +209,21 @@ void Mem2RegContext::insertPhis(AllocaInst *alloca, const std::unordered_set localStackPushed; +// 移除了 AllocaInst *currentAlloca 参数,因为这个函数是为整个基本块处理所有可提升的 Alloca +void Mem2RegContext::renameVariables(BasicBlock *currentBB) { + // 1. 在函数开始时,记录每个 promotableAlloca 的当前栈深度。 + // 这将用于在函数返回时精确地回溯栈状态。 + std::map originalStackSizes; + for (auto alloca : promotableAllocas) { + originalStackSizes[alloca] = allocaToValueStackMap[alloca].size(); + } // -------------------------------------------------------------------- // 处理当前基本块的指令 // -------------------------------------------------------------------- for (auto instIter = currentBB->getInstructions().begin(); instIter != currentBB->getInstructions().end();) { Instruction *inst = instIter->get(); - bool instDeleted = false; + bool instDeleted = false; // 处理 Phi 指令 (如果是当前 alloca 的 Phi) if (auto phiInst = dynamic_cast(inst)) { @@ -227,55 +232,69 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr if (allocaToPhiMap[alloca].count(currentBB) && allocaToPhiMap[alloca][currentBB] == phiInst) { // 为 Phi 指令的输出创建一个新的 SSA 值,并压入值栈 allocaToValueStackMap[alloca].push(phiInst); - localStackPushed.push(phiInst); // 记录以便弹出 - break; // 找到对应的 alloca,处理下一个指令 + if (DEBUG) { + std::cout << "Mem2Reg: Pushed Phi " << (phiInst->getName().empty() ? "anonymous" : phiInst->getName()) << " for alloca " << alloca->getName() + << ". Stack size: " << allocaToValueStackMap[alloca].size() << std::endl; + } + break; // 找到对应的 alloca,处理下一个指令 } } } // 处理 LoadInst else if (auto loadInst = dynamic_cast(inst)) { - // 检查这个 LoadInst 是否是为某个可提升的 alloca for (auto alloca : promotableAllocas) { - if (loadInst->getPointer() == alloca) { - // loadInst->getPointer() 返回 AllocaInst* - // 将 LoadInst 的所有用途替换为当前 alloca 值栈顶部的 SSA 值 + // 检查 LoadInst 的指针是否直接是 alloca,或者是指向 alloca 的 GEP + Value *ptrOperand = loadInst->getPointer(); + if (ptrOperand == alloca || (dynamic_cast(ptrOperand) && + dynamic_cast(ptrOperand)->getBasePointer() == alloca)) { 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; + if (DEBUG) { + std::cout << "Mem2Reg: Replacing load " + << (ptrOperand->getName().empty() ? "anonymous" : ptrOperand->getName()) << " with SSA value " + << (allocaToValueStackMap[alloca].top()->getName().empty() + ? "anonymous" + : allocaToValueStackMap[alloca].top()->getName()) + << " for alloca " << alloca->getName() << std::endl; + std::cout << "Mem2Reg: allocaToValueStackMap[" << alloca->getName() + << "] size: " << allocaToValueStackMap[alloca].size() << std::endl; } loadInst->replaceAllUsesWith(allocaToValueStackMap[alloca].top()); instIter = SysYIROptUtils::usedelete(instIter); instDeleted = true; - // std::cerr << "Mem2Reg: Replaced load " << loadInst->name() << " with SSA value." << std::endl; break; } } } // 处理 StoreInst else if (auto storeInst = dynamic_cast(inst)) { - // 检查这个 StoreInst 是否是为某个可提升的 alloca for (auto alloca : promotableAllocas) { - 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; + // 检查 StoreInst 的指针是否直接是 alloca,或者是指向 alloca 的 GEP + Value *ptrOperand = storeInst->getPointer(); + if (ptrOperand == alloca || (dynamic_cast(ptrOperand) && + dynamic_cast(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()); - localStackPushed.push(storeInst->getValue()); // 记录以便弹出 instIter = SysYIROptUtils::usedelete(instIter); 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; } } } - if (!instDeleted) { ++instIter; // 如果指令没有被删除,移动到下一个 } } - // -------------------------------------------------------------------- // 处理后继基本块的 Phi 指令参数 // -------------------------------------------------------------------- @@ -290,40 +309,57 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr // 参数值是当前 alloca 值栈顶部的 SSA 值 assert(!allocaToValueStackMap[alloca].empty() && "Value stack empty for alloca when setting phi operand!"); phiInst->addIncoming(allocaToValueStackMap[alloca].top(), currentBB); + if (DEBUG) { + std::cout << "Mem2Reg: Added incoming arg to Phi " + << (phiInst->getName().empty() ? "anonymous" : phiInst->getName()) << " from " + << currentBB->getName() << " with value " + << (allocaToValueStackMap[alloca].top()->getName().empty() + ? "anonymous" + : allocaToValueStackMap[alloca].top()->getName()) + << std::endl; + } } } } - // -------------------------------------------------------------------- // 递归访问支配树的子节点 // -------------------------------------------------------------------- const std::set *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) { - if (dominatedBB) { - if(DEBUG){ - std::cout << "Mem2Reg: Recursively renaming variables in dominated block: " << dominatedBB->getName() << std::endl; + if (dominatedBB) { // 确保子块有效 + if (DEBUG) { + std::cout << "Mem2Reg: Recursively renaming variables in dominated block: " << dominatedBB->getName() + << std::endl; } - renameVariables(currentAlloca, dominatedBB); + renameVariables(dominatedBB); // 递归调用,不再传递 currentAlloca } } } - // -------------------------------------------------------------------- - // 退出基本块时,弹出在此块中压入值栈的 SSA 值 + // 退出基本块时,弹出在此块中压入值栈的 SSA 值,恢复栈到进入该块时的状态 // -------------------------------------------------------------------- - while (!localStackPushed.empty()) { - Value *val = localStackPushed.top(); - localStackPushed.pop(); - // 找到是哪个 alloca 对应的栈 - for (auto alloca : promotableAllocas) { - if (!allocaToValueStackMap[alloca].empty() && allocaToValueStackMap[alloca].top() == val) { - allocaToValueStackMap[alloca].pop(); - break; + for (auto alloca : promotableAllocas) { + while (allocaToValueStackMap[alloca].size() > originalStackSizes[alloca]) { + if (DEBUG) { + std::cout << "Mem2Reg: Popping value " + << (allocaToValueStackMap[alloca].top()->getName().empty() + ? "anonymous" + : allocaToValueStackMap[alloca].top()->getName()) + << " for alloca " << alloca->getName() << ". Stack size: " << allocaToValueStackMap[alloca].size() + << " -> " << (allocaToValueStackMap[alloca].size() - 1) << std::endl; } + allocaToValueStackMap[alloca].pop(); } } + } // 删除所有原始的 AllocaInst、LoadInst 和 StoreInst From aef10b48e80c97d4ba28469fc69d06111534a18c Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Fri, 1 Aug 2025 18:34:43 +0800 Subject: [PATCH 16/16] =?UTF-8?q?[midend]=E5=88=A0=E9=99=A4=E5=89=8D?= =?UTF-8?q?=E9=A9=B1=E5=90=8E=E7=BB=A7=E7=A7=BB=E9=99=A4=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E7=9A=84=E6=A3=80=E6=9F=A5=EF=BC=8Cphi?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0llvm=E9=A3=8E=E6=A0=BC=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=EF=BC=8C=E9=87=8D=E6=9E=84CFGOpt=E7=89=B9=E5=88=AB=E6=98=AF?= =?UTF-8?q?=E7=A9=BA=E5=9D=97=E5=88=A0=E9=99=A4=E7=9A=84=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=88=E5=BE=85=E9=AA=8C=E8=AF=81=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/midend/IR.h | 29 +- src/midend/IR.cpp | 19 +- src/midend/Pass/Optimize/SysYIRCFGOpt.cpp | 738 +++++++++++++--------- 3 files changed, 465 insertions(+), 321 deletions(-) diff --git a/src/include/midend/IR.h b/src/include/midend/IR.h index 6c1bbf4..adde8cf 100644 --- a/src/include/midend/IR.h +++ b/src/include/midend/IR.h @@ -576,7 +576,9 @@ public: if (iter != predecessors.end()) { predecessors.erase(iter); } else { - assert(false); + // 如果没有找到前驱块,可能是因为它已经被移除或不存在 + // 这可能是一个错误情况,或者是因为在CFG优化过程中已经处理 + // assert(false && "Predecessor block not found in BasicBlock"); } } void removeSuccessor(BasicBlock *block) { @@ -584,7 +586,9 @@ public: if (iter != successors.end()) { successors.erase(iter); } else { - assert(false); + // 如果没有找到后继块,可能是因为它已经被移除或不存在 + // 这可能是一个错误情况,或者是因为在CFG优化过程中已经处理 + // assert(false && "Successor block not found in BasicBlock"); } } void replacePredecessor(BasicBlock *oldBlock, BasicBlock *newBlock) { @@ -916,10 +920,23 @@ class PhiInst : public Instruction { Value* getIncomingValue(unsigned k) const {return getOperand(2 * k);} ///< 获取位置为k的值 BasicBlock* getIncomingBlock(unsigned k) const {return dynamic_cast(getOperand(2 * k + 1));} + Value* getIncomingValue(BasicBlock* blk) const { + return getvalfromBlk(blk); + } ///< 获取指定基本块的传入值 + + BasicBlock* getIncomingBlock(Value* val) const { + return getBlkfromVal(val); + } ///< 获取指定值的传入基本块 + + void replaceIncoming(BasicBlock *oldBlock, BasicBlock *newBlock, Value *newValue){ + delBlk(oldBlock); + addIncoming(newValue, newBlock); + } + auto& getincomings() const {return blk2val;} ///< 获取所有的基本块和对应的值 - Value* getvalfromBlk(BasicBlock* blk); - BasicBlock* getBlkfromVal(Value* val); + Value* getvalfromBlk(BasicBlock* blk) const ; + BasicBlock* getBlkfromVal(Value* val) const ; unsigned getNumIncomingValues() const { return vsize; } ///< 获取传入值的数量 void addIncoming(Value *value, BasicBlock *block) { @@ -930,6 +947,10 @@ class PhiInst : public Instruction { vsize++; } ///< 添加传入值和对应的基本块 + void removeIncoming(BasicBlock *block){ + delBlk(block); + } + void delValue(Value* val); void delBlk(BasicBlock* blk); diff --git a/src/midend/IR.cpp b/src/midend/IR.cpp index 0fd6198..b61a766 100644 --- a/src/midend/IR.cpp +++ b/src/midend/IR.cpp @@ -569,15 +569,15 @@ void User::replaceOperand(unsigned index, Value *value) { * phi相关函数 */ -Value* PhiInst::getvalfromBlk(BasicBlock* blk){ - refreshB2VMap(); +Value* PhiInst::getvalfromBlk(BasicBlock* blk) const { + // refreshB2VMap(); if( blk2val.find(blk) != blk2val.end()) { return blk2val.at(blk); } return nullptr; } -BasicBlock* PhiInst::getBlkfromVal(Value* val){ +BasicBlock* PhiInst::getBlkfromVal(Value* val) const { // 返回第一个值对应的基本块 for(unsigned i = 0; i < vsize; i++) { if(getValue(i) == val) { @@ -591,6 +591,9 @@ void PhiInst::delValue(Value* val){ //根据value删除对应的基本块和值 unsigned i = 0; BasicBlock* blk = getBlkfromVal(val); + if(blk == nullptr) { + return; // 如果val没有对应的基本块,直接返回 + } for(i = 0; i < vsize; i++) { if(getValue(i) == val) { break; @@ -606,6 +609,9 @@ void PhiInst::delBlk(BasicBlock* blk){ //根据Blk删除对应的基本块和值 unsigned i = 0; Value* val = getvalfromBlk(blk); + if(val == nullptr) { + return; // 如果blk没有对应的值,直接返回 + } for(i = 0; i < vsize; i++) { if(getBlock(i) == blk) { break; @@ -618,9 +624,12 @@ void PhiInst::delBlk(BasicBlock* blk){ } void PhiInst::replaceBlk(BasicBlock* newBlk, unsigned k){ - refreshB2VMap(); + // refreshB2VMap(); 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); @@ -630,7 +639,7 @@ void PhiInst::replaceBlk(BasicBlock* newBlk, unsigned k){ } void PhiInst::replaceold2new(BasicBlock* oldBlk, BasicBlock* newBlk){ - refreshB2VMap(); + // refreshB2VMap(); Value* val = blk2val.at(oldBlk); // 替换基本块 delBlk(oldBlk); diff --git a/src/midend/Pass/Optimize/SysYIRCFGOpt.cpp b/src/midend/Pass/Optimize/SysYIRCFGOpt.cpp index a589453..a4c584b 100644 --- a/src/midend/Pass/Optimize/SysYIRCFGOpt.cpp +++ b/src/midend/Pass/Optimize/SysYIRCFGOpt.cpp @@ -1,12 +1,12 @@ #include "SysYIRCFGOpt.h" #include "SysYIROptUtils.h" #include +#include #include #include #include -#include -#include #include // 引入队列,SysYDelNoPreBLock需要 +#include namespace sysy { @@ -18,7 +18,6 @@ void *SysYBlockMergePass::ID = (void *)&SysYBlockMergePass::ID; void *SysYAddReturnPass::ID = (void *)&SysYAddReturnPass::ID; void *SysYCondBr2BrPass::ID = (void *)&SysYCondBr2BrPass::ID; - // ====================================================================== // SysYCFGOptUtils: 辅助工具类,包含实际的CFG优化逻辑 // ====================================================================== @@ -26,40 +25,42 @@ void *SysYCondBr2BrPass::ID = (void *)&SysYCondBr2BrPass::ID; // 删除br后的无用指令 bool SysYCFGOptUtils::SysYDelInstAfterBr(Function *func) { bool changed = false; - + auto basicBlocks = func->getBasicBlocks(); for (auto &basicBlock : basicBlocks) { bool Branch = false; auto &instructions = basicBlock->getInstructions(); auto Branchiter = instructions.end(); for (auto iter = instructions.begin(); iter != instructions.end(); ++iter) { - if ((*iter)->isTerminator()){ + if ((*iter)->isTerminator()) { Branch = true; Branchiter = iter; break; } } - if (Branchiter != instructions.end()) ++Branchiter; + if (Branchiter != instructions.end()) + ++Branchiter; while (Branchiter != instructions.end()) { changed = true; Branchiter = instructions.erase(Branchiter); } - - if (Branch) { // 更新前驱后继关系 - auto thelastinstinst = basicBlock->getInstructions().end(); - --thelastinstinst; + + if (Branch) { // 更新前驱后继关系 + auto thelastinstinst = basicBlock->terminator(); auto &Successors = basicBlock->getSuccessors(); for (auto iterSucc = Successors.begin(); iterSucc != Successors.end();) { (*iterSucc)->removePredecessor(basicBlock.get()); basicBlock->removeSuccessor(*iterSucc); } if (thelastinstinst->get()->isUnconditional()) { - BasicBlock* branchBlock = dynamic_cast(thelastinstinst->get()->getOperand(0)); + auto brinst = dynamic_cast(thelastinstinst->get()); + BasicBlock *branchBlock = dynamic_cast(brinst->getBlock()); basicBlock->addSuccessor(branchBlock); branchBlock->addPredecessor(basicBlock.get()); } else if (thelastinstinst->get()->isConditional()) { - BasicBlock* thenBlock = dynamic_cast(thelastinstinst->get()->getOperand(1)); - BasicBlock* elseBlock = dynamic_cast(thelastinstinst->get()->getOperand(2)); + auto brinst = dynamic_cast(thelastinstinst->get()); + BasicBlock *thenBlock = dynamic_cast(brinst->getThenBlock()); + BasicBlock *elseBlock = dynamic_cast(brinst->getElseBlock()); basicBlock->addSuccessor(thenBlock); basicBlock->addSuccessor(elseBlock); thenBlock->addPredecessor(basicBlock.get()); @@ -75,26 +76,26 @@ bool SysYCFGOptUtils::SysYDelInstAfterBr(Function *func) { bool SysYCFGOptUtils::SysYBlockMerge(Function *func) { bool changed = false; - for (auto blockiter = func->getBasicBlocks().begin(); - blockiter != func->getBasicBlocks().end();) { + for (auto blockiter = func->getBasicBlocks().begin(); blockiter != func->getBasicBlocks().end();) { if (blockiter->get()->getNumSuccessors() == 1) { // 如果当前块只有一个后继块 // 且后继块只有一个前驱块 // 则将当前块和后继块合并 if (((blockiter->get())->getSuccessors()[0])->getNumPredecessors() == 1) { // std::cout << "merge block: " << blockiter->get()->getName() << std::endl; - BasicBlock* block = blockiter->get(); - BasicBlock* nextBlock = blockiter->get()->getSuccessors()[0]; + BasicBlock *block = blockiter->get(); + BasicBlock *nextBlock = blockiter->get()->getSuccessors()[0]; // auto nextarguments = nextBlock->getArguments(); // 删除br指令 if (block->getNumInstructions() != 0) { - auto thelastinstinst = block->end(); - (--thelastinstinst); + auto thelastinstinst = block->terminator(); if (thelastinstinst->get()->isUnconditional()) { thelastinstinst = SysYIROptUtils::usedelete(thelastinstinst); } else if (thelastinstinst->get()->isConditional()) { - // 如果是条件分支,判断条件是否相同,主要优化相同布尔表达式 - if (thelastinstinst->get()->getOperand(1)->getName() == thelastinstinst->get()->getOperand(1)->getName()) { + // 按道理不会走到这个分支 + // 如果是条件分支,查看then else是否相同 + auto brinst = dynamic_cast(thelastinstinst->get()); + if (brinst->getThenBlock() == brinst->getElseBlock()) { thelastinstinst = SysYIROptUtils::usedelete(thelastinstinst); } } @@ -104,7 +105,7 @@ bool SysYCFGOptUtils::SysYBlockMerge(Function *func) { for (auto institer = nextBlock->begin(); institer != nextBlock->end();) { institer->get()->setParent(block); block->getInstructions().emplace_back(institer->release()); - institer = nextBlock->getInstructions().erase(institer); + institer = nextBlock->getInstructions().erase(institer); } // 更新前驱后继关系,类似树节点操作 block->removeSuccessor(nextBlock); @@ -135,318 +136,431 @@ bool SysYCFGOptUtils::SysYBlockMerge(Function *func) { // 删除无前驱块,兼容SSA后的处理 bool SysYCFGOptUtils::SysYDelNoPreBLock(Function *func) { - - bool changed = false; + bool changed = false; // 标记是否有基本块被删除 + std::set reachableBlocks; // 用于存储所有可达的基本块 + std::queue blockQueue; // BFS 遍历队列 - for (auto &block : func->getBasicBlocks()) { - block->setreachableFalse(); + BasicBlock *entryBlock = func->getEntryBlock(); + if (entryBlock) { // 确保函数有入口块 + reachableBlocks.insert(entryBlock); // 将入口块标记为可达 + blockQueue.push(entryBlock); // 入口块入队 } - // 对函数基本块做一个拓扑排序,排查不可达基本块 - auto entryBlock = func->getEntryBlock(); - entryBlock->setreachableTrue(); - std::queue blockqueue; - blockqueue.push(entryBlock); - while (!blockqueue.empty()) { - auto block = blockqueue.front(); - blockqueue.pop(); - for (auto &succ : block->getSuccessors()) { - if (!succ->getreachable()) { - succ->setreachableTrue(); - blockqueue.push(succ); + // 如果没有入口块(比如一个空函数),则没有块是可达的,所有块都将被删除。 + + while (!blockQueue.empty()) { // BFS 遍历:只要队列不空 + BasicBlock *currentBlock = blockQueue.front(); + blockQueue.pop(); // 取出当前块 + + for (auto &succ : currentBlock->getSuccessors()) { // 遍历当前块的所有后继 + // 如果后继块不在 reachableBlocks 中(即尚未被访问过) + if (reachableBlocks.find(succ) == reachableBlocks.end()) { + reachableBlocks.insert(succ); // 标记为可达 + blockQueue.push(succ); // 入队,以便继续遍历 } } } - // 删除不可达基本块指令 - for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end(); blockIter++) { - if (!blockIter->get()->getreachable()) { - for (auto instIter = blockIter->get()->getInstructions().begin(); - instIter != blockIter->get()->getInstructions().end();) { - instIter = SysYIROptUtils::usedelete(instIter); + std::vector blocksToDelete; // 用于存储所有不可达的基本块 + + for (auto &blockPtr : func->getBasicBlocks()) { + BasicBlock *block = blockPtr.get(); + // 如果当前块不在 reachableBlocks 集合中,说明它是不可达的 + if (reachableBlocks.find(block) == reachableBlocks.end()) { + blocksToDelete.push_back(block); // 将其加入待删除列表 + changed = true; // 只要找到一个不可达块,就说明函数发生了改变 + } + } + + for (BasicBlock *unreachableBlock : blocksToDelete) { + // 遍历不可达块中的所有指令,并删除它们 + for (auto instIter = unreachableBlock->getInstructions().begin(); + instIter != unreachableBlock->getInstructions().end();) { + instIter = SysYIROptUtils::usedelete(instIter); + } + } + + for (BasicBlock *unreachableBlock : blocksToDelete) { + for (BasicBlock *succBlock : unreachableBlock->getSuccessors()) { + // 只有当后继块自身是可达的(没有被删除)时才需要处理 + if (reachableBlocks.count(succBlock)) { + for (auto &phiInstPtr : succBlock->getInstructions()) { + // Phi 指令总是在基本块的开头。一旦遇到非 Phi 指令即可停止。 + if (phiInstPtr->getKind() != Instruction::kPhi) { + break; + } + // 将这个 Phi 节点中来自不可达前驱(unreachableBlock)的输入参数删除 + dynamic_cast(phiInstPtr.get())->delBlk(unreachableBlock); + } } } } - for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();) { - if (!blockIter->get()->getreachable()) { - for (auto succblock : blockIter->get()->getSuccessors()) { - for (auto &phiinst : succblock->getInstructions()) { - if (phiinst->getKind() != Instruction::kPhi) { - break; - } - // 使用 delBlk 方法正确地删除对应于被删除基本块的传入值 - dynamic_cast(phiinst.get())->delBlk(blockIter->get()); - } - } - // 删除不可达基本块,注意迭代器不可达问题 + BasicBlock *currentBlock = blockIter->get(); + // 如果当前块不在可达块集合中,则将其从函数中移除 + if (reachableBlocks.find(currentBlock) == reachableBlocks.end()) { + // func->removeBasicBlock 应该返回下一个有效的迭代器 func->removeBasicBlock((blockIter++)->get()); - changed = true; } else { - blockIter++; + blockIter++; // 如果可达,则移动到下一个块 } } - + return changed; } -// 删除空块 -bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder) { +bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) { bool changed = false; - // 收集不可达基本块 - // 这里的不可达基本块是指没有实际指令的基本块 - // 当一个基本块没有实际指令例如只有phi指令和一个uncondbr指令时,也会被视作不可达 - auto basicBlocks = func->getBasicBlocks(); - std::map EmptyBlocks; - // 空块儿和后继的基本块的映射 - for (auto &basicBlock : basicBlocks) { - if (basicBlock->getNumInstructions() == 0) { - if (basicBlock->getNumSuccessors() == 1) { - EmptyBlocks[basicBlock.get()] = basicBlock->getSuccessors().front(); - } - } - else{ - // 如果只有phi指令和一个uncondbr。(phi)*(uncondbr)? - // 判断除了最后一个指令之外是不是只有phi指令 - bool onlyPhi = true; - for (auto &inst : basicBlock->getInstructions()) { - if (!inst->isPhi() && !inst->isUnconditional()) { - onlyPhi = false; - break; - } - } - if(onlyPhi && basicBlock->getNumSuccessors() == 1) // 确保有后继且只有一个 - EmptyBlocks[basicBlock.get()] = basicBlock->getSuccessors().front(); - } + // 步骤 1: 识别并映射所有符合“空块”定义的基本块及其目标后继 + // 使用 std::map 来存储 <空块, 空块跳转目标> + // 这样可以处理空块链:A -> B -> C,如果 B 是空块,A 应该跳到 C + std::map emptyBlockRedirectMap; + + // 为了避免在遍历 func->getBasicBlocks() 时修改它导致迭代器失效, + // 我们先收集所有的基本块。 + std::vector allBlocks; + for (auto &blockPtr : func->getBasicBlocks()) { + allBlocks.push_back(blockPtr.get()); } - // 更新基本块信息,增加必要指令 - for (auto &basicBlock : basicBlocks) { - // 把空块转换成只有跳转指令的不可达块 (这段逻辑在优化遍中可能需要调整,这里是原样保留) - // 通常,DelEmptyBlock 应该在BlockMerge之后运行,如果存在完全空块,它会尝试填充一个Br指令。 - // 但是,它主要目的是重定向跳转。 - if (distance(basicBlock->begin(), basicBlock->end()) == 0) { - if (basicBlock->getNumSuccessors() == 0) { - continue; - } - if (basicBlock->getNumSuccessors() > 1) { - // 如果一个空块有多个后继,说明CFG结构有问题或者需要特殊处理,这里简单assert - assert(false && "Empty block with multiple successors found during SysYDelEmptyBlock"); - } - // 这里的逻辑有点问题,如果一个块是空的,且只有一个后继,应该直接跳转到后继。 - // 如果这个块最终被删除了,那么其前驱也需要重定向。 - // 这个循环的目的是重定向现有的跳转指令,而不是创建新的。 - // 所以下面的逻辑才是核心。 - // pBuilder->setPosition(basicBlock.get(), basicBlock->end()); - // pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {}); + + for (BasicBlock *block : allBlocks) { + // 入口块通常不应该被认为是空块并删除,除非它没有实际指令且只有一个后继, + // 但为了安全起见,通常会跳过入口块的删除。 + // 如果入口块是空的,它应该被合并到它的后继,但处理起来更复杂,这里先不处理入口块为空的情况 + if (block == func->getEntryBlock()) { continue; } - auto thelastinst = basicBlock->getInstructions().end(); - --thelastinst; - - // 根据br指令传递的后继块信息,跳过空块链 - if (thelastinst->get()->isUnconditional()) { - BasicBlock* OldBrBlock = dynamic_cast(thelastinst->get()->getOperand(0)); - BasicBlock *thelastBlockOld = nullptr; - // 如果空块链表为多个块 - while (EmptyBlocks.count(dynamic_cast(thelastinst->get()->getOperand(0)))) { - thelastBlockOld = dynamic_cast(thelastinst->get()->getOperand(0)); - thelastinst->get()->replaceOperand(0, EmptyBlocks[thelastBlockOld]); - } - - // 如果有重定向发生 - if (thelastBlockOld != nullptr) { - basicBlock->removeSuccessor(OldBrBlock); - OldBrBlock->removePredecessor(basicBlock.get()); - basicBlock->addSuccessor(dynamic_cast(thelastinst->get()->getOperand(0))); - dynamic_cast(thelastinst->get()->getOperand(0))->addPredecessor(basicBlock.get()); - changed = true; // 标记IR被修改 - } - - - if (thelastBlockOld != nullptr) { - for (auto &InstInNew : dynamic_cast(thelastinst->get()->getOperand(0))->getInstructions()) { - if (InstInNew->isPhi()) { - // 使用 delBlk 方法删除 oldBlock 对应的传入值 - dynamic_cast(InstInNew.get())->delBlk(thelastBlockOld); - } else { + // 检查基本块是否是空的:除了Phi指令外,只包含一个终止指令 (Terminator) + // 且该终止指令必须是无条件跳转。 + // 空块必须只有一个后继才能被简化 + if (block->getNumSuccessors() == 1) { + bool hasNonPhiNonTerminator = false; + // 遍历除了最后一个指令之外的指令 + for (auto instIter = block->getInstructions().begin(); instIter != block->getInstructions().end();) { + // 如果是终止指令(例如 br, ret),且不是最后一个指令,则该块有问题 + if ((*instIter)->isTerminator() && instIter != block->terminator()) { + hasNonPhiNonTerminator = true; break; } - } - } - - } else if (thelastinst->get()->getKind() == Instruction::kCondBr) { - auto OldThenBlock = dynamic_cast(thelastinst->get()->getOperand(1)); - auto OldElseBlock = dynamic_cast(thelastinst->get()->getOperand(2)); - bool thenChanged = false; - bool elseChanged = false; - - - BasicBlock *thelastBlockOld = nullptr; - while (EmptyBlocks.count(dynamic_cast(thelastinst->get()->getOperand(1)))) { - thelastBlockOld = dynamic_cast(thelastinst->get()->getOperand(1)); - thelastinst->get()->replaceOperand( - 1, EmptyBlocks[dynamic_cast(thelastinst->get()->getOperand(1))]); - thenChanged = true; - } - - if (thenChanged) { - basicBlock->removeSuccessor(OldThenBlock); - OldThenBlock->removePredecessor(basicBlock.get()); - basicBlock->addSuccessor(dynamic_cast(thelastinst->get()->getOperand(1))); - dynamic_cast(thelastinst->get()->getOperand(1))->addPredecessor(basicBlock.get()); - changed = true; // 标记IR被修改 - } - - // 处理 then 和 else 分支合并的情况 - if (dynamic_cast(thelastinst->get()->getOperand(1)) == - dynamic_cast(thelastinst->get()->getOperand(2))) { - auto thebrBlock = dynamic_cast(thelastinst->get()->getOperand(1)); - thelastinst = SysYIROptUtils::usedelete(thelastinst); - pBuilder->setPosition(basicBlock.get(), basicBlock->end()); - pBuilder->createUncondBrInst(thebrBlock); - changed = true; // 标记IR被修改 - continue; - } - - if (thelastBlockOld != nullptr) { - for (auto &InstInNew : dynamic_cast(thelastinst->get()->getOperand(1))->getInstructions()) { - if (InstInNew->isPhi()) { - // 使用 delBlk 方法删除 oldBlock 对应的传入值 - dynamic_cast(InstInNew.get())->delBlk(thelastBlockOld); - } else { - break; + // 如果不是 Phi 指令且不是终止指令 + if (!(*instIter)->isPhi() && !(*instIter)->isTerminator()) { + hasNonPhiNonTerminator = true; + break; + } + ++instIter; + if (!hasNonPhiNonTerminator && + instIter == block->getInstructions().end()) { // 如果块中只有 Phi 指令和一个 Terminator + // 确保最后一个指令是无条件跳转 + auto lastInst = block->terminator()->get(); + if (lastInst && lastInst->isUnconditional()) { + emptyBlockRedirectMap[block] = block->getSuccessors().front(); } - } - } - - thelastBlockOld = nullptr; - while (EmptyBlocks.count(dynamic_cast(thelastinst->get()->getOperand(2)))) { - thelastBlockOld = dynamic_cast(thelastinst->get()->getOperand(2)); - thelastinst->get()->replaceOperand( - 2, EmptyBlocks[dynamic_cast(thelastinst->get()->getOperand(2))]); - elseChanged = true; - } - - if (elseChanged) { - basicBlock->removeSuccessor(OldElseBlock); - OldElseBlock->removePredecessor(basicBlock.get()); - basicBlock->addSuccessor(dynamic_cast(thelastinst->get()->getOperand(2))); - dynamic_cast(thelastinst->get()->getOperand(2))->addPredecessor(basicBlock.get()); - changed = true; // 标记IR被修改 - } - - // 处理 then 和 else 分支合并的情况 - if (dynamic_cast(thelastinst->get()->getOperand(1)) == - dynamic_cast(thelastinst->get()->getOperand(2))) { - auto thebrBlock = dynamic_cast(thelastinst->get()->getOperand(1)); - thelastinst = SysYIROptUtils::usedelete(thelastinst); - pBuilder->setPosition(basicBlock.get(), basicBlock->end()); - pBuilder->createUncondBrInst(thebrBlock); - changed = true; // 标记IR被修改 - continue; - } - - - // 如果有重定向发生 - // 需要更新后继块的前驱关系 - if (thelastBlockOld != nullptr) { - for (auto &InstInNew : dynamic_cast(thelastinst->get()->getOperand(2))->getInstructions()) { - if (InstInNew->isPhi()) { - // 使用 delBlk 方法删除 oldBlock 对应的传入值 - dynamic_cast(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(thelastinst->get()->getOperand(0)); - // sysy::BasicBlock *thelastBlockOld = nullptr; - // while (EmptyBlocks.find(dynamic_cast(thelastinst->get()->getOperand(0))) != - // EmptyBlocks.end()) { - // thelastBlockOld = dynamic_cast(thelastinst->get()->getOperand(0)); - - // thelastinst->get()->replaceOperand( - // 0, EmptyBlocks[dynamic_cast(thelastinst->get()->getOperand(0))]); - // } - - // basicBlock->removeSuccessor(OldBrBlock); - // OldBrBlock->removePredecessor(basicBlock.get()); - // basicBlock->addSuccessor(dynamic_cast(thelastinst->get()->getOperand(0))); - // dynamic_cast(thelastinst->get()->getOperand(0))->addPredecessor(basicBlock.get()); - // changed = true; // 标记IR被修改 - // if (thelastBlockOld != nullptr) { - // int indexphi = 0; - // for (auto &pred : dynamic_cast(thelastinst->get()->getOperand(0))->getPredecessors()) { - // if (pred == thelastBlockOld) { - // break; - // } - // indexphi++; - // } - - // for (auto &InstInNew : dynamic_cast(thelastinst->get()->getOperand(0))->getInstructions()) { - // if (InstInNew->isPhi()) { - // dynamic_cast(InstInNew.get())->removeOperand(indexphi + 1); - // } else { - // break; - // } - // } - // } + } } } } - // 真正的删除空块 - for (auto iter = func->getBasicBlocks().begin(); iter != func->getBasicBlocks().end();) { - - if (EmptyBlocks.count(iter->get())) { - // EntryBlock跳过 - if (iter->get() == func->getEntryBlock()) { - ++iter; - continue; + // 步骤 2: 遍历 emptyBlockRedirectMap,处理空块链 + // 确保每个空块都直接重定向到其最终的非空后继块 + for (auto const &[emptyBlock, directSucc] : emptyBlockRedirectMap) { + BasicBlock *targetBlock = directSucc; + // 沿着空块链一直找到最终的非空块目标 + while (emptyBlockRedirectMap.count(targetBlock)) { + targetBlock = emptyBlockRedirectMap[targetBlock]; + } + emptyBlockRedirectMap[emptyBlock] = targetBlock; // 更新映射到最终目标 + } + + // 步骤 3: 遍历所有基本块,重定向其终止指令,绕过空块 + // 注意:这里需要再次遍历所有块,包括可能成为新目标的块 + for (BasicBlock *currentBlock : allBlocks) { + // 如果 currentBlock 本身就是个空块,它会通过其前驱的重定向被处理,这里跳过 + if (emptyBlockRedirectMap.count(currentBlock)) { + continue; + } + + // 获取当前块的最后一个指令(终止指令) + if (currentBlock->getInstructions().empty()) { + // 理论上,除了入口块和可能被合并的空块外,所有块都应该有终止指令 + // 如果这里碰到空块,可能是逻辑错误或者需要特殊处理 + continue; + } + + std::function getUltimateSourceValue = [&](Value *val, + BasicBlock *currentDefBlock) -> Value * { + // 如果值不是指令,例如常量或函数参数,则它本身就是最终来源 + if (auto instr = dynamic_cast(val)) { // Assuming Value* has a method to check if it's an instruction + return val; } - for (auto instIter = iter->get()->getInstructions().begin(); - instIter != iter->get()->getInstructions().end();) { - instIter = SysYIROptUtils::usedelete(instIter); + Instruction *inst = dynamic_cast(val); + // 如果定义指令不在任何空块中,它就是最终来源 + if (!emptyBlockRedirectMap.count(currentDefBlock)) { + return val; } - // 删除不可达基本块的phi指令的操作数 - for (auto &succ : iter->get()->getSuccessors()) { - for (auto &instinsucc : succ->getInstructions()) { - if (instinsucc->isPhi()) { - // iter->get() 就是当前被删除的空基本块,它作为前驱连接到这里的Phi指令 - dynamic_cast(instinsucc.get())->delBlk(iter->get()); + + // 如果是 Phi 指令,且它在空块中,则继续追溯其在空块链中前驱的传入值 + if (inst->getKind() == Instruction::kPhi) { + PhiInst *phi = dynamic_cast(inst); + // 查找哪个前驱是空块链中的上一个块 + for (size_t i = 0; i < phi->getNumOperands(); i += 2) { + BasicBlock *incomingBlock = dynamic_cast(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(lastInst); + BasicBlock *oldTarget = dynamic_cast(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(phiInstPtr.get()); + BasicBlock *actualEmptyPredecessorOfS = nullptr; + for (size_t i = 0; i < phiInst->getNumOperands(); i += 2) { + BasicBlock *incomingBlock = dynamic_cast(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 { - // Phi 指令通常在基本块的开头,如果不是 Phi 指令就停止检查 break; } } } - func->removeBasicBlock((iter++)->get()); - changed = true; - } else { - ++iter; + } else if (lastInst->getKind() == Instruction::kCondBr) { // 条件跳转 + CondBrInst *condBrInst = dynamic_cast(lastInst); + BasicBlock *oldThenTarget = dynamic_cast(condBrInst->getThenBlock()); + BasicBlock *oldElseTarget = dynamic_cast(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(phiInstPtr.get())->delBlk(oldThenTarget); + // } else { + // break; + // } + // } + for (auto &phiInstPtr : newThenTarget->getInstructions()) { + if (phiInstPtr->getKind() == Instruction::kPhi) { + PhiInst *phiInst = dynamic_cast(phiInstPtr.get()); + BasicBlock *actualEmptyPredecessorOfS = nullptr; + for (size_t i = 0; i < phiInst->getNumOperands(); i += 2) { + BasicBlock *incomingBlock = dynamic_cast(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(phiInstPtr.get())->delBlk(oldElseTarget); + // } else { + // break; + // } + // } + for (auto &phiInstPtr : newElseTarget->getInstructions()) { + if (phiInstPtr->getKind() == Instruction::kPhi) { + PhiInst *phiInst = dynamic_cast(phiInstPtr.get()); + BasicBlock *actualEmptyPredecessorOfS = nullptr; + for (size_t i = 0; i < phiInst->getNumOperands(); i += 2) { + BasicBlock *incomingBlock = dynamic_cast(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(condBrInst->getThenBlock()); + SysYIROptUtils::usedelete(lastInst); // 删除旧的条件跳转指令 + pBuilder->setPosition(currentBlock, currentBlock->end()); + pBuilder->createUncondBrInst(commonTarget); // 插入新的无条件跳转指令 + + // 更安全地更新 CFG 关系 + std::set currentSuccessors; + currentSuccessors.insert(oldThenTarget); + currentSuccessors.insert(oldElseTarget); + + // 移除旧的后继关系 + for (BasicBlock *succ : currentSuccessors) { + currentBlock->removeSuccessor(succ); + succ->removePredecessor(currentBlock); + } + // 添加新的后继关系 + currentBlock->addSuccessor(commonTarget); + commonTarget->addPredecessor(currentBlock); + + changed = true; + } } } - + + // 步骤 4: 真正地删除空基本块 + // 注意:只能在所有跳转和 Phi 指令都更新完毕后才能删除这些块 + for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();) { + BasicBlock *currentBlock = blockIter->get(); + if (emptyBlockRedirectMap.count(currentBlock)) { // 如果在空块映射中 + // 入口块不应该被删除,即使它符合空块定义,因为函数需要一个入口 + if (currentBlock == func->getEntryBlock()) { + ++blockIter; + continue; + } + + // 在删除块之前,确保其内部指令被正确删除(虽然这类块指令很少) + for (auto instIter = currentBlock->getInstructions().begin(); + instIter != currentBlock->getInstructions().end();) { + instIter = SysYIROptUtils::usedelete(instIter); + } + + // 移除块 + func->removeBasicBlock((blockIter++)->get()); + changed = true; + } else { + ++blockIter; + } + } + return changed; } // 如果函数没有返回指令,则添加一个默认返回指令(主要解决void函数没有返回指令的问题) -bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder* pBuilder) { +bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder *pBuilder) { bool changed = false; auto basicBlocks = func->getBasicBlocks(); for (auto &block : basicBlocks) { @@ -460,7 +574,8 @@ bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder* pBuilder) { auto thelastinst = block->getInstructions().end(); --thelastinst; if (thelastinst->get()->getKind() != Instruction::kReturn) { - // std::cout << "Warning: Function " << func->getName() << " has no return instruction, adding default return." << std::endl; + // std::cout << "Warning: Function " << func->getName() << " has no return instruction, adding default + // return." << std::endl; pBuilder->setPosition(block.get(), block->end()); // TODO: 如果int float函数缺少返回值是否需要报错 @@ -476,7 +591,7 @@ bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder* pBuilder) { } } } - + return changed; } @@ -484,18 +599,18 @@ bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder* pBuilder) { // 主要针对已知条件值的分支转换为无条件分支 // 例如 if (cond) { ... } else { ... } 中的 cond 已经 // 确定为 true 或 false 的情况 -bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) { +bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder *pBuilder) { bool changed = false; for (auto &basicblock : func->getBasicBlocks()) { if (basicblock->getNumInstructions() == 0) continue; - - auto thelast = basicblock->getInstructions().end(); - --thelast; - if (thelast->get()->isConditional()){ - ConstantValue *constOperand = dynamic_cast(thelast->get()->getOperand(0)); + auto thelast = basicblock->terminator(); + + if (thelast->get()->isConditional()) { + auto condBrInst = dynamic_cast(thelast->get()); + ConstantValue *constOperand = dynamic_cast(condBrInst->getCondition()); std::string opname; int constint = 0; float constfloat = 0.0F; @@ -514,27 +629,27 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) { if (constfloat_Use || constint_Use) { changed = true; - auto thenBlock = dynamic_cast(thelast->get()->getOperand(1)); - auto elseBlock = dynamic_cast(thelast->get()->getOperand(2)); + auto thenBlock = dynamic_cast(condBrInst->getThenBlock()); + auto elseBlock = dynamic_cast(condBrInst->getElseBlock()); thelast = SysYIROptUtils::usedelete(thelast); if ((constfloat_Use && constfloat == 1.0F) || (constint_Use && constint == 1)) { // cond为true或非0 pBuilder->setPosition(basicblock.get(), basicblock->end()); pBuilder->createUncondBrInst(thenBlock); - + // 更新CFG关系 basicblock->removeSuccessor(elseBlock); elseBlock->removePredecessor(basicblock.get()); - + // 删除elseBlock的phi指令中对应的basicblock.get()的传入值 for (auto &phiinst : elseBlock->getInstructions()) { if (phiinst->getKind() != Instruction::kPhi) { break; } // 使用 delBlk 方法删除 basicblock.get() 对应的传入值 - dynamic_cast(phiinst.get())->delBlk(basicblock.get()); + dynamic_cast(phiinst.get())->removeIncoming(basicblock.get()); } - + } else { // cond为false或0 pBuilder->setPosition(basicblock.get(), basicblock->end()); @@ -550,9 +665,8 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) { break; } // 使用 delBlk 方法删除 basicblock.get() 对应的传入值 - dynamic_cast(phiinst.get())->delBlk(basicblock.get()); + dynamic_cast(phiinst.get())->removeIncoming(basicblock.get()); } - } } } @@ -565,28 +679,28 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) { // 独立的CFG优化遍的实现 // ====================================================================== -bool SysYDelInstAfterBrPass::runOnFunction(Function *F, AnalysisManager& AM) { +bool SysYDelInstAfterBrPass::runOnFunction(Function *F, AnalysisManager &AM) { return SysYCFGOptUtils::SysYDelInstAfterBr(F); } -bool SysYDelEmptyBlockPass::runOnFunction(Function *F, AnalysisManager& AM) { +bool SysYDelEmptyBlockPass::runOnFunction(Function *F, AnalysisManager &AM) { return SysYCFGOptUtils::SysYDelEmptyBlock(F, pBuilder); } -bool SysYDelNoPreBLockPass::runOnFunction(Function *F, AnalysisManager& AM) { +bool SysYDelNoPreBLockPass::runOnFunction(Function *F, AnalysisManager &AM) { return SysYCFGOptUtils::SysYDelNoPreBLock(F); } -bool SysYBlockMergePass::runOnFunction(Function *F, AnalysisManager& AM) { - return SysYCFGOptUtils::SysYBlockMerge(F); +bool SysYBlockMergePass::runOnFunction(Function *F, AnalysisManager &AM) { + return SysYCFGOptUtils::SysYBlockMerge(F); } -bool SysYAddReturnPass::runOnFunction(Function *F, AnalysisManager& AM) { +bool SysYAddReturnPass::runOnFunction(Function *F, AnalysisManager &AM) { return SysYCFGOptUtils::SysYAddReturn(F, pBuilder); } -bool SysYCondBr2BrPass::runOnFunction(Function *F, AnalysisManager& AM) { +bool SysYCondBr2BrPass::runOnFunction(Function *F, AnalysisManager &AM) { return SysYCFGOptUtils::SysYCondBr2Br(F, pBuilder); } -} // namespace sysy \ No newline at end of file +} // namespace sysy \ No newline at end of file