From f61b51b2fadb9644110baab39f235e6de16f1961 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Tue, 22 Jul 2025 21:25:07 +0800 Subject: [PATCH] =?UTF-8?q?[midend]=E4=BC=98=E5=8C=96=E4=B8=AD=E7=AB=AF?= =?UTF-8?q?=E6=A1=86=E6=9E=B6=EF=BC=8C=E7=A7=BB=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E6=97=A7=E4=BB=A3=E7=A0=81=EF=BC=8Cignore=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- src/DeadCodeElimination.cpp | 259 --------------- src/Liveness.cpp | 83 ++--- src/Mem2Reg.cpp | 515 ------------------------------ src/Pass.cpp | 132 ++++++++ src/Reg2Mem.cpp | 122 ------- src/include/DeadCodeElimination.h | 36 --- src/include/Dom.h | 2 +- src/include/Liveness.h | 5 +- src/include/Mem2Reg.h | 79 ----- src/include/Pass.h | 90 +----- src/include/Reg2Mem.h | 22 -- src/include/SysYIRPass.h | 59 ---- src/sysyc.cpp | 21 +- 14 files changed, 208 insertions(+), 1220 deletions(-) delete mode 100644 src/DeadCodeElimination.cpp delete mode 100644 src/Mem2Reg.cpp create mode 100644 src/Pass.cpp delete mode 100644 src/Reg2Mem.cpp delete mode 100644 src/include/DeadCodeElimination.h delete mode 100644 src/include/Mem2Reg.h delete mode 100644 src/include/Reg2Mem.h delete mode 100644 src/include/SysYIRPass.h diff --git a/.gitignore b/.gitignore index ce3b37a..7a9b7e6 100644 --- a/.gitignore +++ b/.gitignore @@ -53,4 +53,5 @@ __init__.py .DS_* -antlr/ \ No newline at end of file +antlr/ +.clang-format diff --git a/src/DeadCodeElimination.cpp b/src/DeadCodeElimination.cpp deleted file mode 100644 index a986b18..0000000 --- a/src/DeadCodeElimination.cpp +++ /dev/null @@ -1,259 +0,0 @@ -#include "DeadCodeElimination.h" -#include - -extern int DEBUG; -namespace sysy { - -void DeadCodeElimination::runDCEPipeline() { - const auto& functions = pModule->getFunctions(); - for (const auto& function : functions) { - const auto& func = function.second; - bool changed = true; - while (changed) { - changed = false; - eliminateDeadStores(func.get(), changed); - eliminateDeadLoads(func.get(), changed); - eliminateDeadAllocas(func.get(), changed); - eliminateDeadRedundantLoadStore(func.get(), changed); - eliminateDeadGlobals(changed); - } - } -} - -// 消除无用存储 消除条件: -// 存储的目标指针(pointer)不是全局变量(!isGlobal(pointer))。 -// 存储的目标指针不是数组参数(!isArr(pointer) 或不在函数参数列表里)。 -// 该指针的所有使用者(uses)仅限 alloca 或 store(即没有 load 或其他指令使用它)。 -void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) { - for (const auto& block : func->getBasicBlocks()) { - auto& instrs = block->getInstructions(); - for (auto iter = instrs.begin(); iter != instrs.end();) { - auto inst = iter->get(); - if (!inst->isStore()) { - ++iter; - continue; - } - - auto storeInst = dynamic_cast(inst); - auto pointer = storeInst->getPointer(); - // 如果是全局变量或者是函数的数组参数 - if (SysYIROptUtils::isGlobal(pointer) || (SysYIROptUtils::isArr(pointer) && - std::find(func->getEntryBlock()->getArguments().begin(), - func->getEntryBlock()->getArguments().end(), - pointer) != func->getEntryBlock()->getArguments().end())) { - ++iter; - continue; - } - - bool changetag = true; - for (auto& use : pointer->getUses()) { - // 依次判断store的指针是否被其他指令使用 - auto user = use->getUser(); - auto userInst = dynamic_cast(user); - // 如果使用store的指针的指令不是Alloca或Store,则不删除 - if (userInst != nullptr && !userInst->isAlloca() && !userInst->isStore()) { - changetag = false; - break; - } - } - - if (changetag) { - changed = true; - if(DEBUG){ - std::cout << "=== Dead Store Found ===\n"; - SysYPrinter::printInst(storeInst); - } - SysYIROptUtils::usedelete(storeInst); - iter = instrs.erase(iter); - } else { - ++iter; - } - } - } -} -// 消除无用加载 消除条件: -// 该指令的结果未被使用(inst->getUses().empty())。 -void DeadCodeElimination::eliminateDeadLoads(Function* func, bool& changed) { - for (const auto& block : func->getBasicBlocks()) { - auto& instrs = block->getInstructions(); - for (auto iter = instrs.begin(); iter != instrs.end();) { - auto inst = iter->get(); - if (inst->isBinary() || inst->isUnary() || inst->isLoad()) { - if (inst->getUses().empty()) { - changed = true; - if(DEBUG){ - std::cout << "=== Dead Load Binary Unary Found ===\n"; - SysYPrinter::printInst(inst); - } - SysYIROptUtils::usedelete(inst); - iter = instrs.erase(iter); - continue; - } - } - ++iter; - } - } -} - -// 消除无用加载 消除条件: -// 该 alloca 未被任何指令使用(allocaInst->getUses().empty())。 -// 该 alloca 不是函数的参数(不在 entry 块的参数列表里)。 -void DeadCodeElimination::eliminateDeadAllocas(Function* func, bool& changed) { - for (const auto& block : func->getBasicBlocks()) { - auto& instrs = block->getInstructions(); - for (auto iter = instrs.begin(); iter != instrs.end();) { - auto inst = iter->get(); - if (inst->isAlloca()) { - auto allocaInst = dynamic_cast(inst); - if (allocaInst->getUses().empty() && - std::find(func->getEntryBlock()->getArguments().begin(), - func->getEntryBlock()->getArguments().end(), - allocaInst) == func->getEntryBlock()->getArguments().end()) { - changed = true; - if(DEBUG){ - std::cout << "=== Dead Alloca Found ===\n"; - SysYPrinter::printInst(inst); - } - SysYIROptUtils::usedelete(inst); - iter = instrs.erase(iter); - continue; - } - } - ++iter; - } - } -} - -void DeadCodeElimination::eliminateDeadIndirectiveAllocas(Function* func, bool& changed) { - // 删除mem2reg时引入的且现在已经没有value使用了的隐式alloca - FunctionAnalysisInfo* funcInfo = pCFA->getFunctionAnalysisInfo(func); - for (auto it = funcInfo->getIndirectAllocas().begin(); it != funcInfo->getIndirectAllocas().end();) { - auto &allocaInst = *it; - if (allocaInst->getUses().empty()) { - changed = true; - if(DEBUG){ - std::cout << "=== Dead Indirect Alloca Found ===\n"; - SysYPrinter::printInst(allocaInst.get()); - } - it = funcInfo->getIndirectAllocas().erase(it); - } else { - ++it; - } - } -} - -// 该全局变量未被任何指令使用(global->getUses().empty())。 -void DeadCodeElimination::eliminateDeadGlobals(bool& changed) { - auto& globals = pModule->getGlobals(); - for (auto it = globals.begin(); it != globals.end();) { - auto& global = *it; - if (global->getUses().empty()) { - changed = true; - if(DEBUG){ - std::cout << "=== Dead Global Found ===\n"; - SysYPrinter::printValue(global.get()); - } - it = globals.erase(it); - } else { - ++it; - } - } -} - -// 消除冗余加载和存储 消除条件: -// phi 指令的目标指针仅被该 phi 使用(无其他 store/load 使用)。 -// memset 指令的目标指针未被使用(pointer->getUses().empty()) -// store -> load -> store 模式 -void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool& changed) { - for (const auto& block : func->getBasicBlocks()) { - auto& instrs = block->getInstructions(); - for (auto iter = instrs.begin(); iter != instrs.end();) { - auto inst = iter->get(); - if (inst->isPhi()) { - auto phiInst = dynamic_cast(inst); - auto pointer = phiInst->getPointer(); - bool tag = true; - for (const auto& use : pointer->getUses()) { - auto user = use->getUser(); - if (user != inst) { - tag = false; - break; - } - } - /// 如果 pointer 仅被该 phi 使用,可以删除 ph - if (tag) { - changed = true; - SysYIROptUtils::usedelete(inst); - iter = instrs.erase(iter); - continue; - } - // 数组指令还不完善,不保证memset优化效果 - } else if (inst->isMemset()) { - auto memsetInst = dynamic_cast(inst); - auto pointer = memsetInst->getPointer(); - if (pointer->getUses().empty()) { - changed = true; - SysYIROptUtils::usedelete(inst); - iter = instrs.erase(iter); - continue; - } - }else if(inst->isLoad()) { - if (iter != instrs.begin()) { - auto loadInst = dynamic_cast(inst); - auto loadPointer = loadInst->getPointer(); - // TODO:store -> load -> store 模式 - auto prevIter = std::prev(iter); - auto prevInst = prevIter->get(); - if (prevInst->isStore()) { - auto prevStore = dynamic_cast(prevInst); - auto prevStorePointer = prevStore->getPointer(); - auto prevStoreValue = prevStore->getOperand(0); - // 确保前一个 store 不是数组操作 - if (prevStore->getIndices().empty()) { - // 检查后一条指令是否是 store 同一个值 - auto nextIter = std::next(iter); - if (nextIter != instrs.end()) { - auto nextInst = nextIter->get(); - if (nextInst->isStore()) { - auto nextStore = dynamic_cast(nextInst); - auto nextStorePointer = nextStore->getPointer(); - auto nextStoreValue = nextStore->getOperand(0); - // 确保后一个 store 不是数组操作 - if (nextStore->getIndices().empty()) { - // 判断优化条件: - // 1. prevStore 的指针操作数 == load 的指针操作数 - // 2. nextStore 的值操作数 == load 指令本身 - if (prevStorePointer == loadPointer && - nextStoreValue == loadInst) { - // 可以优化直接把prevStorePointer的值存到nextStorePointer - changed = true; - nextStore->setOperand(0, prevStoreValue); - if(DEBUG){ - std::cout << "=== Dead Store Load Store Found(now only del Load) ===\n"; - SysYPrinter::printInst(prevStore); - SysYPrinter::printInst(loadInst); - SysYPrinter::printInst(nextStore); - } - SysYIROptUtils::usedelete(loadInst); - iter = instrs.erase(iter); - // 删除 prevStore 这里是不是可以留给删除无用store处理? - // if (prevStore->getUses().empty()) { - // usedelete(prevStore); - // instrs.erase(prevIter); // 删除 prevStore - // } - continue; // 跳过 ++iter,因为已经移动迭代器 - } - } - } - } - } - } - } - } - ++iter; - } - } -} - - -} // namespace sysy \ No newline at end of file diff --git a/src/Liveness.cpp b/src/Liveness.cpp index 8b92b3d..e1231f1 100644 --- a/src/Liveness.cpp +++ b/src/Liveness.cpp @@ -2,6 +2,7 @@ #include // For std::set_union, std::set_difference #include #include // Potentially for worklist, though not strictly needed for the iterative approach below +#include // For std::set namespace sysy { @@ -12,10 +13,6 @@ char LivenessAnalysisPass::ID = 0; // 任何唯一的地址都可以,这里用 // LivenessAnalysisResult 结果类的实现 // ============================================================== -LivenessAnalysisResult::LivenessAnalysisResult(Function *F) : AssociatedFunction(F) { - // 构造时可以不计算,在分析遍运行里计算并填充 -} - const std::set *LivenessAnalysisResult::getLiveIn(BasicBlock *BB) const { auto it = liveInSets.find(BB); if (it != liveInSets.end()) { @@ -36,70 +33,83 @@ const std::set *LivenessAnalysisResult::getLiveOut(BasicBlock *BB) cons } void LivenessAnalysisResult::computeDefUse(BasicBlock *BB, std::set &def, std::set &use) { - def.clear(); - use.clear(); + def.clear(); // 将持有在 BB 中定义的值 + use.clear(); // 将持有在 BB 中使用但在其定义之前的值 + + // 临时集合,用于跟踪当前基本块中已经定义过的变量 + std::set defined_in_block_so_far; // 按照指令在块中的顺序遍历 for (const auto &inst_ptr : BB->getInstructions()) { Instruction *inst = inst_ptr.get(); - // 检查指令是否产生值 (Def) - if (inst->hasValue()) { // 假设 Instruction 有 hasValue() 方法判断是否生成结果值 - // 如果这个值在此指令之前在块中被使用过,则它是一个 Use - // 否则,它是 Def - if (use.find(inst) == use.end()) { // 如果当前指令本身的值未被当前块内之前的指令使用 - def.insert(inst); + // 1. 处理指令的操作数 (Use) - 在定义之前的使用 + for (const auto &use_ptr : inst->getOperands()) { // 修正迭代器类型 + Value *operand = use_ptr->getValue(); // 从 shared_ptr 获取 Value* + + // 过滤掉常量和全局变量,因为它们通常不被视为活跃变量 + ConstantValue *constValue = dynamic_cast(operand); + GlobalValue *globalValue = dynamic_cast(operand); + if (constValue || globalValue) { + continue; // 跳过常量和全局变量 + } + + // 如果操作数是一个变量(Instruction 或 Argument),并且它在此基本块的当前点之前尚未被定义 + if (defined_in_block_so_far.find(operand) == defined_in_block_so_far.end()) { + use.insert(operand); } } - // 检查指令的操作数 (Use) - for (Value *operand : inst->getOperands()) { // 假设 Instruction 有 getOperands() 返回 Value* - // 只有当操作数是一个Instruction或Argument且未在当前块中被定义时,才算作 Use - if (auto opInst = dynamic_cast(operand)) { - if (def.find(opInst) == def.end()) { // 如果操作数不是由当前块中之前的指令定义 - use.insert(opInst); - } - } else if (auto arg = dynamic_cast(operand)) { - use.insert(arg); - } - // 常量和全局变量不计入 Def/Use 集合,因为它们不随控制流变化 + // 2. 处理指令自身产生的定义 (Def) + if (inst->isDefine()) { // 使用 isDefine() 方法 + // 指令自身定义了一个值。将其添加到块的 def 集合, + // 并添加到当前块中已定义的值的临时集合。 + def.insert(inst); // inst 本身就是被定义的值(例如,虚拟寄存器) + defined_in_block_so_far.insert(inst); } } } void LivenessAnalysisResult::computeLiveness(Function *F) { // 每次计算前清空旧结果 - liveInSets[F].clear(); - liveOutSets[F].clear(); + liveInSets.clear(); // 直接清空 map,不再使用 F 作为键 + liveOutSets.clear(); // 直接清空 map // 初始化所有基本块的 LiveIn 和 LiveOut 集合为空 for (const auto &bb_ptr : F->getBasicBlocks()) { BasicBlock *bb = bb_ptr.get(); - liveInSets[F][bb] = {}; - liveOutSets[F][bb] = {}; + liveInSets[bb] = {}; // 直接以 bb 为键 + liveOutSets[bb] = {}; // 直接以 bb 为键 } bool changed = true; while (changed) { changed = false; - // 迭代所有基本块,通常逆序遍历(reverse post-order)可以加快收敛, - // 但为了简化,这里直接遍历所有块。 - for (const auto &bb_ptr : F->getBasicBlocks()) { - BasicBlock *bb = bb_ptr.get(); + // TODO : 目前为逆序遍历基本块,考虑反向拓扑序遍历基本块 - std::set oldLiveIn = liveInSets[F][bb]; - std::set oldLiveOut = liveOutSets[F][bb]; + // 逆序遍历基本块 + std::list> basicBlocks(F->getBasicBlocks().begin(), F->getBasicBlocks().end()); + std::reverse(basicBlocks.begin(), basicBlocks.end()); + // 然后遍历 basicBlocks + + for (auto bb_iter = basicBlocks.begin(); bb_iter != basicBlocks.end(); ++bb_iter) { + BasicBlock *bb = bb_iter->get(); + if (!bb) + continue; // 避免空指针 + + std::set oldLiveIn = liveInSets[bb]; + std::set oldLiveOut = liveOutSets[bb]; // 1. 计算 LiveOut(BB) = Union(LiveIn(Succ) for Succ in Successors(BB)) std::set newLiveOut; for (BasicBlock *succ : bb->getSuccessors()) { - const std::set *succLiveIn = getLiveIn(succ); // 递归获取后继的 LiveIn + const std::set *succLiveIn = getLiveIn(succ); // 获取后继的 LiveIn if (succLiveIn) { newLiveOut.insert(succLiveIn->begin(), succLiveIn->end()); } } - liveOutSets[F][bb] = newLiveOut; + liveOutSets[bb] = newLiveOut; // 2. 计算 LiveIn(BB) = Use(BB) Union (LiveOut(BB) - Def(BB)) std::set defSet, useSet; @@ -111,7 +121,7 @@ void LivenessAnalysisResult::computeLiveness(Function *F) { std::set newLiveIn = useSet; newLiveIn.insert(liveOutMinusDef.begin(), liveOutMinusDef.end()); - liveInSets[F][bb] = newLiveIn; + liveInSets[bb] = newLiveIn; // 检查是否发生变化 if (oldLiveIn != newLiveIn || oldLiveOut != newLiveOut) { @@ -130,7 +140,6 @@ bool LivenessAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) { CurrentLivenessResult = std::make_unique(F); // 调用 LivenessAnalysisResult 内部的方法来计算分析结果 - // 这里的 computeLiveness 不需要 AM 参数,因为它自身不依赖其他分析。 CurrentLivenessResult->computeLiveness(F); // 分析遍通常不修改 IR,所以返回 false diff --git a/src/Mem2Reg.cpp b/src/Mem2Reg.cpp deleted file mode 100644 index 2daef27..0000000 --- a/src/Mem2Reg.cpp +++ /dev/null @@ -1,515 +0,0 @@ -#include "Mem2Reg.h" -#include "SysYIRPrinter.h" -#include -#include -#include -#include -#include -#include -#include -#include - -namespace sysy { - -// --- 私有成员函数实现 --- - -// 计算给定定义块集合的迭代支配边界 -std::unordered_set Mem2Reg::computeIteratedDomFrontiers(const std::unordered_set& blocks) { - std::unordered_set result; - std::queue worklist; // 使用队列进行 BFS-like 遍历 - - for (auto* block : blocks) - worklist.push(block); - - while (!worklist.empty()) { - auto* block = worklist.front(); - worklist.pop(); - - auto* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(block); - if (!blockInfo) continue; - - for (auto* df : blockInfo->getDomFrontiers()) { - if (result.find(df) == result.end()) { // If not already in result - result.insert(df); - worklist.push(df); - } - } - } - return result; -} - -// 分析一个 alloca 的所有 uses,填充 allocaDefsBlock 和 allocaUsesBlock -void Mem2Reg::allocaAnalysis(AllocaInst* alloca) { - allocaDefsBlock[alloca].clear(); - allocaUsesBlock[alloca].clear(); - - for (auto use : alloca->getUses()) { - Instruction* userInst = dynamic_cast(use->getUser()); - if (!userInst) continue; - - if (StoreInst* store = dynamic_cast(userInst)) { - if (store->getOperand(1) == alloca) { // Store's second operand is the pointer - allocaDefsBlock[alloca].insert(store->getParent()); // Store's parent is the defining block - } - } else if (LoadInst* load = dynamic_cast(userInst)) { - if (load->getOperand(0) == alloca) { // Load's first operand is the pointer - allocaUsesBlock[alloca].insert(load->getParent()); // Load's parent is the using block - } - } - } -} - -// 判断一个 alloca 是否可以被提升为寄存器 (无地址逃逸,标量类型) -bool Mem2Reg::is_promoted(AllocaInst* alloca) { - // 检查是否是标量类型 (非数组、非全局变量等) - if(!(SysYIROptUtils::isArr(alloca) || SysYIROptUtils::isGlobal(alloca))){ - return false; // 只有标量类型的 alloca 才能被提升 - } - - // 获取 alloca 指向的基类型 - PointerType* ptrType = dynamic_cast(alloca->getType()); - if (!ptrType) return false; // Should always be a pointer type - Type* allocabaseType = ptrType->getBaseType(); - - for (const auto& use : alloca->getUses()) { - Instruction* userInst = dynamic_cast(use->getUser()); - if (!userInst) { - // 如果不是指令的 use,比如作为全局变量的初始值等,通常认为逃逸 - return false; - } - - if (LoadInst* load = dynamic_cast(userInst)) { - // Load 指令结果的类型必须与 alloca 的基类型一致 - if (load->getType() != allocabaseType) { - return false; - } - } else if (StoreInst* store = dynamic_cast(userInst)) { - // Store 指令的值操作数类型必须与 alloca 的基类型一致 - // 且 store 的指针操作数必须是当前 alloca - if (store->getOperand(1) != alloca || store->getOperand(0)->getType() != allocabaseType) { - return false; - } - } else if (userInst->isGetSubArray()) { - // GSA 指令表示对数组的访问 - // 这意味着地址逃逸,不能简单提升为单个寄存器 - return false; - } else if (userInst->isCall()) { - // 如果 alloca 作为函数参数传递,通常认为地址逃逸 - return false; - } - // 如果有其他类型的指令使用 alloca 的地址,也需要判断是否是逃逸 - // 例如:BitCastInst, PtrToIntInst, 如果这些操作将地址暴露,则不能提升 - } - return true; -} - -// 在迭代支配边界处插入 Phi 指令 -void Mem2Reg::insertPhiNodes(Function* func) { - // 清空上次 Phi 插入的结果 - phiMap.clear(); - allPhiInstructions.clear(); - - std::unordered_set phiPlacementBlocks; // 存放需要插入 Phi 的块 - std::queue workQueue; // BFS 队列,用于迭代支配边界计算 - - // 遍历所有可提升的 alloca - for (AllocaInst* alloca : currentFunctionAllocas) { - phiPlacementBlocks.clear(); // 为每个 alloca 重新计算 Phi 放置位置 - - // 初始化工作队列,放入所有定义该 alloca 的基本块 - for (BasicBlock* defBB : allocaDefsBlock[alloca]) { - workQueue.push(defBB); - } - - while (!workQueue.empty()) { - BasicBlock* currentBB = workQueue.front(); - workQueue.pop(); - - auto* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(currentBB); - if (!blockInfo) continue; - - // 遍历当前块的支配边界 - for (BasicBlock* domFrontierBB : blockInfo->getDomFrontiers()) { - // 如果这个支配边界块还没有为当前 alloca 插入 Phi 指令 - if (phiPlacementBlocks.find(domFrontierBB) == phiPlacementBlocks.end()) { - // 获取 alloca 的基类型,作为 Phi 指令的结果类型 - Type* phiType = dynamic_cast(alloca->getType())->getBaseType(); - - // 在支配边界块的开头插入 Phi 指令 - pBuilder->setPosition(domFrontierBB->begin()); - PhiInst* newPhi = pBuilder->createPhiInst(phiType, {}, {}); // 初始入边为空 - - allPhiInstructions.push_back(newPhi); // 记录所有 Phi - phiPlacementBlocks.insert(domFrontierBB); // 标记已插入 - - // 将 Phi 指令映射到它所代表的原始 alloca - phiMap[domFrontierBB][newPhi] = alloca; - - // 如果支配边界块本身没有定义该 alloca,则其支配边界也可能需要 Phi - // 只有当这个块不是当前alloca的定义块时,才将其加入workQueue,以计算其DF。 - if (allocaDefsBlock[alloca].find(domFrontierBB) == allocaDefsBlock[alloca].end()) { - workQueue.push(domFrontierBB); - } - } - } - } - } -} - -// 获取前驱块在后继块前驱列表中的索引 -int Mem2Reg::getPredIndex(BasicBlock* pred, BasicBlock* succ) { - int index = 0; - for (auto* elem : succ->getPredecessors()) { - if (elem == pred) { - return index; - } - ++index; - } - // 断言通常在你的 IR 框架中应该确保前驱是存在的 - // assert(false && "Predecessor not found in successor's predecessor list"); - return -1; // 应该不会发生 -} - -// 递归地重命名基本块中的变量并填充 Phi 指令 -void Mem2Reg::renameBlock(BasicBlock* block, - std::unordered_map& currentIncomings, - std::unordered_set& visitedBlocks) { - - // 记录在此块中发生的定义,以便在退出时将它们从栈中弹出 - std::unordered_map definitionsInBlockCount; - - // 如果已经访问过这个块,直接返回(防止无限循环或重复处理,在DFS中尤其重要) - if (visitedBlocks.count(block)) { - return; - } - visitedBlocks.insert(block); - - // --- 1. 处理当前基本块内的指令 --- - // 使用迭代器安全地遍历和删除指令 - for (auto it = block->getInstructions().begin(); it != block->getInstructions().end(); ) { - Instruction* currentInst = it->get(); - - if (AllocaInst* alloca = dynamic_cast(currentInst)) { - // 如果是可提升的 alloca,标记为删除 - if (std::find(currentFunctionAllocas.begin(), currentFunctionAllocas.end(), alloca) != currentFunctionAllocas.end()) { - SysYIROptUtils::usedelete(currentInst); // 标记为删除(或直接删除取决于你的 IR 管理) - it = block->getInstructions().erase(it); // 从列表中移除 - continue; // 继续下一个指令 - } - } else if (LoadInst* load = dynamic_cast(currentInst)) { - AllocaInst* originalAlloca = dynamic_cast(load->getOperand(0)); // load 的第一个操作数是指针 - if (originalAlloca && std::find(currentFunctionAllocas.begin(), currentFunctionAllocas.end(), originalAlloca) != currentFunctionAllocas.end()) { - // 如果是可提升 alloca 的 load 指令 - Value* incomingVal = nullptr; - if (currentIncomings.count(originalAlloca)) { - incomingVal = currentIncomings[originalAlloca]; - } else { - // 如果在当前路径上没有找到定义,则使用 UndefinedValue - incomingVal = UndefinedValue::get(originalAlloca->getType()->isPointer() ? - dynamic_cast(originalAlloca->getType())->getBaseType() : - originalAlloca->getType()); - } - - load->replaceAllUsesWith(incomingVal); // 用最新值替换所有 load 的用途 - SysYIROptUtils::usedelete(currentInst); - it = block->getInstructions().erase(it); - continue; - } - } else if (StoreInst* store = dynamic_cast(currentInst)) { - AllocaInst* originalAlloca = dynamic_cast(store->getOperand(1)); // store 的第二个操作数是指针 - if (originalAlloca && std::find(currentFunctionAllocas.begin(), currentFunctionAllocas.end(), originalAlloca) != currentFunctionAllocas.end()) { - // 如果是可提升 alloca 的 store 指令,更新当前值 - currentIncomings[originalAlloca] = store->getOperand(0); // store 的第一个操作数是值 - definitionsInBlockCount[originalAlloca]++; // 记录在该块中进行的定义数量 - SysYIROptUtils::usedelete(currentInst); - it = block->getInstructions().erase(it); - continue; - } - } else if (PhiInst* phi = dynamic_cast(currentInst)) { - // 如果是 Mem2Reg 插入的 Phi 指令 (通过 phiMap 判断) - if (phiMap[block].count(phi)) { - AllocaInst* originalAlloca = phiMap[block][phi]; - currentIncomings[originalAlloca] = phi; // Phi 指令本身成为该变量的新定义 - definitionsInBlockCount[originalAlloca]++; // 记录该 Phi 的定义 - } - } - ++it; // 移动到下一个指令 - } - - // --- 2. 填充后继基本块中 Phi 指令的入边 --- - for (BasicBlock* successorBB : block->getSuccessors()) { - int predIndex = getPredIndex(block, successorBB); - if (predIndex == -1) continue; - - // Phi 指令总是在基本块的开头 - for (auto& inst_ptr : successorBB->getInstructions()) { - if (PhiInst* phi = dynamic_cast(inst_ptr.get())) { - if (phiMap[successorBB].count(phi)) { // 确保这是我们关心的 Phi 指令 - AllocaInst* originalAlloca = phiMap[successorBB][phi]; - Value* incomingValue = nullptr; - - if (currentIncomings.count(originalAlloca)) { - incomingValue = currentIncomings[originalAlloca]; - } else { - // 如果在当前块没有找到对应的定义,使用 UndefinedValue - incomingValue = UndefinedValue::get(originalAlloca->getType()->isPointer() ? - dynamic_cast(originalAlloca->getType())->getBaseType() : - originalAlloca->getType()); - } - - if (incomingValue) { - phi->addIncoming(incomingValue, block); // 添加 (值, 前驱块) 对 - } - } - } else { - // 遇到非 Phi 指令,说明已经处理完所有 Phi,可以跳出 - break; - } - } - } - - // --- 3. 递归调用支配树的子节点 --- - auto* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(block); - if (blockInfo) { - for (BasicBlock* dominatedChildBB : blockInfo->getSdoms()) { // getSdoms 获取直接支配的子节点 - // 递归调用,传递当前 Incomings 的副本(或通过值传递以实现回溯) - // 注意:这里是传递 `currentIncomings` 的拷贝,以便递归返回后可以恢复。 - // 但如果 `currentIncomings` 是引用传递,则这里需要回溯逻辑。 - // 鉴于它是值传递,此处的 `definitionsInBlockCount` 仅用于统计,无需实际操作 `currentIncomings`。 - renameBlock(dominatedChildBB, currentIncomings, visitedBlocks); - } - } - - // --- 4. 回溯:从栈中弹出在此块中创建的所有定义 --- - for (auto const& [alloca, count] : definitionsInBlockCount) { - // 在我们的实现中,`currentIncomings` 是通过值传递的,每次递归都收到一个新的拷贝。 - // 因此,不需要显式地 "pop" 栈。`currentIncomings` 在函数返回时会自动销毁。 - // 这种方式模拟了 "SSA 栈" 的行为,每个函数调用帧有自己的局部定义环境。 - } -} - -// 简化冗余的 Phi 指令 (当所有输入都相同时) -void Mem2Reg::simplifyphi(PhiInst* phi) { - BasicBlock* phifromblock = phi->getParent(); - if (!phifromblock) return; // 指令可能已经被删除 - - Value* commonValue = nullptr; - bool allSame = true; - - // Phi 指令的操作数是 Value, BasicBlock 交替出现,所以是 getOperandSize() / 2 个入边 - if (phi->getNumOperands() == 0) { // 空 Phi,通常是无效的,直接删除 - phi->replaceAllUsesWith(UndefinedValue::get(phi->getType())); // 用 UndefinedValue 替换所有用途 - // phi->getParent()->delete_inst(phi); - // 删除 Phi 指令后直接返回 - // phi指令在开头一个比较快 - // TODO:后续可优化查找 - auto tofind = std::find_if(phifromblock->getInstructions().begin(), phifromblock->getInstructions().end(), - [phi](const auto &instr) { return instr.get() == phi; }); - SysYIROptUtils::usedelete(phi); // 使用 SysYIROptUtils 删除指令 - phifromblock->getInstructions().erase(tofind); - // 从基本块中删除 Phi 指令 - return; - } - - for (size_t i = 0; i < phi->getNumIncomingValues(); ++i) { - Value* incomingVal = phi->getOperand(2 * i); // 值位于偶数索引 - - if (incomingVal == phi) { // 如果 Phi 指令引用自身 (循环变量) - // 这种情况下,Phi 暂时不能简化,除非所有入边都是它自己,这通常通过其他优化处理 - // 为避免复杂性,我们在此处不处理自引用 Phi 的简化,除非它是唯一选择。 - // 更好的做法是,如果所有入边都指向自身,则该Phi是冗余的,可以替换为undef或其第一个实际值 - // 但这需要更复杂的分析来确定循环的初始值。目前简单返回。 - // TODO:留到后续循环优化处理 - return; - } - - if (commonValue == nullptr) { - commonValue = incomingVal; - } else if (commonValue != incomingVal) { - allSame = false; - break; // 发现不同的入边值 - } - } - - if (allSame && commonValue != nullptr) { - // 所有入边值都相同,用这个值替换 Phi 指令的所有用途 - phi->replaceAllUsesWith(commonValue); - // 从基本块中删除 Phi 指令 - auto tofind = std::find_if(phifromblock->getInstructions().begin(), phifromblock->getInstructions().end(), - [phi](const auto &instr) { return instr.get() == phi; }); - SysYIROptUtils::usedelete(phi); // 使用 SysYIROptUtils 删除指令 - phifromblock->getInstructions().erase(tofind); - } -} - -// 对单个函数执行内存到寄存器的提升 -bool Mem2Reg::promoteMemoryToRegisters(Function* func) { - bool changed = false; - - // 每次开始对一个函数进行 Mem2Reg 时,清空所有上下文信息 - currentFunctionAllocas.clear(); - allocaDefsBlock.clear(); - allocaUsesBlock.clear(); - phiMap.clear(); - allPhiInstructions.clear(); - - // 1. 收集所有可提升的 AllocaInst,并进行初步分析 - BasicBlock* entryBB = func->getEntryBlock(); - if (!entryBB) return false; - - // 逆序遍历入口块的指令,安全地识别 Alloca - for (auto it = entryBB->getInstructions().rbegin(); it != entryBB->getInstructions().rend(); ++it) { - if (AllocaInst* alloca = dynamic_cast(it->get())) { - if (is_promoted(alloca)) { - currentFunctionAllocas.push_back(alloca); - } - } - } - // 收集后反转,使其按原始顺序排列 (如果需要的话,但对后续分析影响不大) - std::reverse(currentFunctionAllocas.begin(), currentFunctionAllocas.end()); - - // 对收集到的所有 alloca 进行 DefsBlock 和 UsesBlock 分析 - for (AllocaInst* alloca : currentFunctionAllocas) { - allocaAnalysis(alloca); - } - - // 2. 预处理:删除无用的 AllocaInst (没有 Load 和 Store) - // 迭代 currentFunctionAllocas,安全删除 - for (unsigned int i = 0; i < currentFunctionAllocas.size(); ) { - AllocaInst* alloca = currentFunctionAllocas[i]; - - bool hasRelevantUse = false; - // 检查 alloca 的 uses 列表,看是否有 Load 或 Store - // 只要有 Load/Store,就认为是"相关用途",不删除 - for (auto use_ptr : alloca->getUses()) { - Instruction* user_inst = dynamic_cast(use_ptr->getUser()); - if (user_inst && (dynamic_cast(user_inst) || dynamic_cast(user_inst))) { - hasRelevantUse = true; - break; - } - } - - // 如果没有相关用途(没有 Load 和 Store),则 alloca 是死代码 - if (!hasRelevantUse && allocaDefsBlock[alloca].empty() && allocaUsesBlock[alloca].empty()) { - if (alloca->getParent()) { - // alloca->getParent()->delete_inst(alloca); // 从其所在块删除 alloca 指令 - auto tofind = std::find_if(alloca->getParent()->getInstructions().begin(), alloca->getParent()->getInstructions().end(), - [alloca](const auto &instr) { return instr.get() == alloca; }); - SysYIROptUtils::usedelete(alloca); - alloca->getParent()->getInstructions().erase(tofind); - } - currentFunctionAllocas.erase(currentFunctionAllocas.begin() + i); // 从列表中移除 - changed = true; // 发生了改变 - } else { - i++; // 否则,移动到下一个 alloca - } - } - - // 如果没有可提升的 alloca 了,直接返回 - if (currentFunctionAllocas.empty()) { - return changed; - } - - // 3. 插入 Phi 指令 - insertPhiNodes(func); - if (!allPhiInstructions.empty()) changed = true; - - // 4. 重命名变量,转换为 SSA 形式并填充 Phi 指令 - std::unordered_map initialIncomings; - std::unordered_set visitedBlocks; // 用于 DFS 遍历,防止循环 - - // 初始化 entry block 的 Incomings 状态 - for (AllocaInst* alloca : currentFunctionAllocas) { - initialIncomings[alloca] = UndefinedValue::get(dynamic_cast(alloca->getType())->getBaseType()); - } - - // 从入口块开始递归重命名 - renameBlock(entryBB, initialIncomings, visitedBlocks); - - // 5. 简化 Phi 指令 - // 由于 renameBlock 可能会删除 Phi,这里复制一份列表以安全迭代 - std::vector phisToSimplify = allPhiInstructions; - for (PhiInst* phi : phisToSimplify) { - // 检查 phi 是否还在 IR 中 (可能已被其他优化删除) - // 一个简单检查是看它是否有父块 - if (phi->getParent()) { - simplifyphi(phi); - // simplifyphi 内部会删除 Phi,所以这里不需要再处理 allPhiInstructions - // 最终的 allPhiInstructions 清理将在 promoteMemoryToRegisters 结束后进行 - } - } - - // 清理所有 Phi 的列表和映射 - // 遍历 allPhiInstructions,删除那些在 simplifyphi 后可能仍然存在的、但已经没有 uses 的 Phi - std::vector remainingPhis; - for(PhiInst* phi : allPhiInstructions) { - if(phi->getParent() && phi->getUses().empty()){ // 如果还在IR中但没有用处 - - // phi->getParent()->delete_inst(phi); - // 找到phi节点对应的迭代器 - auto tofind = std::find_if(phi->getParent()->getInstructions().begin(), phi->getParent()->getInstructions().end(), - [phi](const auto &instr) { return instr.get() == phi; }); - SysYIROptUtils::usedelete(phi); // 使用 SysYIROptUtils 删除指令 - phi->getParent()->getInstructions().erase(tofind); - - changed = true; - } else if (phi->getParent()) { // 仍在IR中且有uses - remainingPhis.push_back(phi); - } - } - allPhiInstructions = remainingPhis; // 更新为仅包含未被删除的 Phi - - // 重新清理 phiMap 中已经删除的 Phi 指令项 - for (auto& pairBBPhiMap : phiMap) { - std::vector phisToRemoveFromMap; - for (auto& pairPhiAlloca : pairBBPhiMap.second) { - if (!pairPhiAlloca.first->getParent()) { // 如果 Phi 已经被删除 - phisToRemoveFromMap.push_back(pairPhiAlloca.first); - } - } - for (PhiInst* phi : phisToRemoveFromMap) { - pairBBPhiMap.second.erase(phi); - } - } - - - return changed; -} - -// --- run函数实现 --- -void Mem2Reg::run() { - // 每次运行整个 Mem2Reg Pass 时,重新进行分析 - controlFlowAnalysis->clear(); - controlFlowAnalysis->runControlFlowAnalysis(); - activeVarAnalysis->clear(); - // 假设 dataFlowAnalysisUtils 可以管理和运行各个分析器 - dataFlowAnalysisUtils.addBackwardAnalyzer(activeVarAnalysis); - dataFlowAnalysisUtils.backwardAnalyze(pModule); // 运行活跃变量分析 - - bool globalChanged = false; - // 循环直到没有更多的 alloca 可以被提升 - // 每次 promoteMemoryToRegisters 会尝试在一个函数内完成所有 Mem2Reg 优化 - do { - globalChanged = false; - for (const auto& [_, func] : pModule->getFunctions()) { - // 对每个函数执行 Mem2Reg - if (promoteMemoryToRegisters(func.get())) { - globalChanged = true; - // 如果一个函数发生改变,可能影响其他函数或需要重新分析 - // 因此需要重新运行控制流和活跃变量分析,以备下一次循环 - controlFlowAnalysis->clear(); - controlFlowAnalysis->runControlFlowAnalysis(); - activeVarAnalysis->clear(); - dataFlowAnalysisUtils.backwardAnalyze(pModule); // 重新分析活跃变量 - } - } - } while (globalChanged); // 如果全局有任何函数发生改变,则继续迭代 - - // 最终清理和重新分析 - controlFlowAnalysis->clear(); - controlFlowAnalysis->runControlFlowAnalysis(); - activeVarAnalysis->clear(); - dataFlowAnalysisUtils.backwardAnalyze(pModule); -} - -} // namespace sysy \ No newline at end of file diff --git a/src/Pass.cpp b/src/Pass.cpp new file mode 100644 index 0000000..c9ec38d --- /dev/null +++ b/src/Pass.cpp @@ -0,0 +1,132 @@ +// Pass.cpp +#include "Pass.h" +#include "SysYIRCFGOpt.h" +#include "SysYIRPrinter.h" +#include +#include +#include +#include +#include +#include +#include "Dom.h" +#include "Liveness.h" + +namespace sysy { + +extern int DEBUG; // 全局调试标志 + +// ====================================================================== +// 封装优化流程的函数:包含Pass注册和迭代运行逻辑 +// ====================================================================== + +void PassManager::runOptimizationPipeline(Module* moduleIR, int optLevel) { + if (DEBUG) std::cout << "--- Starting Middle-End Optimizations (Level -O" << optLevel << ") ---\n"; + + // 1. 注册所有可用的分析遍和优化遍 + // 这些注册只需执行一次。 + sysy::registerAnalysisPass(); + sysy::registerAnalysisPass(); + + + // 2. 创建遍管理器 + sysy::PassManager pm(moduleIR); + + // 3. 根据优化级别添加不同的优化遍 + if (optLevel >= 1) { + if (DEBUG) std::cout << "Applying -O1 optimizations.\n"; + + // 4. 循环执行遍,直到 IR 稳定 (不再有任何遍修改 IR) + bool changed_in_iteration = true; + int iteration_count = 0; + while(changed_in_iteration) { + iteration_count++; + if (DEBUG) std::cout << "Optimization iteration: " << iteration_count << std::endl; + changed_in_iteration = pm.run(); // 运行一次所有添加到 PassManager 的遍 + if (DEBUG && changed_in_iteration) { + std::cout << "=== IR after iteration " << iteration_count << " ===\n"; + SysYPrinter printer_iter(moduleIR); + printer_iter.printIR(); + } + } + if (DEBUG) std::cout << "Optimizations stabilized after " << iteration_count << " iterations.\n"; + } + + + if (DEBUG) { + std::cout << "=== Final IR After Middle-End Optimizations (Level -O" << optLevel << ") ===\n"; + SysYPrinter printer(moduleIR); + printer.printIR(); + } +} + +void PassManager::addPass(void *passID) { + + PassRegistry ®istry = PassRegistry::getPassRegistry(); + std::unique_ptr P = registry.createPass(passID); + if (!P) { + // Error: Pass not found or failed to create + return; + } + + passes.push_back(std::move(P)); +} + +// 运行所有注册的遍 +bool PassManager::run() { + bool changed = false; + for (const auto &p : passes) { + bool passChanged = false; // 记录当前遍是否修改了 IR + + // 处理优化遍的分析依赖和失效 + if (p->getPassKind() == Pass::PassKind::Optimization) { + OptimizationPass *optPass = static_cast(p.get()); + std::set analysisDependencies; + std::set analysisInvalidations; + optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations); + + // PassManager 不显式运行分析依赖。 + // 而是优化遍在 runOnFunction 内部通过 AnalysisManager.getAnalysisResult 按需请求。 + } + + if (p->getGranularity() == Pass::Granularity::Module) { + passChanged = p->runOnModule(pmodule, analysisManager); + } else if (p->getGranularity() == Pass::Granularity::Function) { + for (auto &funcPair : pmodule->getFunctions()) { + Function *F = funcPair.second.get(); + passChanged = p->runOnFunction(F, analysisManager) || passChanged; + + if (passChanged && p->getPassKind() == Pass::PassKind::Optimization) { + OptimizationPass *optPass = static_cast(p.get()); + std::set analysisDependencies; + std::set analysisInvalidations; + optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations); + for (void *invalidationID : analysisInvalidations) { + analysisManager.invalidateAnalysis(invalidationID, F); + } + } + } + } else if (p->getGranularity() == Pass::Granularity::BasicBlock) { + for (auto &funcPair : pmodule->getFunctions()) { + Function *F = funcPair.second.get(); + for (auto &bbPtr : funcPair.second->getBasicBlocks()) { + passChanged = p->runOnBasicBlock(bbPtr.get(), analysisManager) || passChanged; + + if (passChanged && p->getPassKind() == Pass::PassKind::Optimization) { + OptimizationPass *optPass = static_cast(p.get()); + std::set analysisDependencies; + std::set analysisInvalidations; + optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations); + for (void *invalidationID : analysisInvalidations) { + analysisManager.invalidateAnalysis(invalidationID, F); + } + } + } + } + } + changed = changed || passChanged; + } + return changed; + +} + +} // namespace sysy \ No newline at end of file diff --git a/src/Reg2Mem.cpp b/src/Reg2Mem.cpp deleted file mode 100644 index d90812a..0000000 --- a/src/Reg2Mem.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "Reg2Mem.h" -#include -#include -#include -#include - -namespace sysy { - -/** - * 删除phi节点 - * 删除phi节点后可能会生成冗余存储代码 - */ -void Reg2Mem::DeletePhiInst(){ - auto &functions = pModule->getFunctions(); - for (auto &function : functions) { - auto basicBlocks = function.second->getBasicBlocks(); - for (auto &basicBlock : basicBlocks) { - - for (auto iter = basicBlock->begin(); iter != basicBlock->end();) { - auto &instruction = *iter; - if (instruction->isPhi()) { - auto predBlocks = basicBlock->getPredecessors(); - // 寻找源和目的 - // 目的就是phi指令的第一个操作数 - // 源就是phi指令的后续操作数 - auto destination = instruction->getOperand(0); - int predBlockindex = 0; - for (auto &predBlock : predBlocks) { - ++predBlockindex; - // 判断前驱块儿只有一个后继还是多个后继 - // 如果有多个 - auto source = instruction->getOperand(predBlockindex); - if (source == destination) { - continue; - } - // std::cout << predBlock->getNumSuccessors() << std::endl; - if (predBlock->getNumSuccessors() > 1) { - // 创建一个basicblock - auto newbasicBlock = function.second->addBasicBlock(); - std::stringstream ss; - ss << "phidel.L" << pBuilder->getLabelIndex(); - newbasicBlock->setName(ss.str()); - ss.str(""); - // // 修改前驱后继关系 - basicBlock->replacePredecessor(predBlock, newbasicBlock); - // predBlock = newbasicBlock; - newbasicBlock->addPredecessor(predBlock); - newbasicBlock->addSuccessor(basicBlock.get()); - predBlock->removeSuccessor(basicBlock.get()); - predBlock->addSuccessor(newbasicBlock); - // std::cout << "the block name is " << basicBlock->getName() << std::endl; - // for (auto pb : basicBlock->getPredecessors()) { - // // newbasicBlock->addPredecessor(pb); - // std::cout << pb->getName() << std::endl; - // } - // sysy::BasicBlock::conectBlocks(newbasicBlock, static_cast(basicBlock.get())); - // 若后为跳转指令,应该修改跳转指令所到达的位置 - auto thelastinst = predBlock->end(); - (--thelastinst); - - if (thelastinst->get()->isConditional() || thelastinst->get()->isUnconditional()) { // 如果是跳转指令 - auto opnum = thelastinst->get()->getNumOperands(); - for (size_t i = 0; i < opnum; i++) { - if (thelastinst->get()->getOperand(i) == basicBlock.get()) { - thelastinst->get()->replaceOperand(i, newbasicBlock); - } - } - } - // 在新块中插入store指令 - pBuilder->setPosition(newbasicBlock, newbasicBlock->end()); - // pBuilder->createStoreInst(source, destination); - if (source->isInt() || source->isFloat()) { - pBuilder->createStoreInst(source, destination); - } else { - auto loadInst = pBuilder->createLoadInst(source); - pBuilder->createStoreInst(loadInst, destination); - } - // pBuilder->createMoveInst(Instruction::kMove, destination->getType(), destination, source, - // newbasicBlock); - pBuilder->setPosition(newbasicBlock, newbasicBlock->end()); - pBuilder->createUncondBrInst(basicBlock.get(), {}); - } else { - // 如果前驱块只有一个后继 - auto thelastinst = predBlock->end(); - (--thelastinst); - // std::cout << predBlock->getName() << std::endl; - // std::cout << thelastinst->get() << std::endl; - // std::cout << "First point 11 " << std::endl; - if (thelastinst->get()->isConditional() || thelastinst->get()->isUnconditional()) { - // 在跳转语句前insert st指令 - pBuilder->setPosition(predBlock, thelastinst); - } else { - pBuilder->setPosition(predBlock, predBlock->end()); - } - - if (source->isInt() || source->isFloat()) { - pBuilder->createStoreInst(source, destination); - } else { - auto loadInst = pBuilder->createLoadInst(source); - pBuilder->createStoreInst(loadInst, destination); - } - } - } - // 删除phi指令 - auto &instructions = basicBlock->getInstructions(); - SysYIROptUtils::usedelete(iter->get()); - iter = instructions.erase(iter); - if (basicBlock->getNumInstructions() == 0) { - if (basicBlock->getNumSuccessors() == 1) { - pBuilder->setPosition(basicBlock.get(), basicBlock->end()); - pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {}); - } - } - } else { - break; - } - } - } - } -} - -} // namespace sysy diff --git a/src/include/DeadCodeElimination.h b/src/include/DeadCodeElimination.h deleted file mode 100644 index 9864a2d..0000000 --- a/src/include/DeadCodeElimination.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "IR.h" -#include "SysYIRAnalyser.h" -#include "SysYIRPrinter.h" -#include "SysYIROptUtils.h" - -namespace sysy { - -class DeadCodeElimination { - private: - Module *pModule; - ControlFlowAnalysis *pCFA; // 控制流分析指针 - ActiveVarAnalysis *pAVA; // 活跃变量分析指针 - DataFlowAnalysisUtils dataFlowAnalysisUtils; // 数据流分析工具类 - - public: - explicit DeadCodeElimination(Module *pMoudle, - ControlFlowAnalysis *pCFA = nullptr, - ActiveVarAnalysis *pAVA = nullptr) - : pModule(pMoudle), pCFA(pCFA), pAVA(pAVA), dataFlowAnalysisUtils() {} // 构造函数 - - // TODO:根据参数传入的passes来运行不同的死代码删除流程 - // void runDCEPipeline(const std::vector& passes = { - // "dead-store", "redundant-load-store", "dead-load", "dead-alloca", "dead-global" - // }); - void runDCEPipeline(); // 运行死代码删除 - - void eliminateDeadStores(Function* func, bool& changed); // 消除无用存储 - void eliminateDeadLoads(Function* func, bool& changed); // 消除无用加载 - void eliminateDeadAllocas(Function* func, bool& changed); // 消除无用内存分配 - void eliminateDeadGlobals(bool& changed); // 消除无用全局变量 - void eliminateDeadIndirectiveAllocas(Function* func, bool& changed); // 消除无用间接内存分配(phi节点) - void eliminateDeadRedundantLoadStore(Function* func, bool& changed); // 消除冗余加载和存储 -}; -} // namespace sysy diff --git a/src/include/Dom.h b/src/include/Dom.h index 6b38f83..1a09f34 100644 --- a/src/include/Dom.h +++ b/src/include/Dom.h @@ -41,7 +41,7 @@ public: // 实现 getPassID void* getPassID() const override { return &ID; } - bool runOnFunction(Function* F) override; + bool runOnFunction(Function* F, AnalysisManager &AM) override; std::unique_ptr getResult() override; diff --git a/src/include/Liveness.h b/src/include/Liveness.h index d804d33..713053a 100644 --- a/src/include/Liveness.h +++ b/src/include/Liveness.h @@ -20,7 +20,8 @@ class Instruction; class LivenessAnalysisResult : public AnalysisResultBase { public: LivenessAnalysisResult(Function *F); // 构造函数,需要一个函数来关联结果 - + LivenessAnalysisResult::LivenessAnalysisResult(Function *F) : AssociatedFunction(F) {} + // 获取给定基本块的 LiveIn 集合 const std::set *getLiveIn(BasicBlock *BB) const; @@ -52,7 +53,7 @@ public: static char ID; // LLVM 风格的唯一 ID LivenessAnalysisPass() : AnalysisPass("LivenessAnalysis", Pass::Granularity::Function) {} - + // 实现 getPassID void *getPassID() const override { return &ID; } diff --git a/src/include/Mem2Reg.h b/src/include/Mem2Reg.h deleted file mode 100644 index 2c65583..0000000 --- a/src/include/Mem2Reg.h +++ /dev/null @@ -1,79 +0,0 @@ -// 假设 Mem2Reg.h 看起来像这样 (你需要根据实际情况调整) -#ifndef SYSY_MEM2REG_H -#define SYSY_MEM2REG_H - -#include -#include -#include -#include -#include // For computeIteratedDomFrontiers - -// Include your IR and analysis headers -#include "IR.h" -#include "IRBuilder.h" -#include "SysYIRAnalyser.h" -#include "SysYIROptUtils.h" - -namespace sysy { - -class Mem2Reg { -private: - Module* pModule; - IRBuilder* pBuilder; - ControlFlowAnalysis* controlFlowAnalysis; - ActiveVarAnalysis* activeVarAnalysis; - DataFlowAnalysisUtils dataFlowAnalysisUtils; // If this is part of Mem2Reg or an external helper - -public: - Mem2Reg(Module* module, IRBuilder* builder, ControlFlowAnalysis* cfa, ActiveVarAnalysis* ava) - : pModule(module), pBuilder(builder), controlFlowAnalysis(cfa), activeVarAnalysis(ava) {} - // Constructor initializes members - void run(); - - // --- 新增的私有成员变量和方法,用于SSA转换上下文 --- - // 这是核心,用于存储 SSA 转换过程中的状态 - std::vector currentFunctionAllocas; // 当前函数中所有可提升的 alloca - // alloca -> set of BasicBlocks where it's defined (stored into) - std::unordered_map> allocaDefsBlock; - // alloca -> set of BasicBlocks where it's used (loaded from) - std::unordered_map> allocaUsesBlock; - - // BasicBlock -> Map of (PhiInst, Original AllocaInst) - // 用于在 rename 阶段通过 phi 指令找到它代表的原始 alloca - std::unordered_map> phiMap; - std::vector allPhiInstructions; // 收集所有创建的 Phi 指令以便后续简化和清理 - - // --- 核心 SSA 转换辅助函数 --- - // 计算给定定义块集合的迭代支配边界 - std::unordered_set computeIteratedDomFrontiers(const std::unordered_set& blocks); - - // 分析一个 alloca 的所有 uses,填充 allocaDefsBlock 和 allocaUsesBlock - void allocaAnalysis(AllocaInst* alloca); - - // 判断一个 alloca 是否可以被提升为寄存器 (无地址逃逸,标量类型) - bool is_promoted(AllocaInst* alloca); - - // 在迭代支配边界处插入 Phi 指令 - void insertPhiNodes(Function* func); - - // 递归地重命名基本块中的变量并填充 Phi 指令 - // 这里的 `count` 和 `stacks` 是临时的,用于 DFS 过程中传递状态 - void renameBlock(BasicBlock* block, - std::unordered_map& currentIncomings, - std::unordered_set& visitedBlocks); // 修改为传递 map 和 set - - // 简化冗余的 Phi 指令 (当所有输入都相同时) - void simplifyphi(PhiInst* phi); - - // 获取前驱块在后继块前驱列表中的索引,用于 Phi 指令入边 - int getPredIndex(BasicBlock* pred, BasicBlock* succ); - - // --- Mem2Reg 的主要工作流函数 --- - // 对单个函数执行内存到寄存器的提升 - bool promoteMemoryToRegisters(Function* func); - -}; - -} // namespace sysy - -#endif // SYSY_MEM2REG_H \ No newline at end of file diff --git a/src/include/Pass.h b/src/include/Pass.h index 063462f..17a61b8 100644 --- a/src/include/Pass.h +++ b/src/include/Pass.h @@ -111,6 +111,9 @@ private: // AnalysisManager: 负责管理和提供分析结果 // ====================================================================== class AnalysisManager { +private: + std::map, std::unique_ptr> cachedResults; + // cachedResults 存储分析结果,键是 (Function*, AnalysisPass ID) public: AnalysisManager() = default; ~AnalysisManager() = default; @@ -172,97 +175,38 @@ public: cachedResults = std::move(newCachedResults); } } - -private: - std::map, std::unique_ptr> cachedResults; }; // ====================================================================== // PassManager:遍管理器 // ====================================================================== class PassManager { - +private: + std::vector> passes; + AnalysisManager analysisManager; Module *pmodule; - AnalysisManager &AM; // 引用 AnalysisManager,用于获取分析结果 public: PassManager() = default; ~PassManager() = default; - // 添加遍:现在接受 Pass 的 ID,而不是直接的 unique_ptr - void addPass(void *passID) { - PassRegistry ®istry = PassRegistry::getPassRegistry(); - std::unique_ptr P = registry.createPass(passID); - if (!P) { - // Error: Pass not found or failed to create - return; - } - - passes.push_back(std::move(P)); + PassManager(Module *module) : pmodule(module) { + analysisManager = AnalysisManager(); // 初始化分析管理器 } - + // 运行所有注册的遍 - bool run(Module *M) { - bool changed = false; - for (const auto &p : passes) { - bool passChanged = false; // 记录当前遍是否修改了 IR + bool run(); + + // 运行优化管道主要负责注册和运行优化遍 + // 这里可以根据 optLevel 和 DEBUG 控制不同的优化遍 + void runOptimizationPipeline(Module* moduleIR, int optLevel); - // 处理优化遍的分析依赖和失效 - if (p->getPassKind() == Pass::PassKind::Optimization) { - OptimizationPass *optPass = static_cast(p.get()); - std::set analysisDependencies; - std::set analysisInvalidations; - optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations); - - // PassManager 不显式运行分析依赖。 - // 而是优化遍在 runOnFunction 内部通过 AnalysisManager.getAnalysisResult 按需请求。 - } - - if (p->getGranularity() == Pass::Granularity::Module) { - passChanged = p->runOnModule(M, AM); - } else if (p->getGranularity() == Pass::Granularity::Function) { - for (auto &funcPair : M->getFunctions()) { - Function *F = funcPair.second.get(); - passChanged = p->runOnFunction(F, AM) || passChanged; - - if (passChanged && p->getPassKind() == Pass::PassKind::Optimization) { - OptimizationPass *optPass = static_cast(p.get()); - std::set analysisDependencies; - std::set analysisInvalidations; - optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations); - for (void *invalidationID : analysisInvalidations) { - analysisManager.invalidateAnalysis(invalidationID, F); - } - } - } - } else if (p->getGranularity() == Pass::Granularity::BasicBlock) { - for (auto &funcPair : M->getFunctions()) { - Function *F = funcPair.second.get(); - for (auto &bbPtr : funcPair.second->getBasicBlocks()) { - passChanged = p->runOnBasicBlock(bbPtr.get(), AM) || passChanged; - - if (passChanged && p->getPassKind() == Pass::PassKind::Optimization) { - OptimizationPass *optPass = static_cast(p.get()); - std::set analysisDependencies; - std::set analysisInvalidations; - optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations); - for (void *invalidationID : analysisInvalidations) { - analysisManager.invalidateAnalysis(invalidationID, F); - } - } - } - } - } - changed = changed || passChanged; - } - return changed; - } + // 添加遍:现在接受 Pass 的 ID,而不是直接的 unique_ptr + void addPass(void *passID); AnalysisManager &getAnalysisManager() { return analysisManager; } -private: - std::vector> passes; - AnalysisManager analysisManager; + }; // ====================================================================== diff --git a/src/include/Reg2Mem.h b/src/include/Reg2Mem.h deleted file mode 100644 index 8eec1b6..0000000 --- a/src/include/Reg2Mem.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "IR.h" -#include "IRBuilder.h" -#include "SysYIROptUtils.h" - -namespace sysy { -/** - * Reg2Mem(后端未做phi指令翻译) - */ -class Reg2Mem { -private: - Module *pModule; - IRBuilder *pBuilder; - -public: - Reg2Mem(Module *pMoudle, IRBuilder *pBuilder) : pModule(pMoudle), pBuilder(pBuilder) {} - - void DeletePhiInst(); -}; - -} // namespace sysy \ No newline at end of file diff --git a/src/include/SysYIRPass.h b/src/include/SysYIRPass.h deleted file mode 100644 index cb6e6a9..0000000 --- a/src/include/SysYIRPass.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include "IR.h" - -namespace sysy { - -// 前置声明 -class FunctionPass; -class ModulePass; -class AnalysisPass; -class PassManager; - -// 抽象基类 Pass -class Pass { -public: - enum PassKind { - PK_Function, - PK_Module, - PK_Analysis - }; - - Pass(PassKind kind, const std::string& name) : Kind(kind), Name(name) {} - virtual ~Pass() = default; - - PassKind getPassKind() const { return Kind; } - const std::string& getPassName() const { return Name; } - - // 每个Pass需要实现此方法来执行其逻辑 - // 具体的run方法将根据Pass类型在FunctionPass和ModulePass中定义 -protected: - PassKind Kind; - std::string Name; -}; - -// 针对函数的优化遍 -class FunctionPass : public Pass { -public: - FunctionPass(const std::string& name) : Pass(PK_Function, name) {} - // 真正的优化逻辑将在此方法中实现 - virtual bool runOnFunction(Function& F) = 0; -}; - -// 针对模块的优化遍 -class ModulePass : public Pass { -public: - ModulePass(const std::string& name) : Pass(PK_Module, name) {} - // 真正的优化逻辑将在此方法中实现 - virtual bool runOnModule(Module& M) = 0; -}; - -// 分析遍 -class AnalysisPass : public Pass { -public: - AnalysisPass(const std::string& name) : Pass(PK_Analysis, name) {} - // 分析遍通常需要一个模块或函数作为输入,并计算出分析结果 - // 具体分析结果的存储和访问方式需要设计 -}; - -} // namespace sysy \ No newline at end of file diff --git a/src/sysyc.cpp b/src/sysyc.cpp index 1afe7c9..c22c0a8 100644 --- a/src/sysyc.cpp +++ b/src/sysyc.cpp @@ -13,13 +13,10 @@ using namespace antlr4; #include "SysYIRGenerator.h" #include "SysYIRPrinter.h" -#include "SysYIRCFGOpt.h" +#include "SysYIRCFGOpt.h" // 包含 CFG 优化 #include "RISCv64Backend.h" -// #include "SysYIRAnalyser.h" -// #include "DeadCodeElimination.h" +#include "Pass.h" // 包含新的 Pass 框架 #include "AddressCalculationExpansion.h" -// #include "Mem2Reg.h" -// #include "Reg2Mem.h" using namespace sysy; @@ -131,17 +128,13 @@ int main(int argc, char **argv) { if (argStopAfter == "ird") { DEBUG = 1; // 这里可能需要更精细地控制 DEBUG 的开启时机和范围 } - // 默认优化 pass (在所有优化级别都会执行) - SysYCFGOpt cfgopt(moduleIR, builder); - cfgopt.SysYOptimizateAfterIR(); - - // ControlFlowAnalysis cfa(moduleIR); - // cfa.init(); - // ActiveVarAnalysis ava; - // ava.init(moduleIR); + + // 创建 Pass 管理器并运行优化管道 + PassManager passManager(moduleIR); // 创建 Pass 管理器 + passManager.runOptimizationPipeline(moduleIR, optLevel); if (DEBUG) { - cout << "=== After CFA & AVA (Default) ===\n"; + cout << "=== Init IR ===\n"; SysYPrinter(moduleIR).printIR(); // 临时打印器用于调试 } AddressCalculationExpansion ace(moduleIR, builder);