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] =?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