From 3dbb394bc2c5456a1d0f5891055aa6b8d72994ab Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Tue, 24 Jun 2025 22:39:20 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E5=88=86=E6=9E=90=E5=99=A8=EF=BC=8C=E5=A2=9E=E5=8A=A0=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E6=B5=81=E5=88=86=E6=9E=90=EF=BC=8C=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E6=94=AF=E9=85=8D=E8=8A=82=E7=82=B9=E8=AE=A1=E7=AE=97=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E9=85=8D=E6=A0=91=E6=9E=84=E5=BB=BA=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E9=85=8D=E8=BE=B9=E7=95=8C=E8=AE=A1=E7=AE=97=EF=BC=8C=E4=B8=BA?= =?UTF-8?q?=E5=90=8E=E7=BB=ADMem2reg=E5=81=9A=E5=87=86=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SysYIRAnalyser.cpp | 259 ++++++++++++++++++++++++++++++ src/include/SysYIRAnalyser.h | 299 +++++++++++++++++++++++++++++++++++ 2 files changed, 558 insertions(+) diff --git a/src/SysYIRAnalyser.cpp b/src/SysYIRAnalyser.cpp index e69de29..f7c685d 100644 --- a/src/SysYIRAnalyser.cpp +++ b/src/SysYIRAnalyser.cpp @@ -0,0 +1,259 @@ +#include "SysYIRAnalyser.h" + + +namespace sysy { + + +void ControlFlowAnalysis::init() { + // 初始化分析器 + auto &functions = pModule->getFunctions(); + for (const auto &function : functions) { + auto func = function.second.get(); + auto basicBlocks = func->getBasicBlocks(); + for (auto &basicBlock : basicBlocks) { + blockAnalysisInfo[basicBlock.get()] = new BlockAnalysisInfo(); + blockAnalysisInfo[basicBlock.get()]->clear(); + } + functionAnalysisInfo[func] = new FunctionAnalysisInfo(); + functionAnalysisInfo[func]->clear(); + } +} + +void ControlFlowAnalysis::runControlFlowAnalysis() { + // 运行控制流分析 + clear(); // 清空之前的分析结果 + init(); // 初始化分析器 + computeDomNode(); + computeDomTree(); + computeDomFrontierAllBlk(); +} + +void ControlFlowAnalysis::intersectOP4Dom(std::unordered_set &dom, const std::unordered_set &other) { + // 计算交集 + for (auto it = dom.begin(); it != dom.end();) { + if (other.find(*it) == other.end()) { + // 如果other中没有这个基本块,则从dom中删除 + it = dom.erase(it); + } else { + ++it; + } + } +} + +auto ControlFlowAnalysis::findCommonDominator(BasicBlock *a, BasicBlock *b) -> BasicBlock * { + // 查找两个基本块的共同支配结点 + while (a != b) { + BlockAnalysisInfo* infoA = blockAnalysisInfo[a]; + BlockAnalysisInfo* infoB = blockAnalysisInfo[b]; + // 如果深度不同,则向上移动到直接支配结点 + // TODO:空间换时间倍增优化,优先级较低 + while (infoA->getDomDepth() > infoB->getDomDepth()) a = const_cast(infoA->getIdom()); + while (infoB->getDomDepth() > infoA->getDomDepth()) b = const_cast(infoB->getIdom()); + if (a == b) break; + a = const_cast(infoA->getIdom()); + b = const_cast(infoB->getIdom()); + } + return a; +} + +void ControlFlowAnalysis::computeDomNode(){ + auto &functions = pModule->getFunctions(); + // 分析每个函数内的基本块 + for (const auto &function : functions) { + auto func = function.second.get(); + auto basicBlocks = func->getBasicBlocks(); + std::unordered_set domSetTmp; + // 一开始把domSetTmp置为所有block + auto entry_block = func->getEntryBlock(); + entry_block->setName("Entry"); + blockAnalysisInfo[entry_block]->addDominants(entry_block); + for (auto &basicBlock : basicBlocks) { + domSetTmp.emplace(basicBlock.get()); + } + // 初始化 + for (auto &basicBlock : basicBlocks) { + if (basicBlock.get() != entry_block) { + blockAnalysisInfo[basicBlock.get()]->setDominants(domSetTmp); + // 先把所有block的必经结点都设为N + } + } + + // 支配节点计算公式 + //DOM[B]={B}∪ {⋂P∈pred(B) DOM[P]} + // 其中pred(B)是B的所有前驱结点 + // 迭代计算支配结点,直到不再变化 + // 这里使用迭代法,直到支配结点不再变化 + // TODO:Lengauer-Tarjan 算法可以更高效地计算支配结点 + // 或者按照CFG拓扑序遍历效率更高 + bool changed = true; + while (changed) { + changed = false; + // 循环非start结点 + for (auto &basicBlock : basicBlocks) { + if (basicBlock.get() != entry_block) { + auto olddom = + blockAnalysisInfo[basicBlock.get()]->getDominants(); + + std::unordered_set dom = + blockAnalysisInfo[basicBlock->getPredecessors().front()]->getDominants(); + + // 对于每个基本块,计算其支配结点 + // 取其前驱结点的支配结点的交集和自己 + for (auto pred : basicBlock->getPredecessors()) { + intersectOP4Dom(dom, blockAnalysisInfo[pred]->getDominants()); + } + dom.emplace(basicBlock.get()); + blockAnalysisInfo[basicBlock.get()]->setDominants(dom); + + if (dom != olddom) { + changed = true; + } + } + } + } + } +} + +void ControlFlowAnalysis::computeDomTree() { + // 构造支配树 + auto &functions = pModule->getFunctions(); + for (const auto &function : functions) { + auto func = function.second.get(); + auto basicBlocks = func->getBasicBlocks(); + auto entry_block = func->getEntryBlock(); + + blockAnalysisInfo[entry_block]->setIdom(entry_block); + blockAnalysisInfo[entry_block]->setDomDepth(0); // 入口块深度为0 + + bool changed = true; + while (changed) { + changed = false; + + for (auto &basicBlock : basicBlocks) { + if (basicBlock.get() == entry_block) continue; + + BasicBlock *new_idom = nullptr; + for (auto pred : basicBlock->getPredecessors()) { + // 跳过未处理的前驱 + if (blockAnalysisInfo[pred]->getIdom() == nullptr) continue; + new_idom = (new_idom == nullptr) ? pred : findCommonDominator(new_idom, pred); + // if (new_idom == nullptr) + // new_idom = pred; + // else + // new_idom = findCommonDominator(new_idom, pred); + } + // 更新直接支配节点 + if (new_idom && new_idom != blockAnalysisInfo[basicBlock.get()]->getIdom()) { + // 移除旧的支配关系 + if (blockAnalysisInfo[basicBlock.get()]->getIdom()) { + blockAnalysisInfo[const_cast(blockAnalysisInfo[basicBlock.get()]->getIdom())]->removeSdoms(basicBlock.get()); + } + // 设置新的支配关系 + blockAnalysisInfo[basicBlock.get()]->setIdom(new_idom); + blockAnalysisInfo[new_idom]->addSdoms(basicBlock.get()); + // 更新深度 = 直接支配节点深度 + 1 + blockAnalysisInfo[basicBlock.get()]->setDomDepth( + blockAnalysisInfo[new_idom]->getDomDepth() + 1); + + changed = true; + } + } + } + } + // for (auto &basicBlock : basicBlocks) { + // if (basicBlock.get() != func->getEntryBlock()) { + // auto dominats = + // blockAnalysisInfo[basicBlock.get()]->getDominants(); + // bool found = false; + // // 从前驱结点开始寻找直接支配结点 + // std::queue q; + // for (auto pred : basicBlock->getPredecessors()) { + // q.push(pred); + // } + // // BFS遍历前驱结点,直到找到直接支配结点 + // while (!found && !q.empty()) { + // auto curr = q.front(); + // q.pop(); + // if (curr == basicBlock.get()) + // continue; + // if (dominats.count(curr) != 0U) { + // blockAnalysisInfo[basicBlock.get()]->setIdom(curr); + // blockAnalysisInfo[curr]->addSdoms(basicBlock.get()); + // found = true; + // } else { + // for (auto pred : curr->getPredecessors()) { + // q.push(pred); + // } + // } + // } + // } + // } +} + +// std::unordered_set ControlFlowAnalysis::computeDomFrontier(BasicBlock *block) { +// std::unordered_set ret_list; +// // 计算 localDF +// for (auto local_successor : block->getSuccessors()) { +// if (local_successor->getIdom() != block) { +// ret_list.emplace(local_successor); +// } +// } +// // 计算 upDF +// for (auto up_successor : block->getSdoms()) { +// auto childrenDF = computeDF(up_successor); +// for (auto w : childrenDF) { +// if (block != w->getIdom() || block == w) { +// ret_list.emplace(w); +// } +// } +// } + +// return ret_list; +// } + +void ControlFlowAnalysis::computeDomFrontierAllBlk() { + auto &functions = pModule->getFunctions(); + for (const auto &function : functions) { + auto func = function.second.get(); + auto basicBlocks = func->getBasicBlocks(); + + // 按支配树深度排序(从深到浅) + std::vector orderedBlocks; + for (auto &bb : basicBlocks) { + orderedBlocks.push_back(bb.get()); + } + std::sort(orderedBlocks.begin(), orderedBlocks.end(), + [this](BasicBlock *a, BasicBlock *b) { + return blockAnalysisInfo[a]->getDomDepth() > blockAnalysisInfo[b]->getDomDepth(); + }); + + // 计算支配边界 + for (auto block : orderedBlocks) { + std::unordered_set df; + + // Local DF: 直接后继中不被当前块支配的 + for (auto succ : block->getSuccessors()) { + // 当前块不支配该后继(即不是其直接支配节点) + if (blockAnalysisInfo[succ]->getIdom() != block) { + df.insert(succ); + } + } + + // Up DF: 从支配子树中继承 + for (auto child : blockAnalysisInfo[block]->getSdoms()) { + for (auto w : blockAnalysisInfo[child]->getDomFrontiers()) { + // 如果w不被当前块支配 + if (block != blockAnalysisInfo[w]->getIdom()) { + df.insert(w); + } + } + } + + blockAnalysisInfo[block]->setDomFrontiers(df); + } + } +} + + +} // namespace sysy + diff --git a/src/include/SysYIRAnalyser.h b/src/include/SysYIRAnalyser.h index e69de29..2cb3f1f 100644 --- a/src/include/SysYIRAnalyser.h +++ b/src/include/SysYIRAnalyser.h @@ -0,0 +1,299 @@ +#pragma once + +#include "IR.h" + +namespace sysy { + +// 前向声明 + +class Loop; +// 基本块分析信息类 +class BlockAnalysisInfo { + +public: + using block_list = std::vector; + using block_set = std::unordered_set; + +protected: + // 支配树相关 + int domdepth = 0; ///< 支配节点所在深度 + BasicBlock* idom = nullptr; ///< 直接支配结点 + block_list sdoms; ///< 支配树后继 + block_set dominants; ///< 必经结点集合 + block_set dominant_frontiers; ///< 支配边界 + + // 后续添加循环分析相关 + // Loop* loopbelong = nullptr; ///< 所属循环 + // int loopdepth = 0; ///< 循环深度 + +public: + // getterface + const int getDomDepth() const { return domdepth; } + const BasicBlock* getIdom() const { return idom; } + const block_list& getSdoms() const { return sdoms; } + const block_set& getDominants() const { return dominants; } + const block_set& getDomFrontiers() const { return dominant_frontiers; } + + // 支配树操作 + void setDomDepth(int depth) { domdepth = depth; } + void setIdom(BasicBlock* block) { idom = block; } + void addSdoms(BasicBlock* block) { sdoms.push_back(block); } + void clearSdoms() { sdoms.clear(); } + void removeSdoms(BasicBlock* block) { + sdoms.erase(std::remove(sdoms.begin(), sdoms.end(), block), sdoms.end()); + } + void addDominants(BasicBlock* block) { dominants.emplace(block); } + void addDominants(const block_set& blocks) { dominants.insert(blocks.begin(), blocks.end()); } + void setDominants(BasicBlock* block) { + dominants.clear(); + addDominants(block); + } + void setDominants(const block_set& doms) { + dominants = doms; + } + void setDomFrontiers(const block_set& df) { + dominant_frontiers = df; + } + + + // TODO:循环分析操作方法 + + // 清空所有分析信息 + void clear() { + domdepth = -1; + idom = nullptr; + sdoms.clear(); + dominants.clear(); + dominant_frontiers.clear(); + // loopbelong = nullptr; + // loopdepth = 0; + } +}; + +// 函数分析信息类 +class FunctionAnalysisInfo { + + +public: + // 函数属性 + enum FunctionAttribute : uint64_t { + PlaceHolder = 0x0UL, + Pure = 0x1UL << 0, + SelfRecursive = 0x1UL << 1, + SideEffect = 0x1UL << 2, + NoPureCauseMemRead = 0x1UL << 3 + }; + + // 数据结构 + using Loop_list = std::list>; + using block_loop_map = std::unordered_map; + using value_block_map = std::unordered_map; + using value_block_count_map = std::unordered_map>; + + // 分析数据 + FunctionAttribute attribute = PlaceHolder; ///< 函数属性 + std::set callees; ///< 函数调用集合 + Loop_list loops; ///< 所有循环 + Loop_list topLoops; ///< 顶层循环 + block_loop_map basicblock2Loop; ///< 基本块到循环映射 + std::list> indirectAllocas; ///< 间接分配内存 + + // 值定义/使用信息 + value_block_map value2AllocBlocks; ///< 值分配位置映射 + value_block_count_map value2DefBlocks; ///< 值定义位置映射 + value_block_count_map value2UseBlocks; ///< 值使用位置映射 + + // 函数属性操作 + FunctionAttribute getAttribute() const { return attribute; } + void setAttribute(FunctionAttribute attr) { attribute = static_cast(attribute | attr); } + void clearAttribute() { attribute = PlaceHolder; } + + // 调用关系操作 + void addCallee(Function* callee) { callees.insert(callee); } + void removeCallee(Function* callee) { callees.erase(callee); } + void clearCallees() { callees.clear(); } + + // 循环分析操作 + Loop* getLoopOfBasicBlock(BasicBlock* bb) { + auto it = basicblock2Loop.find(bb); + return it != basicblock2Loop.end() ? it->second : nullptr; + } + + void addBBToLoop(BasicBlock* bb, Loop* loop) { basicblock2Loop[bb] = loop; } + + unsigned getLoopDepthByBlock(BasicBlock* bb) { + Loop* loop = getLoopOfBasicBlock(bb); + return loop ? loop->getLoopDepth() : 0; + } + + // 值-块映射操作 + void addValue2AllocBlocks(Value* value, BasicBlock* block) { value2AllocBlocks[value] = block; } + + BasicBlock* getAllocBlockByValue(Value* value) { + auto it = value2AllocBlocks.find(value); + return it != value2AllocBlocks.end() ? it->second : nullptr; + } + + // 值定义/使用操作 + void addValue2DefBlocks(Value* value, BasicBlock* block) { ++value2DefBlocks[value][block]; } + void addValue2UseBlocks(Value* value, BasicBlock* block) { ++value2UseBlocks[value][block]; } + + // 间接分配操作 + void addIndirectAlloca(AllocaInst* alloca) { indirectAllocas.emplace_back(alloca); } + + // 清空所有分析信息 + void clear() { + attribute = PlaceHolder; + callees.clear(); + loops.clear(); + topLoops.clear(); + basicblock2Loop.clear(); + indirectAllocas.clear(); + value2AllocBlocks.clear(); + value2DefBlocks.clear(); + value2UseBlocks.clear(); + } +}; +// 循环类 - 未实现优化 +class Loop { +public: + using block_list = std::vector; + using block_set = std::unordered_set; + using Loop_list = std::vector; + +protected: + Function *parent; // 所属函数 + block_list blocksInLoop; // 循环内的基本块 + BasicBlock *preheaderBlock = nullptr; // 前驱块 + BasicBlock *headerBlock = nullptr; // 循环头 + block_list latchBlock; // 回边块 + block_set exitingBlocks; // 退出块 + block_set exitBlocks; // 退出目标块 + Loop *parentloop = nullptr; // 父循环 + Loop_list subLoops; // 子循环 + size_t loopID; // 循环ID + unsigned loopDepth; // 循环深度 + + Instruction *indCondVar = nullptr; // 循环条件变量 + Instruction::Kind IcmpKind; // 比较类型 + Value *indEnd = nullptr; // 循环结束值 + AllocaInst *IndPhi = nullptr; // 循环变量 + + ConstantValue *indBegin = nullptr; // 循环起始值 + ConstantValue *indStep = nullptr; // 循环步长 + + std::set GlobalValuechange; // 循环内改变的全局变量 + + int StepType = 0; // 循环步长类型 + bool parallelable = false; // 是否可并行 + +public: + explicit Loop(BasicBlock *header, const std::string &name = "") + : headerBlock(header) { + blocksInLoop.push_back(header); + } + + void setloopID() { + static unsigned loopCount = 0; + loopCount = loopCount + 1; + loopID = loopCount; + } + ConstantValue* getindBegin() { return indBegin; } + ConstantValue* getindStep() { return indStep; } + void setindBegin(ConstantValue *indBegin2set) { indBegin = indBegin2set; } + void setindStep(ConstantValue *indStep2set) { indStep = indStep2set; } + void setStepType(int StepType2Set) { StepType = StepType2Set; } + int getStepType() { return StepType; } + size_t getLoopID() { return loopID; } + + BasicBlock* getHeader() const { return headerBlock; } + BasicBlock* getPreheaderBlock() const { return preheaderBlock; } + block_list& getLatchBlocks() { return latchBlock; } + block_set& getExitingBlocks() { return exitingBlocks; } + block_set& getExitBlocks() { return exitBlocks; } + Loop* getParentLoop() const { return parentloop; } + void setParentLoop(Loop *parent) { parentloop = parent; } + void addBasicBlock(BasicBlock *bb) { blocksInLoop.push_back(bb); } + void addSubLoop(Loop *loop) { subLoops.push_back(loop); } + void setLoopDepth(unsigned depth) { loopDepth = depth; } + block_list& getBasicBlocks() { return blocksInLoop; } + Loop_list& getSubLoops() { return subLoops; } + unsigned getLoopDepth() const { return loopDepth; } + + bool isLoopContainsBasicBlock(BasicBlock *bb) const { + return std::find(blocksInLoop.begin(), blocksInLoop.end(), bb) != blocksInLoop.end(); + } + + void addExitingBlock(BasicBlock *bb) { exitingBlocks.insert(bb); } + void addExitBlock(BasicBlock *bb) { exitBlocks.insert(bb); } + void addLatchBlock(BasicBlock *bb) { latchBlock.push_back(bb); } + void setPreheaderBlock(BasicBlock *bb) { preheaderBlock = bb; } + + void setIndexCondInstr(Instruction *instr) { indCondVar = instr; } + void setIcmpKind(Instruction::Kind kind) { IcmpKind = kind; } + Instruction::Kind getIcmpKind() const { return IcmpKind; } + + bool isSimpleLoopInvariant(Value *value) ; + + void setIndEnd(Value *value) { indEnd = value; } + void setIndPhi(AllocaInst *phi) { IndPhi = phi; } + Value* getIndEnd() const { return indEnd; } + AllocaInst* getIndPhi() const { return IndPhi; } + Instruction* getIndCondVar() const { return indCondVar; } + + void addGlobalValuechange(GlobalValue *globalvaluechange2add) { + GlobalValuechange.insert(globalvaluechange2add); + } + std::set& getGlobalValuechange() { + return GlobalValuechange; + } + + void setParallelable(bool flag) { parallelable = flag; } + bool isParallelable() const { return parallelable; } +}; + +class ControlFlowAnalysis { +private: + Module *pModule; ///< 模块 + std::unordered_map blockAnalysisInfo; // 基本块分析信息 + std::unordered_map functionAnalysisInfo; // 函数分析信息 + +public: + explicit ControlFlowAnalysis(Module *pMoudle) : pModule(pMoudle) {} + + void init(); // 初始化分析器 + void computeDomNode(); // 计算必经结点 + void computeDomTree(); // 构造支配树 + // std::unordered_set computeDomFrontier(BasicBlock *block) ; // 计算单个块的支配边界(弃用) + void computeDomFrontierAllBlk(); // 计算所有块的支配边界 + void runControlFlowAnalysis(); // 运行控制流分析(主要是支配树和支配边界) + void clear(){ + for (auto &pair : blockAnalysisInfo) { + delete pair.second; // 清理基本块分析信息 + } + blockAnalysisInfo.clear(); + + for (auto &pair : functionAnalysisInfo) { + delete pair.second; // 清理函数分析信息 + } + functionAnalysisInfo.clear(); + } // 清空分析结果 + ~ControlFlowAnalysis() { + clear(); // 析构时清理所有分析信息 + } + +private: + void intersectOP4Dom(std::unordered_set &dom, const std::unordered_set &other); // 交集运算, + BasicBlock* findCommonDominator(BasicBlock *a, BasicBlock *b); // 查找两个基本块的共同支配结点 +}; + + +// 分析管理器(整合版) +class AnalysisManager { + +}; + + + + +} // namespace sysy \ No newline at end of file From ac7644f45074c85a09ae898a3fb2c097c7496ee4 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Tue, 24 Jun 2025 23:45:43 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=B5=81=E5=88=86=E6=9E=90=E7=B1=BB=EF=BC=8C=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E5=89=8D=E5=90=91=E5=90=8E=E5=90=91=E5=88=86=E6=9E=90=E7=9A=84?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E5=8A=A8=E4=BD=9C=EF=BC=8C=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E6=B4=BB=E8=B7=83=E5=8F=98=E9=87=8F=E5=88=86=E6=9E=90=EF=BC=8C?= =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E5=80=9F=E9=89=B4=E5=AD=A6=E9=95=BF=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=EF=BC=8C=E5=90=8E=E7=BB=AD=E5=8F=AF=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SysYIRAnalyser.cpp | 261 +++++++++++++++++++++++++++++++++++ src/include/SysYIRAnalyser.h | 106 +++++++++++++- 2 files changed, 366 insertions(+), 1 deletion(-) diff --git a/src/SysYIRAnalyser.cpp b/src/SysYIRAnalyser.cpp index f7c685d..9b78fb4 100644 --- a/src/SysYIRAnalyser.cpp +++ b/src/SysYIRAnalyser.cpp @@ -254,6 +254,267 @@ void ControlFlowAnalysis::computeDomFrontierAllBlk() { } } +// ========================== +// dataflow analysis utils +// ========================== + +// 先引用学长的代码 +// TODO: Worklist 增加逆后序遍历机制 +void DataFlowAnalysisUtils::forwardAnalyze(Module *pModule){ + std::map workAnalysis; + for (auto &dataflow : forwardAnalysisList) { + dataflow->init(pModule); + } + + for (const auto &function : pModule->getFunctions()) { + for (auto &dataflow : forwardAnalysisList) { + workAnalysis.emplace(dataflow, false); + } + while (!workAnalysis.empty()) { + for (const auto &block : function.second->getBasicBlocks()) { + for (auto &elem : workAnalysis) { + if (elem.first->analyze(pModule, block.get())) { + elem.second = true; + } + } + } + std::map tmp; + std::remove_copy_if(workAnalysis.begin(), workAnalysis.end(), std::inserter(tmp, tmp.end()), + [](const std::pair &elem) -> bool { return !elem.second; }); + workAnalysis.swap(tmp); + + for (auto &elem : workAnalysis) { + elem.second = false; + } + } + } +} + +void DataFlowAnalysisUtils::backwardAnalyze(Module *pModule) { + std::map workAnalysis; + for (auto &dataflow : backwardAnalysisList) { + dataflow->init(pModule); + } + + for (const auto &function : pModule->getFunctions()) { + for (auto &dataflow : backwardAnalysisList) { + workAnalysis.emplace(dataflow, false); + } + while (!workAnalysis.empty()) { + for (const auto &block : function.second->getBasicBlocks()) { + for (auto &elem : workAnalysis) { + if (elem.first->analyze(pModule, block.get())) { + elem.second = true; + } + } + } + std::map tmp; + std::remove_copy_if(workAnalysis.begin(), workAnalysis.end(), std::inserter(tmp, tmp.end()), + [](const std::pair &elem) -> bool { return !elem.second; }); + workAnalysis.swap(tmp); + + for (auto &elem : workAnalysis) { + elem.second = false; + } + } + } +} + + +std::set ActiveVarAnalysis::getUsedSet(Instruction *inst) { + using Kind = Instruction::Kind; + std::vector operands; + for (const auto &operand : inst->getOperands()) { + operands.emplace_back(dynamic_cast(operand->getValue())); + } + std::set result; + switch (inst->getKind()) { + // phi op + case Kind::kPhi: + case Kind::kCall: + result.insert(std::next(operands.begin()), operands.end()); + break; + case Kind::kCondBr: + result.insert(operands[0]); + break; + case Kind::kBr: + case Kind::kAlloca: + break; + // mem op + case Kind::kStore: + // StoreInst 的第一个操作数是被存储的值,第二个操作数是存储的变量 + // 后续的是可能的数组维度 + result.insert(operands[0]); + result.insert(operands.begin() + 2, operands.end()); + break; + case Kind::kLoad: + case Kind::kLa: { + auto variable = dynamic_cast(operands[0]); + auto global = dynamic_cast(operands[0]); + auto constArray = dynamic_cast(operands[0]); + if ((variable != nullptr && variable->getNumDims() == 0) || (global != nullptr && global->getNumDims() == 0) || + (constArray != nullptr && constArray->getNumDims() == 0)) { + result.insert(operands[0]); + } + result.insert(std::next(operands.begin()), operands.end()); + break; + } + case Kind::kGetSubArray: { + for (unsigned i = 2; i < operands.size(); i++) { + // 数组的维度信息 + result.insert(operands[i]); + } + break; + } + case Kind::kMemset: { + result.insert(std::next(operands.begin()), operands.end()); + break; + } + case Kind::kInvalid: + // Binary + case Kind::kAdd: + case Kind::kSub: + case Kind::kMul: + case Kind::kDiv: + case Kind::kRem: + case Kind::kICmpEQ: + case Kind::kICmpNE: + case Kind::kICmpLT: + case Kind::kICmpLE: + case Kind::kICmpGT: + case Kind::kICmpGE: + case Kind::kFAdd: + case Kind::kFSub: + case Kind::kFMul: + case Kind::kFDiv: + case Kind::kFCmpEQ: + case Kind::kFCmpNE: + case Kind::kFCmpLT: + case Kind::kFCmpLE: + case Kind::kFCmpGT: + case Kind::kFCmpGE: + case Kind::kAnd: + case Kind::kOr: + // Unary + case Kind::kNeg: + case Kind::kNot: + case Kind::kFNot: + case Kind::kFNeg: + case Kind::kFtoI: + case Kind::kItoF: + // terminator + case Kind::kReturn: + result.insert(operands.begin(), operands.end()); + break; + default: + assert(false); + break; + } + result.erase(nullptr); + return result; +} + +User * ActiveVarAnalysis::getDefine(Instruction *inst) { + User *result = nullptr; + if (inst->isStore()) { + StoreInst* store = dynamic_cast(inst); + auto operand = store->getPointer(); + AllocaInst* variable = dynamic_cast(operand); + GlobalValue* global = dynamic_cast(operand); + if ((variable != nullptr && variable->getNumDims() != 0) || (global != nullptr && global->getNumDims() != 0)) { + // 如果是数组变量或者全局变量,则不返回定义 + // TODO:兼容数组变量 + result = nullptr; + } else { + result = dynamic_cast(operand); + } + } else if (inst->isPhi()) { + result = dynamic_cast(inst->getOperand(0)); + } else if (inst->isBinary() || inst->isUnary() || inst->isCall() || + inst->isLoad() || inst->isLa()) { + result = dynamic_cast(inst); + } + return result; +} + +void ActiveVarAnalysis::init(Module *pModule) { + for (const auto &function : pModule->getFunctions()) { + for (const auto &block : function.second->getBasicBlocks()) { + activeTable.emplace(block.get(), std::vector>{}); + for (unsigned i = 0; i < block->getNumInstructions() + 1; i++) + activeTable.at(block.get()).emplace_back(); + } + } +} + +// 活跃变量分析公式 每个块内的分析动作供分析器调用 +bool ActiveVarAnalysis::analyze(Module *pModule, BasicBlock *block) { + bool changed = false; // 标记数据流结果是否有变化 + std::set activeSet{}; // 当前计算的活跃变量集合 + + // 步骤1: 计算基本块出口的活跃变量集 (OUT[B]) + // 公式: OUT[B] = ∪_{S ∈ succ(B)} IN[S] + for (const auto &succ : block->getSuccessors()) { + // 获取后继块入口的活跃变量集 (IN[S]) + auto succActiveSet = activeTable.at(succ).front(); + // 合并所有后继块的入口活跃变量 + activeSet.insert(succActiveSet.begin(), succActiveSet.end()); + } + + // 步骤2: 处理基本块出口处的活跃变量集 + const auto &instructions = block->getInstructions(); + const auto numInstructions = instructions.size(); + + // 获取旧的出口活跃变量集 (block出口对应索引numInstructions) + const auto &oldEndActiveSet = activeTable.at(block)[numInstructions]; + + // 检查出口活跃变量集是否有变化 + if (!std::equal(activeSet.begin(), activeSet.end(), + oldEndActiveSet.begin(), oldEndActiveSet.end())) + { + changed = true; // 标记变化 + activeTable.at(block)[numInstructions] = activeSet; // 更新出口活跃变量集 + } + + // 步骤3: 逆序遍历基本块中的指令 + // 从最后一条指令开始向前计算每个程序点的活跃变量 + auto instructionIter = instructions.end(); + instructionIter--; // 指向最后一条指令 + + // 从出口向入口遍历 (索引从numInstructions递减到1) + for (unsigned i = numInstructions; i > 0; i--) { + auto inst = instructionIter->get(); // 当前指令 + + auto used = getUsedSet(inst); + User *defined = getDefine(inst); + + // 步骤3.3: 计算指令入口的活跃变量 (IN[i]) + // 公式: IN[i] = use_i ∪ (OUT[i] - def_i) + activeSet.erase(defined); // 移除被定义的变量 (OUT[i] - def_i) + activeSet.insert(used.begin(), used.end()); // 添加使用的变量 + + // 获取旧的入口活跃变量集 (位置i-1对应当前指令的入口) + const auto &oldActiveSet = activeTable.at(block)[i - 1]; + + // 检查活跃变量集是否有变化 + if (!std::equal(activeSet.begin(), activeSet.end(), + oldActiveSet.begin(), oldActiveSet.end())) + { + changed = true; // 标记变化 + activeTable.at(block)[i - 1] = activeSet; // 更新入口活跃变量集 + } + + instructionIter--; // 移动到前一条指令 + } + + return changed; // 返回数据流结果是否变化 +} + + +auto ActiveVarAnalysis::getActiveTable() const -> const std::map>> & { + return activeTable; +} + } // namespace sysy diff --git a/src/include/SysYIRAnalyser.h b/src/include/SysYIRAnalyser.h index 2cb3f1f..7a13491 100644 --- a/src/include/SysYIRAnalyser.h +++ b/src/include/SysYIRAnalyser.h @@ -252,6 +252,7 @@ public: bool isParallelable() const { return parallelable; } }; +// 控制流分析类 class ControlFlowAnalysis { private: Module *pModule; ///< 模块 @@ -287,8 +288,111 @@ private: BasicBlock* findCommonDominator(BasicBlock *a, BasicBlock *b); // 查找两个基本块的共同支配结点 }; +// 数据流分析类 +// 该类为抽象类,具体的数据流分析器需要继承此类 +// 因为每个数据流分析器的分析动作都不一样,所以需要继承并实现analyze方法 +class DataFlowAnalysis { + public: + virtual ~DataFlowAnalysis() = default; -// 分析管理器(整合版) + public: + virtual void init(Module *pModule) {} ///< 分析器初始化 + virtual auto analyze(Module *pModule, BasicBlock *block) -> bool { return true; } ///< 分析动作,若完成则返回true; + virtual void clear() {} ///< 清空 +}; + +// 数据流分析工具类 +// 该类用于管理多个数据流分析器,提供统一的前向与后向分析接口 +class DataFlowAnalysisUtils { +private: + std::vector forwardAnalysisList; ///< 前向分析器列表 + std::vector backwardAnalysisList; ///< 后向分析器列表 + +public: + DataFlowAnalysisUtils() = default; + + // 统一构造 + DataFlowAnalysisUtils( + std::vector forwardList = {}, + std::vector backwardList = {}) + : forwardAnalysisList(std::move(forwardList)), + backwardAnalysisList(std::move(backwardList)) {} + + // 统一添加接口 + void addAnalyzers( + std::vector forwardList, + std::vector backwardList = {}) + { + forwardAnalysisList.insert( + forwardAnalysisList.end(), + forwardList.begin(), + forwardList.end()); + + backwardAnalysisList.insert( + backwardAnalysisList.end(), + backwardList.begin(), + backwardList.end()); + } + + // 单独添加接口 + void addForwardAnalyzer(DataFlowAnalysis *analyzer) { + forwardAnalysisList.push_back(analyzer); + } + + void addBackwardAnalyzer(DataFlowAnalysis *analyzer) { + backwardAnalysisList.push_back(analyzer); + } + + // 设置分析器列表 + void setAnalyzers( + std::vector forwardList, + std::vector backwardList) + { + forwardAnalysisList = std::move(forwardList); + backwardAnalysisList = std::move(backwardList); + } + + // 清空列表 + void clear() { + forwardAnalysisList.clear(); + backwardAnalysisList.clear(); + } + + // 访问器 + const auto& getForwardAnalyzers() const { return forwardAnalysisList; } + const auto& getBackwardAnalyzers() const { return backwardAnalysisList; } + +public: + void forwardAnalyze(Module *pModule); ///< 执行前向分析 + void backwardAnalyze(Module *pModule); ///< 执行后向分析 +}; + +// 活跃变量分析类 +// 提供def - use分析 +// 未兼容数组变量但是考虑了维度的use信息 +class ActiveVarAnalysis : public DataFlowAnalysis { + private: + std::map>> activeTable; ///< 活跃信息表,存储每个基本块内的的活跃变量信息 + + public: + ActiveVarAnalysis() = default; + ~ActiveVarAnalysis() override = default; + + public: + static std::set getUsedSet(Instruction *inst); + static User* getDefine(Instruction *inst); + + public: + void init(Module *pModule) override; + bool analyze(Module *pModule, BasicBlock *block) override; + // 外部活跃信息表访问器 + const std::map>> &getActiveTable() const; + void clear() override { + activeTable.clear(); // 清空活跃信息表 + } +}; + +// 分析管理器 class AnalysisManager { }; From bd0b624e8748e506e0fe8b5b0aaf904b7cc9e4f4 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Wed, 25 Jun 2025 02:22:16 +0800 Subject: [PATCH 03/10] debugging --- src/CMakeLists.txt | 2 + src/Mem2Reg.cpp | 661 +++++++++++++++++++++++++++++++++++ src/Reg2Mem.cpp | 0 src/SysYIRAnalyser.cpp | 3 +- src/include/Mem2Reg.h | 58 +++ src/include/Reg2Mem.h | 0 src/include/SysYIRAnalyser.h | 120 +++++-- src/sysyc.cpp | 4 + 8 files changed, 818 insertions(+), 30 deletions(-) create mode 100644 src/Reg2Mem.cpp create mode 100644 src/include/Reg2Mem.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f6f841a..1251e4f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,6 +18,8 @@ add_executable(sysyc # Backend.cpp SysYIRPrinter.cpp SysYIROptPre.cpp + SysYIRAnalyser.cpp + Mem2Reg.cpp RISCv32Backend.cpp ) target_include_directories(sysyc PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include) diff --git a/src/Mem2Reg.cpp b/src/Mem2Reg.cpp index e69de29..9e12948 100644 --- a/src/Mem2Reg.cpp +++ b/src/Mem2Reg.cpp @@ -0,0 +1,661 @@ +#include "Mem2Reg.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "IR.h" +#include "SysYIRAnalyser.h" +#include "SysYIRPrinter.h" + +namespace sysy { + +// 计算给定变量的定义块集合的迭代支配边界 +// TODO:优化Semi-Naive IDF +std::unordered_set Mem2Reg::computeIterDf(const std::unordered_set &blocks) { + std::unordered_set workList; + std::unordered_set ret_list; + workList.insert(blocks.begin(), blocks.end()); + + while (!workList.empty()) { + auto n = workList.begin(); + BlockAnalysisInfo* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(*n); + auto DFs = blockInfo->getDomFrontiers(); + for (auto c : DFs) { + // 如果c不在ret_list中,则将其加入ret_list和workList + // 这里的c是n的支配边界 + // 也就是n的支配边界中的块 + // 需要注意的是,支配边界是一个集合,所以可能会有重复 + if (ret_list.count(c) == 0U) { + ret_list.emplace(c); + workList.emplace(c); + } + } + workList.erase(n); + } + return ret_list; +} + +/** + * 计算value2Blocks的映射,包括value2AllocBlocks、value2DefBlocks以及value2UseBlocks + * 其中value2DefBlocks可用于计算迭代支配边界来插入相应变量的phi结点 + * 这里的value2AllocBlocks、value2DefBlocks和value2UseBlocks改变了函数级别的分析信息 + */ +auto Mem2Reg::computeValue2Blocks() -> void { + auto &functions = pModule->getFunctions(); + for (const auto &function : functions) { + auto func = function.second.get(); + auto basicBlocks = func->getBasicBlocks(); + FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func); + for (auto &it : basicBlocks) { + auto basicBlock = it.get(); + auto &instrs = basicBlock->getInstructions(); + for (auto &instr : instrs) { + // 如果指令本身就是alloca指令,则加到allocblocks中 + if (instr->isAlloca()) { + if (!(isArr(instr.get()) || isGlobal(instr.get()))) { + + funcInfo->addValue2AllocBlocks(instr.get(), basicBlock); + // func->addValue2AllocBlocks(instr.get(), basicBlock); + } + } else if (instr->isStore()) { + // 否则就看Store指令,找到operands里的alloc指令 + auto val = instr->getOperand(1); + if (!(isArr(val) || isGlobal(val))) { + funcInfo->addValue2DefBlocks(instr.get(), basicBlock); + // func->addValue2DefBlocks(val, basicBlock); + } + } else if (instr->isLoad()) { + // 如果是load指令,那么就是use,看operand(因为IR是reg-reg型,所以use只看load就行) + auto val = instr->getOperand(0); + if (!(isArr(val) || isGlobal(val))) { + funcInfo->addValue2UseBlocks(instr.get(), basicBlock); + // func->addValue2UseBlocks(val, basicBlock); + } + } + } + } + } +} + +/** + * @brief 级联关系的顺带消除,用于llvm mem2reg类预优化1 + * + * 采用队列进行模拟,从某种程度上来看其实可以看作是UD链的反向操作; + * + * @param [in] instr store指令使用的指令 + * @param [in] changed 不动点法的判断标准,地址传递 + * @param [in] func 指令所在函数 + * @param [in] block 指令所在基本块 + * @param [in] instrs 基本块所在指令集合,地址传递 + * @return 无返回值,但满足条件的情况下会对指令进行删除 + */ +auto Mem2Reg::cascade(Instruction *instr, bool &changed, Function *func, BasicBlock *block, + std::list> &instrs) -> void { + if (instr != nullptr) { + if (instr->isUnary() || instr->isBinary() || instr->isLoad()) { + std::queue toRemove; + toRemove.push(instr); + while (!toRemove.empty()) { + auto top = toRemove.front(); + toRemove.pop(); + auto operands = top->getOperands(); + for (const auto &operand : operands) { + auto elem = dynamic_cast(operand->getValue()); + if (elem != nullptr) { + if ((elem->isUnary() || elem->isBinary() || elem->isLoad()) && elem->getUses().size() == 1 && + elem->getUses().front()->getUser() == top) { + toRemove.push(elem); + } else if (elem->isAlloca()) { + // value2UseBlock中该block对应次数-1,如果该变量的该useblock中count减为0了,则意味着 + // 该block其他地方也没用到该alloc了,故从value2UseBlock中删除 + FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func); + auto res = funcInfo->removeValue2UseBlock(elem, block); + // 只要有一次返回了true,就说明有变化 + if (res) { + changed = true; + } + } + } + } + auto tofind = + std::find_if(instrs.begin(), instrs.end(), [&top](const auto &instr) { return instr.get() == top; }); + assert(tofind != instrs.end()); + usedelete(tofind->get()); + instrs.erase(tofind); + } + } + } +} + +/** + * @brief llvm mem2reg预优化1: 删除不含load的alloc和store + * + * 1. 删除不含load的alloc和store; + * 2. 删除store指令,之前的用于作store指令第0个操作数的那些级联指令就冗余了,也要删除; + * 3. 删除之后,可能有些变量的load使用恰好又没有了,因此再次从第一步开始循环,这里使用不动点法 + * + * @note 额外说明:由于删除了级联关系,所以这里的方法有点儿激进; + * 同时也考虑了级联关系时如果调用了函数,可能会有side effect,所以没有删除调用函数的级联关系; + * 而且关于函数参数的alloca不会在指令中删除,也不会在value2Alloca中删除; + * 同样地,我们不考虑数组和global,不过这里的代码是基于value2blocks的,在value2blocks中已经考虑了,所以不用显式指明 + * + * @param [in] void + * @return 无返回值,但满足条件的情况下会对指令进行删除 + */ +auto Mem2Reg::preOptimize1() -> void { + auto &functions = pModule->getFunctions(); + for (const auto &function : functions) { + auto func = function.second.get(); + FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func); + auto &vToDefB = funcInfo->getValue2DefBlocks(); + auto &vToUseB = funcInfo->getValue2UseBlocks(); + // 先删除孤零零的alloca,即没有store的alloca + auto &vToAllocB = funcInfo->getValue2AllocBlocks(); + for (auto iter = vToAllocB.begin(); iter != vToAllocB.end();) { + auto val = iter->first; + if (vToDefB.count(val) == 0U && + std::find(func->getEntryBlock()->getArguments().begin(), func->getEntryBlock()->getArguments().end(), val) == + func->getEntryBlock()->getArguments().end()) { + auto bb = iter->second; + auto tofind = std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(), + [val](const auto &instr) { return instr.get() == val; }); + usedelete(tofind->get()); + bb->getInstructions().erase(tofind); + iter = vToAllocB.erase(iter); + } else { + ++iter; + } + } + bool changed = true; + // 不动点法 + while (changed) { + changed = false; + for (auto iter = vToDefB.begin(); iter != vToDefB.end();) { + auto val = iter->first; + // 找到没有load的变量,删除关于该变量的store + if (vToUseB.count(val) == 0U) { + auto blocks = funcInfo->getDefBlocksByValue(val); + for (auto block : blocks) { + auto &instrs = block->getInstructions(); + for (auto it = instrs.begin(); it != instrs.end();) { + if (((*it)->isStore() && (*it)->getOperand(1) == val)) { + // 关于该变量的store指令删除了,那对于之前的用于作store指令第0个操作数的那些指令就冗余了,也要删除 + // 只考虑为指令,不考虑字面量和常数,因为它们与之前的指令无关了 + // 同时考虑指令的话,该指令可能又与前面的指令可能有较强的级联关系,级联之间又有级联,因此又要考虑前面指令的删除 + auto valUsedByStore = dynamic_cast((*it)->getOperand(0)); + usedelete(it->get()); + // if it is constantvalue which it not instruction + if (valUsedByStore != nullptr && valUsedByStore->getUses().size() == 1 && + valUsedByStore->getUses().front()->getUser() == (*it).get()) { + cascade(valUsedByStore, changed, func, block, instrs); + } + it = instrs.erase(it); + } else { + ++it; + } + } + } + // 再删除关于该变量的alloc(如果是函数参数的就不删除,函数参数的alloca在entry块的arguments内) + if (std::find(func->getEntryBlock()->getArguments().begin(), func->getEntryBlock()->getArguments().end(), + val) == func->getEntryBlock()->getArguments().end()) { + auto bb = funcInfo->getAllocBlockByValue(val); + if (bb != nullptr) { + funcInfo->removeValue2AllocBlock(val); + auto tofind = std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(), + [val](const auto &instr) { return instr.get() == val; }); + usedelete(tofind->get()); + bb->getInstructions().erase(tofind); + } + } + iter = vToDefB.erase(iter); + } else { + ++iter; + } + } + } + } +} + +/** + * @brief llvm mem2reg预优化2: 针对某个变量的Defblocks只有一个块的情况 + * + * 1. 该基本块最后一次对该变量的store指令后的所有对该变量的load指令都可以替换为该基本块最后一次store指令的第0个操作数; + * 2. 以该基本块为必经结点的结点集合中的对该变量的load指令都可以替换为该基本块最后一次对该变量的store指令的第0个操作数; + * 3. + * 如果对该变量的所有load均替换掉了,删除该基本块中最后一次store指令,如果这个store指令是唯一的define,那么再删除alloca指令(不删除参数的alloca); + * 4. + * 如果对该value的所有load都替换掉了,对于该变量剩下还有store的话,就转换成了preOptimize1的情况,再调用preOptimize1进行删除; + * + * @note 额外说明:同样有点儿激进; + * 同样不考虑数组和全局变量,因为这些变量不会被mem2reg优化,在value2blocks中已经考虑了,所以不用显式指明; + * 替换的操作采用了UD链进行简化和效率的提升 + * + * @param [in] void + * @return 无返回值,但满足条件的情况下会对指令的操作数进行替换以及对指令进行删除 + */ +auto Mem2Reg::preOptimize2() -> void { + auto &functions = pModule->getFunctions(); + for (const auto &function : functions) { + auto func = function.second.get(); + FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func); + auto values = funcInfo->getValuesOfDefBlock(); + for (auto val : values) { + auto blocks = funcInfo->getDefBlocksByValue(val); + // 该val只有一个defining block + if (blocks.size() == 1) { + auto block = *blocks.begin(); + auto &instrs = block->getInstructions(); + auto rit = std::find_if(instrs.rbegin(), instrs.rend(), + [val](const auto &instr) { return instr->isStore() && instr->getOperand(1) == val; }); + // 注意reverse_iterator求base后是指向下一个指令,因此要减一才是原来的指令 + assert(rit != instrs.rend()); + auto it = --rit.base(); + auto propogationVal = (*it)->getOperand(0); + // 其实该块中it后对该val的load指令也可以替换掉了 + for (auto curit = std::next(it); curit != instrs.end();) { + if ((*curit)->isLoad() && (*curit)->getOperand(0) == val) { + curit->get()->replaceAllUsesWith(propogationVal); + usedelete(curit->get()); + curit = instrs.erase(curit); + funcInfo->removeValue2UseBlock(val, block); + } else { + ++curit; + } + } + // 在支配树后继结点中替换load指令的操作数 + BlockAnalysisInfo* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(block); + std::vector blkchildren; + // 获取该块的支配树后继结点 + std::queue q; + auto sdoms = blockInfo->getSdoms(); + for (auto sdom : sdoms) { + q.push(sdom); + blkchildren.push_back(sdom); + } + while (!q.empty()) { + auto blk = q.front(); + q.pop(); + BlockAnalysisInfo* blkInfo = controlFlowAnalysis->getBlockAnalysisInfo(blk); + for (auto sdom : blkInfo->getSdoms()) { + q.push(sdom); + blkchildren.push_back(sdom); + } + } + for (auto child : blkchildren) { + auto &childInstrs = child->getInstructions(); + for (auto childIter = childInstrs.begin(); childIter != childInstrs.end();) { + if ((*childIter)->isLoad() && (*childIter)->getOperand(0) == val) { + childIter->get()->replaceAllUsesWith(propogationVal); + usedelete(childIter->get()); + childIter = childInstrs.erase(childIter); + funcInfo->removeValue2UseBlock(val, child); + } else { + ++childIter; + } + } + } + // 如果对该val的所有load均替换掉了,那么对于该val的defining block中的最后一个define也可以删除了 + // 同时该块中前面对于该val的define也变成死代码了,可调用preOptimize1进行删除 + if (funcInfo->getUseBlocksByValue(val).empty()) { + usedelete(it->get()); + instrs.erase(it); + auto change = funcInfo->removeValue2DefBlock(val, block); + if (change) { + // 如果define是唯一的,且不是函数参数的alloca,直接删alloca + if (std::find(func->getEntryBlock()->getArguments().begin(), func->getEntryBlock()->getArguments().end(), + val) == func->getEntryBlock()->getArguments().end()) { + auto bb = funcInfo->getAllocBlockByValue(val); + assert(bb != nullptr); + auto tofind = std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(), + [val](const auto &instr) { return instr.get() == val; }); + usedelete(tofind->get()); + bb->getInstructions().erase(tofind); + funcInfo->removeValue2AllocBlock(val); + } + } else { + // 如果该变量还有其他的define,那么前面的define也变成死代码了 + assert(!funcInfo->getDefBlocksByValue(val).empty()); + assert(funcInfo->getUseBlocksByValue(val).empty()); + preOptimize1(); + } + } + } + } + } +} + +/** + * @brief llvm mem2reg类预优化3:针对某个变量的所有读写都在同一个块中的情况 + * + * 1. 将每一个load替换成前一个store的值,并删除该load; + * 2. 如果在load前没有对该变量的store,则不删除该load; + * 3. 如果一个store后没有任何对改变量的load,则删除该store; + * + * @note 额外说明:第二点不用显式处理,因为我们的方法是从找到第一个store开始; + * 第三点其实可以更激进一步地理解,即每次替换了load之后,它对应地那个store也可以删除了,同时注意这里不要使用preoptimize1进行处理,因为他们的级联关系是有用的:即用来求load的替换值; + * 同样地,我们这里不考虑数组和全局变量,因为这些变量不会被mem2reg优化,不过这里在计算value2DefBlocks时已经跳过了,所以不需要再显式处理了; + * 替换的操作采用了UD链进行简化和效率的提升 + * + * @param [in] void + * @return 无返回值,但满足条件的情况下会对指令的操作数进行替换以及对指令进行删除 + */ +auto Mem2Reg::preOptimize3() -> void { + auto &functions = pModule->getFunctions(); + for (const auto &function : functions) { + auto func = function.second.get(); + FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func); + auto values = funcInfo->getValuesOfDefBlock(); + for (auto val : values) { + auto sblocks = funcInfo->getDefBlocksByValue(val); + auto lblocks = funcInfo->getUseBlocksByValue(val); + if (sblocks.size() == 1 && lblocks.size() == 1 && *sblocks.begin() == *lblocks.begin()) { + auto block = *sblocks.begin(); + auto &instrs = block->getInstructions(); + auto it = std::find_if(instrs.begin(), instrs.end(), + [val](const auto &instr) { return instr->isStore() && instr->getOperand(1) == val; }); + while (it != instrs.end()) { + auto propogationVal = (*it)->getOperand(0); + auto last = std::find_if(std::next(it), instrs.end(), [val](const auto &instr) { + return instr->isStore() && instr->getOperand(1) == val; + }); + for (auto curit = std::next(it); curit != last;) { + if ((*curit)->isLoad() && (*curit)->getOperand(0) == val) { + curit->get()->replaceAllUsesWith(propogationVal); + usedelete(curit->get()); + curit = instrs.erase(curit); + funcInfo->removeValue2UseBlock(val, block); + } else { + ++curit; + } + } + // 替换了load之后,它对应地那个store也可以删除了 + if (!(std::find_if(func->getEntryBlock()->getArguments().begin(), func->getEntryBlock()->getArguments().end(), + [val](const auto &instr) { return instr == val; }) != + func->getEntryBlock()->getArguments().end()) && + last == instrs.end()) { + usedelete(it->get()); + it = instrs.erase(it); + if (funcInfo->removeValue2DefBlock(val, block)) { + auto bb = funcInfo->getAllocBlockByValue(val); + if (bb != nullptr) { + auto tofind = std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(), + [val](const auto &instr) { return instr.get() == val; }); + usedelete(tofind->get()); + bb->getInstructions().erase(tofind); + funcInfo->removeValue2AllocBlock(val); + } + } + } + it = last; + } + } + } + } +} + +/** + * @brief 为所有变量的定义块集合的迭代支配边界插入phi结点(剪枝版) + * + * insertPhi是mem2reg的核心之一,这里是对所有变量的迭代支配边界的phi结点插入,无参数也无返回值; + * 同样跳过对数组和全局变量的处理,因为这些变量不会被mem2reg优化,刚好这里在计算value2DefBlocks时已经跳过了,所以不需要再显式处理了; + * 同时我们进行了剪枝处理,只有在基本块入口活跃的变量,才插入phi函数 + * + * @param [in] void + * @return 无返回值,但是会在每个变量的迭代支配边界上插入phi结点 + */ +auto Mem2Reg::insertPhi() -> void { + auto &functions = pModule->getFunctions(); + for (const auto &function : functions) { + auto func = function.second.get(); + FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func); + const auto &vToDefB = funcInfo->getValue2DefBlocks(); + for (const auto &map_pair : vToDefB) { + // 首先为每个变量找到迭代支配边界 + auto val = map_pair.first; + auto blocks = funcInfo->getDefBlocksByValue(val); + auto itDFs = computeIterDf(blocks); + // 然后在每个变量相应的迭代支配边界上插入phi结点 + for (auto basicBlock : itDFs) { + const auto &actiTable = activeVarAnalysis->getActiveTable(); + auto dval = dynamic_cast(val); + // 只有在基本块入口活跃的变量,才插入phi函数 + if (actiTable.at(basicBlock).front().count(dval) != 0U) { + pBuilder->createPhiInst(val->getType(), val, basicBlock); + } + } + } + } +} + +/** + * @brief 重命名 + * + * 重命名是mem2reg的核心之二,这里是对单个块的重命名,递归实现 + * 同样跳过对数组和全局变量的处理,因为这些变量不会被mem2reg优化 + * + * @param [in] block 一个基本块 + * @param [in] count 计数器,用于给变量重命名,地址传递 + * @param [in] stacks 用于存储变量的栈,地址传递 + * @return 无返回值 + */ +auto Mem2Reg::rename(BasicBlock *block, std::unordered_map &count, + std::unordered_map> &stacks) -> void { + auto &instrs = block->getInstructions(); + std::unordered_map valPop; + // 第一大步:对块中的所有指令遍历处理 + for (auto iter = instrs.begin(); iter != instrs.end();) { + auto instr = iter->get(); + // 对于load指令,变量用最新的那个 + if (instr->isLoad()) { + auto val = instr->getOperand(0); + if (!(isArr(val) || isGlobal(val))) { + if (!stacks[val].empty()) { + instr->replaceOperand(0, stacks[val].top()); + } + } + } + // 然后对于define的情况,看alloca、store和phi指令 + if (instr->isDefine()) { + if (instr->isAlloca()) { + // alloca指令名字不改了,命名就按x,x_1,x_2...来就行 + auto val = instr; + if (!(isArr(val) || isGlobal(val))) { + ++valPop[val]; + stacks[val].push(val); + ++count[val]; + } + } else if (instr->isPhi()) { + // Phi指令也是一条特殊的define指令 + auto val = dynamic_cast(instr)->getMapVal(); + if (!(isArr(val) || isGlobal(val))) { + auto i = count[val]; + if (i == 0) { + // 对还未alloca就有phi的指令的处理,直接删除 + usedelete(iter->get()); + iter = instrs.erase(iter); + continue; + } + auto newname = dynamic_cast(val)->getName() + "_" + std::to_string(i); + auto newalloca = pBuilder->createAllocaInstWithoutInsert(val->getType(), {}, block, newname); + FunctionAnalysisInfo* ParentfuncInfo = controlFlowAnalysis->getFunctionAnalysisInfo(block->getParent()); + ParentfuncInfo->addIndirectAlloca(newalloca); + instr->replaceOperand(0, newalloca); + ++valPop[val]; + stacks[val].push(newalloca); + ++count[val]; + } + } else { + // store指令看operand的名字,我们的实现是规定变量在operand的第二位,用一个新的alloca x_i代替 + auto val = instr->getOperand(1); + if (!(isArr(val) || isGlobal(val))) { + auto i = count[val]; + auto newname = dynamic_cast(val)->getName() + "_" + std::to_string(i); + auto newalloca = pBuilder->createAllocaInstWithoutInsert(val->getType(), {}, block, newname); + FunctionAnalysisInfo* ParentfuncInfo = controlFlowAnalysis->getFunctionAnalysisInfo(block->getParent()); + ParentfuncInfo->addIndirectAlloca(newalloca); + // block->getParent()->addIndirectAlloca(newalloca); + instr->replaceOperand(1, newalloca); + ++valPop[val]; + stacks[val].push(newalloca); + ++count[val]; + } + } + } + ++iter; + } + // 第二大步:把所有CFG中的该块的successor的phi指令的相应operand确定 + for (auto succ : block->getSuccessors()) { + auto position = getPredIndex(block, succ); + for (auto &instr : succ->getInstructions()) { + if (instr->isPhi()) { + auto val = dynamic_cast(instr.get())->getMapVal(); + if (!stacks[val].empty()) { + instr->replaceOperand(position + 1, stacks[val].top()); + } + } else { + // phi指令是添加在块的最前面的,因此过了之后就不会有phi了,直接break + break; + } + } + } + // 第三大步:递归支配树的后继,支配树才能表示define-use关系 + BlockAnalysisInfo* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(block); + for (auto sdom : blockInfo->getSdoms()) { + rename(sdom, count, stacks); + } + // 第四大步:遍历块中的所有指令,如果涉及到define,就弹栈,这一步是必要的,可以从递归的整体性来思考原因 + // 注意这里count没清理,因为平级之间计数仍然是一直增加的,但是stack要清理,因为define-use关系来自直接 + // 支配结点而不是平级之间,不清理栈会被污染 + // 提前优化:知道变量对应的要弹栈的次数就可以了,没必要遍历所有instr. + for (auto val_pair : valPop) { + auto val = val_pair.first; + for (int i = 0; i < val_pair.second; ++i) { + stacks[val].pop(); + } + } +} + +/** + * @brief 重命名所有块 + * + * 调用rename,自上而下实现所有rename + * + * @param [in] void + * @return 无返回值 + */ +auto Mem2Reg::renameAll() -> void { + auto &functions = pModule->getFunctions(); + for (const auto &function : functions) { + auto func = function.second.get(); + // 对于每个function都要SSA化,所以count和stacks定义在这并初始化 + std::unordered_map count; + std::unordered_map> stacks; + FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func); + for (const auto &map_pair : funcInfo->getValue2DefBlocks()) { + auto val = map_pair.first; + count[val] = 0; + } + rename(func->getEntryBlock(), count, stacks); + } +} + +/** + * @brief mem2reg,对外的接口 + * + * 静态单一赋值 + mem2reg等pass的逻辑组合 + * + * @param [in] void + * @return 无返回值 + */ +auto Mem2Reg::mem2regPipeline() -> void { + // 首先进行mem2reg的前置分析 + controlFlowAnalysis = new ControlFlowAnalysis(pModule); + activeVarAnalysis = new ActiveVarAnalysis(); + // 控制流分析 + controlFlowAnalysis->runControlFlowAnalysis(); + // 活跃变量分析 + dataFlowAnalysisUtils.addBackwardAnalyzer(activeVarAnalysis); + dataFlowAnalysisUtils.backwardAnalyze(pModule); + + // 计算所有valueToBlocks的定义映射 + computeValue2Blocks(); + SysYPrinter printer(pModule); + // 参考llvm的mem2reg遍,在插入phi结点之前,先做些优化 + preOptimize1(); + printer.printIR(); + preOptimize2(); + printer.printIR(); + // 优化三 可能会针对局部变量优化而删除整个块的alloca/store + preOptimize3(); + //再进行活跃变量分析 + // 报错? + + printer.printIR(); + dataFlowAnalysisUtils.backwardAnalyze(pModule); + // 为所有变量插入phi结点 + insertPhi(); + // 重命名 + renameAll(); +} + +/** + * @brief 计算块n是块s的第几个前驱 + * + * helperfunction,没有返回值,但是会将dom和other的交集赋值给dom + * + * @param [in] n 基本块,n是s的前驱之一 + * @param [in] s 基本块,s是n的后继之一 + * @return 返回n是s的第几个前驱 + */ +auto Mem2Reg::getPredIndex(BasicBlock *n, BasicBlock *s) -> int { + int index = 0; + for (auto elem : s->getPredecessors()) { + if (elem == n) { + break; + } + ++index; + } + assert(index < static_cast(s->getPredecessors().size()) && "n is not a predecessor of s."); + return index; +} + +/** + * @brief 判断一个value是不是全局变量 + * + * @param [in] val 一个value + * @return 返回true表示是全局变量,返回false表示不是 + */ +auto Mem2Reg::isGlobal(Value *val) -> bool { + auto gval = dynamic_cast(val); + return gval != nullptr; +} + +/** + * @brief 判断一个value是不是数组 + * + * @param [in] val 一个value + * @return 返回true表示是数组,返回false表示不是 + */ +auto Mem2Reg::isArr(Value *val) -> bool { + auto aval = dynamic_cast(val); + return aval != nullptr && aval->getNumDims() != 0; +} + +/** + * @brief 删除一个指令的operand对应的value的该条use + * + * @param [in] inst 一条指令 + * @return 无返回值 + */ +auto Mem2Reg::usedelete(Instruction *instr) -> void { + for (auto &use : instr->getOperands()) { + auto val = use->getValue(); + val->removeUse(use); + } +} +} // namespace sysy diff --git a/src/Reg2Mem.cpp b/src/Reg2Mem.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/SysYIRAnalyser.cpp b/src/SysYIRAnalyser.cpp index 9b78fb4..c0f304b 100644 --- a/src/SysYIRAnalyser.cpp +++ b/src/SysYIRAnalyser.cpp @@ -83,7 +83,7 @@ void ControlFlowAnalysis::computeDomNode(){ // 其中pred(B)是B的所有前驱结点 // 迭代计算支配结点,直到不再变化 // 这里使用迭代法,直到支配结点不再变化 - // TODO:Lengauer-Tarjan 算法可以更高效地计算支配结点 + // TODO:Lengauer-Tarjan 算法可以更高效地计算支配结点 // 或者按照CFG拓扑序遍历效率更高 bool changed = true; while (changed) { @@ -114,6 +114,7 @@ void ControlFlowAnalysis::computeDomNode(){ } } +// TODO: SEMI-NCA算法改进 void ControlFlowAnalysis::computeDomTree() { // 构造支配树 auto &functions = pModule->getFunctions(); diff --git a/src/include/Mem2Reg.h b/src/include/Mem2Reg.h index e69de29..f3b54ff 100644 --- a/src/include/Mem2Reg.h +++ b/src/include/Mem2Reg.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include +#include +#include +#include "IR.h" +#include "IRBuilder.h" +#include "SysYIRAnalyser.h" + +namespace sysy { +/** + * 实现静态单变量赋值核心类 mem2reg + */ +class Mem2Reg { +private: + Module *pModule; + IRBuilder *pBuilder; + ActiveVarAnalysis *activeVarAnalysis; // 活跃变量分析 + ControlFlowAnalysis *controlFlowAnalysis; // 控制流分析 + DataFlowAnalysisUtils dataFlowAnalysisUtils; + +public: + Mem2Reg(Module *pMoudle, IRBuilder *pBuilder) : + pModule(pMoudle), pBuilder(pBuilder), activeVarAnalysis(nullptr), controlFlowAnalysis(nullptr), dataFlowAnalysisUtils() + {} // 初始化函数 + + void mem2regPipeline(); ///< mem2reg + +private: + + // phi节点的插入需要计算IDF + std::unordered_set computeIterDf(const std::unordered_set &blocks); ///< 计算定义块集合的迭代支配边界 + + auto computeValue2Blocks() -> void; ///< 计算value2block的映射(不包括数组和global) + + auto preOptimize1() -> void; ///< llvm memtoreg预优化1: 删除不含load的alloc和store + auto preOptimize2() -> void; ///< llvm memtoreg预优化2: 针对某个变量的Defblocks只有一个块的情况 + auto preOptimize3() -> void; ///< llvm memtoreg预优化3: 针对某个变量的所有读写都在同一个块中的情况 + + auto insertPhi() -> void; ///< 为所有变量的迭代支配边界插入phi结点 + + auto rename(BasicBlock *block, std::unordered_map &count, + std::unordered_map> &stacks) -> void; ///< 单个块的重命名 + auto renameAll() -> void; ///< 重命名所有块 + + // private helper function. +private: + auto getPredIndex(BasicBlock *n, BasicBlock *s) -> int; ///< 获取前驱索引 + auto cascade(Instruction *instr, bool &changed, Function *func, BasicBlock *block, + std::list> &instrs) -> void; ///< 消除级联关系 + auto isGlobal(Value *val) -> bool; ///< 判断是否是全局变量 + auto isArr(Value *val) -> bool; ///< 判断是否是数组 + auto usedelete(Instruction *instr) -> void; ///< 删除指令相关的value-use-user关系 + +}; +} // namespace sysy diff --git a/src/include/Reg2Mem.h b/src/include/Reg2Mem.h new file mode 100644 index 0000000..e69de29 diff --git a/src/include/SysYIRAnalyser.h b/src/include/SysYIRAnalyser.h index 7a13491..45a7a06 100644 --- a/src/include/SysYIRAnalyser.h +++ b/src/include/SysYIRAnalyser.h @@ -55,7 +55,6 @@ public: dominant_frontiers = df; } - // TODO:循环分析操作方法 // 清空所有分析信息 @@ -113,34 +112,86 @@ public: void removeCallee(Function* callee) { callees.erase(callee); } void clearCallees() { callees.clear(); } - // 循环分析操作 - Loop* getLoopOfBasicBlock(BasicBlock* bb) { - auto it = basicblock2Loop.find(bb); - return it != basicblock2Loop.end() ? it->second : nullptr; - } - - void addBBToLoop(BasicBlock* bb, Loop* loop) { basicblock2Loop[bb] = loop; } - - unsigned getLoopDepthByBlock(BasicBlock* bb) { - Loop* loop = getLoopOfBasicBlock(bb); - return loop ? loop->getLoopDepth() : 0; - } // 值-块映射操作 - void addValue2AllocBlocks(Value* value, BasicBlock* block) { value2AllocBlocks[value] = block; } - BasicBlock* getAllocBlockByValue(Value* value) { auto it = value2AllocBlocks.find(value); return it != value2AllocBlocks.end() ? it->second : nullptr; } - + std::unordered_set getDefBlocksByValue(Value *value) { + std::unordered_set blocks; + if (value2DefBlocks.count(value) > 0) { + for (const auto &pair : value2DefBlocks[value]) { + blocks.insert(pair.first); + } + } + return blocks; + } + std::unordered_set getUseBlocksByValue(Value *value) { + std::unordered_set blocks; + if (value2UseBlocks.count(value) > 0) { + for (const auto &pair : value2UseBlocks[value]) { + blocks.insert(pair.first); + } + } + return blocks; + } + // 值定义/使用操作 + void addValue2AllocBlocks(Value* value, BasicBlock* block) { value2AllocBlocks[value] = block; } void addValue2DefBlocks(Value* value, BasicBlock* block) { ++value2DefBlocks[value][block]; } void addValue2UseBlocks(Value* value, BasicBlock* block) { ++value2UseBlocks[value][block]; } + + // 获取值定义/使用信息 + std::unordered_map& getValue2AllocBlocks() { + return value2AllocBlocks; + } + std::unordered_map>& getValue2DefBlocks() { + return value2DefBlocks; + } + std::unordered_map>& getValue2UseBlocks() { + return value2UseBlocks; + } + std::unordered_set getValuesOfDefBlock() { + std::unordered_set values; + for (const auto &pair : value2DefBlocks) { + values.insert(pair.first); + } + return values; + } + + // 删除信息操作 + void removeValue2AllocBlock(Value *value) { value2AllocBlocks.erase(value); } + bool removeValue2DefBlock(Value *value, BasicBlock *block) { + bool changed = false; + if (--value2DefBlocks[value][block] == 0) { + value2DefBlocks[value].erase(block); + if (value2DefBlocks[value].empty()) { + value2DefBlocks.erase(value); + changed = true; + } + } + return changed; + } + bool removeValue2UseBlock(Value *value, BasicBlock *block) { + bool changed = false; + if (--value2UseBlocks[value][block] == 0) { + value2UseBlocks[value].erase(block); + if (value2UseBlocks[value].empty()) { + value2UseBlocks.erase(value); + changed = true; + } + } + return changed; + } + // 间接分配操作 void addIndirectAlloca(AllocaInst* alloca) { indirectAllocas.emplace_back(alloca); } - + std::list>& getIndirectAllocas() { return indirectAllocas; } + + // TODO:循环分析操作 + // 清空所有分析信息 void clear() { attribute = PlaceHolder; @@ -256,12 +307,28 @@ public: class ControlFlowAnalysis { private: Module *pModule; ///< 模块 - std::unordered_map blockAnalysisInfo; // 基本块分析信息 + std::unordered_map blockAnalysisInfo; // 基本块分析信息表 std::unordered_map functionAnalysisInfo; // 函数分析信息 public: explicit ControlFlowAnalysis(Module *pMoudle) : pModule(pMoudle) {} + // 获取基本块分析信息 + BlockAnalysisInfo* getBlockAnalysisInfo(BasicBlock *block) { + auto it = blockAnalysisInfo.find(block); + if (it != blockAnalysisInfo.end()) { + return it->second; + } + return nullptr; // 如果未找到,返回nullptr + } + FunctionAnalysisInfo* getFunctionAnalysisInfo(Function *func) { + auto it = functionAnalysisInfo.find(func); + if (it != functionAnalysisInfo.end()) { + return it->second; + } + return nullptr; // 如果未找到,返回nullptr + } + void init(); // 初始化分析器 void computeDomNode(); // 计算必经结点 void computeDomTree(); // 构造支配树 @@ -310,14 +377,9 @@ private: public: DataFlowAnalysisUtils() = default; - - // 统一构造 - DataFlowAnalysisUtils( - std::vector forwardList = {}, - std::vector backwardList = {}) - : forwardAnalysisList(std::move(forwardList)), - backwardAnalysisList(std::move(backwardList)) {} - + ~DataFlowAnalysisUtils() { + clear(); // 析构时清理所有分析器 + } // 统一添加接口 void addAnalyzers( std::vector forwardList, @@ -392,10 +454,10 @@ class ActiveVarAnalysis : public DataFlowAnalysis { } }; -// 分析管理器 -class AnalysisManager { +// 分析管理器 后续实现 +// class AnalysisManager { -}; +// }; diff --git a/src/sysyc.cpp b/src/sysyc.cpp index 854ac53..f2f68a3 100644 --- a/src/sysyc.cpp +++ b/src/sysyc.cpp @@ -10,6 +10,8 @@ using namespace antlr4; #include "SysYIRGenerator.h" #include "SysYIRPrinter.h" #include "SysYIROptPre.h" +#include "SysYIRAnalyser.h" +#include "Mem2Reg.h" // #include "LLVMIRGenerator.h" using namespace sysy; @@ -83,6 +85,8 @@ int main(int argc, char **argv) { auto builder = generator.getBuilder(); SysYOptPre optPre(moduleIR, builder); optPre.SysYOptimizateAfterIR(); + Mem2Reg mem2reg(moduleIR, builder); + mem2reg.mem2regPipeline(); printer.printIR(); return EXIT_SUCCESS; } From 4fabcc9952f25a088a2e6703c68bcf102db6b508 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Wed, 25 Jun 2025 12:23:59 +0800 Subject: [PATCH 04/10] =?UTF-8?q?mem2reg=E6=B5=81=E7=A8=8B=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E8=B7=91=E9=80=9A=EF=BC=8C=E4=BF=AE=E5=A4=8Dphi?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E6=89=93=E5=8D=B0=EF=BC=8C=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E8=B0=83=E8=AF=95print?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Mem2Reg.cpp | 241 ++++++++++++++++++++++++++++++----- src/SysYIRGenerator.cpp | 2 +- src/SysYIRPrinter.cpp | 8 +- src/include/SysYIRAnalyser.h | 4 +- 4 files changed, 214 insertions(+), 41 deletions(-) diff --git a/src/Mem2Reg.cpp b/src/Mem2Reg.cpp index 9e12948..4991d96 100644 --- a/src/Mem2Reg.cpp +++ b/src/Mem2Reg.cpp @@ -46,42 +46,116 @@ std::unordered_set Mem2Reg::computeIterDf(const std::unordered_set * 这里的value2AllocBlocks、value2DefBlocks和value2UseBlocks改变了函数级别的分析信息 */ auto Mem2Reg::computeValue2Blocks() -> void { + SysYPrinter printer(pModule); // 初始化打印机 + std::cout << "===== Start computeValue2Blocks =====" << std::endl; + auto &functions = pModule->getFunctions(); for (const auto &function : functions) { auto func = function.second.get(); - auto basicBlocks = func->getBasicBlocks(); + std::cout << "\nProcessing function: " << func->getName() << std::endl; + FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func); + if (!funcInfo) { + std::cerr << "ERROR: No analysis info for function " << func->getName() << std::endl; + continue; + } + + auto basicBlocks = func->getBasicBlocks(); + std::cout << "BasicBlocks count: " << basicBlocks.size() << std::endl; + for (auto &it : basicBlocks) { auto basicBlock = it.get(); + std::cout << "\nProcessing BB: " << basicBlock->getName() << std::endl; + // printer.printBlock(basicBlock); // 打印基本块内容 + auto &instrs = basicBlock->getInstructions(); for (auto &instr : instrs) { - // 如果指令本身就是alloca指令,则加到allocblocks中 + std::cout << " Analyzing instruction: "; + printer.printInst(instr.get()); + std::cout << std::endl; + if (instr->isAlloca()) { if (!(isArr(instr.get()) || isGlobal(instr.get()))) { + std::cout << " Found alloca: "; + printer.printInst(instr.get()); + std::cout << " -> Adding to allocBlocks" << std::endl; funcInfo->addValue2AllocBlocks(instr.get(), basicBlock); - // func->addValue2AllocBlocks(instr.get(), basicBlock); + } else { + std::cout << " Skip array/global alloca: "; + printer.printInst(instr.get()); + std::cout << std::endl; } - } else if (instr->isStore()) { - // 否则就看Store指令,找到operands里的alloc指令 + } + else if (instr->isStore()) { auto val = instr->getOperand(1); + std::cout << " Store target: "; + printer.printInst(dynamic_cast(val)); + if (!(isArr(val) || isGlobal(val))) { - funcInfo->addValue2DefBlocks(instr.get(), basicBlock); - // func->addValue2DefBlocks(val, basicBlock); + std::cout << " Adding store to defBlocks for value: "; + printer.printInst(dynamic_cast(instr.get())); + std::cout << std::endl; + // 将store的目标值添加到defBlocks中 + funcInfo->addValue2DefBlocks(val, basicBlock); + } else { + std::cout << " Skip array/global store" << std::endl; } - } else if (instr->isLoad()) { - // 如果是load指令,那么就是use,看operand(因为IR是reg-reg型,所以use只看load就行) + } + else if (instr->isLoad()) { auto val = instr->getOperand(0); + std::cout << " Load source: "; + printer.printInst(dynamic_cast(val)); + std::cout << std::endl; + if (!(isArr(val) || isGlobal(val))) { - funcInfo->addValue2UseBlocks(instr.get(), basicBlock); - // func->addValue2UseBlocks(val, basicBlock); + std::cout << " Adding load to useBlocks for value: "; + printer.printInst(dynamic_cast(val)); + std::cout << std::endl; + + funcInfo->addValue2UseBlocks(val, basicBlock); + } else { + std::cout << " Skip array/global load" << std::endl; } } } } + + // 打印分析结果 + std::cout << "\nAnalysis results for function " << func->getName() << ":" << std::endl; + + auto &allocMap = funcInfo->getValue2AllocBlocks(); + std::cout << "AllocBlocks (" << allocMap.size() << "):" << std::endl; + for (auto &[val, bb] : allocMap) { + std::cout << " "; + printer.printInst(dynamic_cast(val)); + std::cout << " in BB: " << bb->getName() << std::endl; + } + + auto &defMap = funcInfo->getValue2DefBlocks(); + std::cout << "DefBlocks (" << defMap.size() << "):" << std::endl; + for (auto &[val, bbs] : defMap) { + std::cout << " "; + printer.printInst(dynamic_cast(val)); + for (const auto &[bb, count] : bbs) { + std::cout << " in BB: " << bb->getName() << " (count: " << count << ")"; + } + } + + auto &useMap = funcInfo->getValue2UseBlocks(); + std::cout << "UseBlocks (" << useMap.size() << "):" << std::endl; + for (auto &[val, bbs] : useMap) { + std::cout << " "; + printer.printInst(dynamic_cast(val)); + for (const auto &[bb, count] : bbs) { + std::cout << " in BB: " << bb->getName() << " (count: " << count << ")"; + } + } } + std::cout << "===== End computeValue2Blocks =====" << std::endl; } + /** * @brief 级联关系的顺带消除,用于llvm mem2reg类预优化1 * @@ -148,22 +222,80 @@ auto Mem2Reg::cascade(Instruction *instr, bool &changed, Function *func, BasicBl * @return 无返回值,但满足条件的情况下会对指令进行删除 */ auto Mem2Reg::preOptimize1() -> void { + SysYPrinter printer(pModule); // 初始化打印机 + auto &functions = pModule->getFunctions(); + std::cout << "===== Start preOptimize1 =====" << std::endl; + for (const auto &function : functions) { auto func = function.second.get(); + std::cout << "\nProcessing function: " << func->getName() << std::endl; + FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func); + if (!funcInfo) { + std::cerr << "ERROR: No analysis info for function " << func->getName() << std::endl; + continue; + } + auto &vToDefB = funcInfo->getValue2DefBlocks(); auto &vToUseB = funcInfo->getValue2UseBlocks(); - // 先删除孤零零的alloca,即没有store的alloca auto &vToAllocB = funcInfo->getValue2AllocBlocks(); + + // 打印初始状态 + std::cout << "Initial allocas: " << vToAllocB.size() << std::endl; + for (auto &[val, bb] : vToAllocB) { + std::cout << " Alloca: "; + printer.printInst(dynamic_cast(val)); + std::cout << " in BB: " << bb->getName() << std::endl; + } + + // 阶段1:删除无store的alloca + std::cout << "\nPhase 1: Remove unused allocas" << std::endl; for (auto iter = vToAllocB.begin(); iter != vToAllocB.end();) { auto val = iter->first; + auto bb = iter->second; + + std::cout << "Checking alloca: "; + printer.printInst(dynamic_cast(val)); + std::cout << " in BB: " << bb->getName() << std::endl; + + // 如果该alloca没有对应的store指令,且不在函数参数中 + // 这里的vToDefB是value2DefBlocks,vToUseB是value2UseBlocks + + // 打印vToDefB + std::cout << "DefBlocks (" << vToDefB.size() << "):" << std::endl; + for (auto &[val, bbs] : vToDefB) { + std::cout << " "; + printer.printInst(dynamic_cast(val)); + for (const auto &[bb, count] : bbs) { + std::cout << " in BB: " << bb->getName() << " (count: " << count << ")" << std::endl; + } + } + std::cout << vToDefB.count(val) << std::endl; + bool hasStore = false; + + + if (vToDefB.count(val) == 0U && - std::find(func->getEntryBlock()->getArguments().begin(), func->getEntryBlock()->getArguments().end(), val) == - func->getEntryBlock()->getArguments().end()) { - auto bb = iter->second; - auto tofind = std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(), - [val](const auto &instr) { return instr.get() == val; }); + std::find(func->getEntryBlock()->getArguments().begin(), + func->getEntryBlock()->getArguments().end(), + val) == func->getEntryBlock()->getArguments().end()) { + + std::cout << " Removing unused alloca: "; + printer.printInst(dynamic_cast(val)); + std::cout << std::endl; + + auto tofind = std::find_if(bb->getInstructions().begin(), + bb->getInstructions().end(), + [val](const auto &instr) { + return instr.get() == val; + }); + if (tofind == bb->getInstructions().end()) { + std::cerr << "ERROR: Alloca not found in BB!" << std::endl; + ++iter; + continue; + } + usedelete(tofind->get()); bb->getInstructions().erase(tofind); iter = vToAllocB.erase(iter); @@ -171,45 +303,83 @@ auto Mem2Reg::preOptimize1() -> void { ++iter; } } + + // 阶段2:删除无load的store + std::cout << "\nPhase 2: Remove dead stores" << std::endl; bool changed = true; - // 不动点法 + int iteration = 0; + while (changed) { changed = false; + iteration++; + std::cout << "\nIteration " << iteration << std::endl; + for (auto iter = vToDefB.begin(); iter != vToDefB.end();) { auto val = iter->first; - // 找到没有load的变量,删除关于该变量的store + + std::cout << "Checking value: "; + printer.printInst(dynamic_cast(val)); + std::cout << std::endl; + if (vToUseB.count(val) == 0U) { + std::cout << " Found dead store for value: "; + printer.printInst(dynamic_cast(val)); + std::cout << std::endl; + auto blocks = funcInfo->getDefBlocksByValue(val); for (auto block : blocks) { + std::cout << " Processing BB: " << block->getName() << std::endl; + // printer.printBlock(block); // 打印基本块内容 + auto &instrs = block->getInstructions(); for (auto it = instrs.begin(); it != instrs.end();) { - if (((*it)->isStore() && (*it)->getOperand(1) == val)) { - // 关于该变量的store指令删除了,那对于之前的用于作store指令第0个操作数的那些指令就冗余了,也要删除 - // 只考虑为指令,不考虑字面量和常数,因为它们与之前的指令无关了 - // 同时考虑指令的话,该指令可能又与前面的指令可能有较强的级联关系,级联之间又有级联,因此又要考虑前面指令的删除 + if ((*it)->isStore() && (*it)->getOperand(1) == val) { + std::cout << " Removing store: "; + printer.printInst(it->get()); + std::cout << std::endl; + auto valUsedByStore = dynamic_cast((*it)->getOperand(0)); usedelete(it->get()); - // if it is constantvalue which it not instruction - if (valUsedByStore != nullptr && valUsedByStore->getUses().size() == 1 && + + if (valUsedByStore != nullptr && + valUsedByStore->getUses().size() == 1 && valUsedByStore->getUses().front()->getUser() == (*it).get()) { + std::cout << " Cascade deleting: "; + printer.printInst(valUsedByStore); + std::cout << std::endl; + cascade(valUsedByStore, changed, func, block, instrs); } it = instrs.erase(it); + changed = true; } else { ++it; } } } - // 再删除关于该变量的alloc(如果是函数参数的就不删除,函数参数的alloca在entry块的arguments内) - if (std::find(func->getEntryBlock()->getArguments().begin(), func->getEntryBlock()->getArguments().end(), + + // 删除对应的alloca + if (std::find(func->getEntryBlock()->getArguments().begin(), + func->getEntryBlock()->getArguments().end(), val) == func->getEntryBlock()->getArguments().end()) { auto bb = funcInfo->getAllocBlockByValue(val); if (bb != nullptr) { + std::cout << " Removing alloca: "; + printer.printInst(dynamic_cast(val)); + std::cout << " in BB: " << bb->getName() << std::endl; + funcInfo->removeValue2AllocBlock(val); - auto tofind = std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(), - [val](const auto &instr) { return instr.get() == val; }); - usedelete(tofind->get()); - bb->getInstructions().erase(tofind); + auto tofind = std::find_if(bb->getInstructions().begin(), + bb->getInstructions().end(), + [val](const auto &instr) { + return instr.get() == val; + }); + if (tofind != bb->getInstructions().end()) { + usedelete(tofind->get()); + bb->getInstructions().erase(tofind); + } else { + std::cerr << "ERROR: Alloca not found in BB!" << std::endl; + } } } iter = vToDefB.erase(iter); @@ -219,6 +389,7 @@ auto Mem2Reg::preOptimize1() -> void { } } } + std::cout << "===== End preOptimize1 =====" << std::endl; } /** @@ -584,18 +755,18 @@ auto Mem2Reg::mem2regPipeline() -> void { // 计算所有valueToBlocks的定义映射 computeValue2Blocks(); - SysYPrinter printer(pModule); + // SysYPrinter printer(pModule); // 参考llvm的mem2reg遍,在插入phi结点之前,先做些优化 preOptimize1(); - printer.printIR(); + // printer.printIR(); preOptimize2(); - printer.printIR(); + // printer.printIR(); // 优化三 可能会针对局部变量优化而删除整个块的alloca/store preOptimize3(); //再进行活跃变量分析 // 报错? - printer.printIR(); + // printer.printIR(); dataFlowAnalysisUtils.backwardAnalyze(pModule); // 为所有变量插入phi结点 insertPhi(); diff --git a/src/SysYIRGenerator.cpp b/src/SysYIRGenerator.cpp index 912930e..653554a 100644 --- a/src/SysYIRGenerator.cpp +++ b/src/SysYIRGenerator.cpp @@ -264,7 +264,7 @@ std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) { dims.push_back(std::any_cast(visitExp(exp))); } - User* variable = module->getVariable(name); + auto variable = module->getVariable(name); Value* value = std::any_cast(visitExp(ctx->exp())); Type* variableType = dynamic_cast(variable->getType())->getBaseType(); diff --git a/src/SysYIRPrinter.cpp b/src/SysYIRPrinter.cpp index 04be4da..a27faf0 100644 --- a/src/SysYIRPrinter.cpp +++ b/src/SysYIRPrinter.cpp @@ -438,14 +438,16 @@ void SysYPrinter::printInst(Instruction *pInst) { case Kind::kPhi: { auto phiInst = dynamic_cast(pInst); - std::cout << "%" << phiInst->getName() << " = phi "; + std::cout << "%"; + printValue(phiInst->getOperand(0)); + std::cout << " = phi "; printType(phiInst->getType()); - for (unsigned i = 0; i < phiInst->getNumOperands(); i += 2) { + for (unsigned i = 1; i < phiInst->getNumOperands(); i++) { if (i > 0) std::cout << ", "; std::cout << "[ "; printValue(phiInst->getOperand(i)); - std::cout << ", %" << dynamic_cast(phiInst->getOperand(i+1))->getName() << " ]"; + std::cout << " ]"; } std::cout << std::endl; } break; diff --git a/src/include/SysYIRAnalyser.h b/src/include/SysYIRAnalyser.h index 45a7a06..1837b99 100644 --- a/src/include/SysYIRAnalyser.h +++ b/src/include/SysYIRAnalyser.h @@ -94,7 +94,7 @@ public: std::set callees; ///< 函数调用集合 Loop_list loops; ///< 所有循环 Loop_list topLoops; ///< 顶层循环 - block_loop_map basicblock2Loop; ///< 基本块到循环映射 + // block_loop_map basicblock2Loop; ///< 基本块到循环映射 std::list> indirectAllocas; ///< 间接分配内存 // 值定义/使用信息 @@ -198,7 +198,7 @@ public: callees.clear(); loops.clear(); topLoops.clear(); - basicblock2Loop.clear(); + // basicblock2Loop.clear(); indirectAllocas.clear(); value2AllocBlocks.clear(); value2DefBlocks.clear(); From e6c4e919567ba9cca7d47f2c395050e0fdccf45e Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Wed, 25 Jun 2025 12:27:02 +0800 Subject: [PATCH 05/10] fix % repeat --- src/SysYIRPrinter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SysYIRPrinter.cpp b/src/SysYIRPrinter.cpp index a27faf0..ae5a3e8 100644 --- a/src/SysYIRPrinter.cpp +++ b/src/SysYIRPrinter.cpp @@ -438,7 +438,6 @@ void SysYPrinter::printInst(Instruction *pInst) { case Kind::kPhi: { auto phiInst = dynamic_cast(pInst); - std::cout << "%"; printValue(phiInst->getOperand(0)); std::cout << " = phi "; printType(phiInst->getType()); From 3dc7c274cfe4218fd9e8f1dc7b2e0af2d14958e3 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Wed, 25 Jun 2025 12:42:28 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=94=AF=E9=85=8D?= =?UTF-8?q?=E6=A0=91=E7=94=9F=E6=88=90=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SysYIRAnalyser.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/SysYIRAnalyser.cpp b/src/SysYIRAnalyser.cpp index c0f304b..0761c0a 100644 --- a/src/SysYIRAnalyser.cpp +++ b/src/SysYIRAnalyser.cpp @@ -1,4 +1,5 @@ #include "SysYIRAnalyser.h" +#include namespace sysy { @@ -47,8 +48,14 @@ auto ControlFlowAnalysis::findCommonDominator(BasicBlock *a, BasicBlock *b) -> B BlockAnalysisInfo* infoB = blockAnalysisInfo[b]; // 如果深度不同,则向上移动到直接支配结点 // TODO:空间换时间倍增优化,优先级较低 - while (infoA->getDomDepth() > infoB->getDomDepth()) a = const_cast(infoA->getIdom()); - while (infoB->getDomDepth() > infoA->getDomDepth()) b = const_cast(infoB->getIdom()); + while (infoA->getDomDepth() > infoB->getDomDepth()) { + a = const_cast(infoA->getIdom()); + infoA = blockAnalysisInfo[a]; + } + while (infoB->getDomDepth() > infoA->getDomDepth()) { + b = const_cast(infoB->getIdom()); + infoB = blockAnalysisInfo[b]; + } if (a == b) break; a = const_cast(infoA->getIdom()); b = const_cast(infoB->getIdom()); @@ -137,11 +144,11 @@ void ControlFlowAnalysis::computeDomTree() { for (auto pred : basicBlock->getPredecessors()) { // 跳过未处理的前驱 if (blockAnalysisInfo[pred]->getIdom() == nullptr) continue; - new_idom = (new_idom == nullptr) ? pred : findCommonDominator(new_idom, pred); - // if (new_idom == nullptr) - // new_idom = pred; - // else - // new_idom = findCommonDominator(new_idom, pred); + // new_idom = (new_idom == nullptr) ? pred : findCommonDominator(new_idom, pred); + if (new_idom == nullptr) + new_idom = pred; + else + new_idom = findCommonDominator(new_idom, pred); } // 更新直接支配节点 if (new_idom && new_idom != blockAnalysisInfo[basicBlock.get()]->getIdom()) { @@ -150,6 +157,10 @@ void ControlFlowAnalysis::computeDomTree() { blockAnalysisInfo[const_cast(blockAnalysisInfo[basicBlock.get()]->getIdom())]->removeSdoms(basicBlock.get()); } // 设置新的支配关系 + + // std::cout << "Block: " << basicBlock->getName() + // << " New Idom: " << new_idom->getName() << std::endl; + blockAnalysisInfo[basicBlock.get()]->setIdom(new_idom); blockAnalysisInfo[new_idom]->addSdoms(basicBlock.get()); // 更新深度 = 直接支配节点深度 + 1 From 050113d31da3c05e38c1bf7235ba800a61939561 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Wed, 25 Jun 2025 13:17:16 +0800 Subject: [PATCH 07/10] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Reg2Mem,=E4=BD=86?= =?UTF-8?q?=E6=98=AF=E4=BC=9A=E7=94=9F=E6=88=90=E6=AD=BB=E5=AD=98=E5=82=A8?= =?UTF-8?q?=E6=8C=87=E4=BB=A4=EF=BC=8C=E9=9C=80=E8=A6=81=E6=AD=BB=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=88=A0=E9=99=A4=E6=94=AF=E6=8C=81=E8=AF=86=E5=88=AB?= =?UTF-8?q?=E6=AD=BB=E5=AD=98=E5=82=A8=E6=8C=87=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CMakeLists.txt | 1 + src/Mem2Reg.cpp | 17 ++---- src/Reg2Mem.cpp | 129 ++++++++++++++++++++++++++++++++++++++++++ src/include/Reg2Mem.h | 23 ++++++++ src/sysyc.cpp | 4 ++ 5 files changed, 161 insertions(+), 13 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1251e4f..b1a2f00 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,6 +20,7 @@ add_executable(sysyc SysYIROptPre.cpp SysYIRAnalyser.cpp Mem2Reg.cpp + Reg2Mem.cpp RISCv32Backend.cpp ) target_include_directories(sysyc PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include) diff --git a/src/Mem2Reg.cpp b/src/Mem2Reg.cpp index 4991d96..968e4f3 100644 --- a/src/Mem2Reg.cpp +++ b/src/Mem2Reg.cpp @@ -570,7 +570,7 @@ auto Mem2Reg::preOptimize3() -> void { } /** - * @brief 为所有变量的定义块集合的迭代支配边界插入phi结点(剪枝版) + * @brief 为所有变量的定义块集合的迭代支配边界插入phi结点 * * insertPhi是mem2reg的核心之一,这里是对所有变量的迭代支配边界的phi结点插入,无参数也无返回值; * 同样跳过对数组和全局变量的处理,因为这些变量不会被mem2reg优化,刚好这里在计算value2DefBlocks时已经跳过了,所以不需要再显式处理了; @@ -796,10 +796,7 @@ auto Mem2Reg::getPredIndex(BasicBlock *n, BasicBlock *s) -> int { } /** - * @brief 判断一个value是不是全局变量 - * - * @param [in] val 一个value - * @return 返回true表示是全局变量,返回false表示不是 + * 判断一个value是不是全局变量 */ auto Mem2Reg::isGlobal(Value *val) -> bool { auto gval = dynamic_cast(val); @@ -807,10 +804,7 @@ auto Mem2Reg::isGlobal(Value *val) -> bool { } /** - * @brief 判断一个value是不是数组 - * - * @param [in] val 一个value - * @return 返回true表示是数组,返回false表示不是 + * 判断一个value是不是数组 */ auto Mem2Reg::isArr(Value *val) -> bool { auto aval = dynamic_cast(val); @@ -818,10 +812,7 @@ auto Mem2Reg::isArr(Value *val) -> bool { } /** - * @brief 删除一个指令的operand对应的value的该条use - * - * @param [in] inst 一条指令 - * @return 无返回值 + * 删除一个指令的operand对应的value的该条use */ auto Mem2Reg::usedelete(Instruction *instr) -> void { for (auto &use : instr->getOperands()) { diff --git a/src/Reg2Mem.cpp b/src/Reg2Mem.cpp index e69de29..d44d1c8 100644 --- a/src/Reg2Mem.cpp +++ b/src/Reg2Mem.cpp @@ -0,0 +1,129 @@ +#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(); + 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; + } + } + } + } +} + +void Reg2Mem::usedelete(Instruction *instr) { + for (auto &use : instr->getOperands()) { + auto val = use->getValue(); + val->removeUse(use); + } +} + +} // namespace sysy diff --git a/src/include/Reg2Mem.h b/src/include/Reg2Mem.h index e69de29..6249d71 100644 --- a/src/include/Reg2Mem.h +++ b/src/include/Reg2Mem.h @@ -0,0 +1,23 @@ +#pragma once + +#include "IR.h" +#include "IRBuilder.h" + +namespace sysy { +/** + * Reg2Mem(后端未做phi指令翻译) + */ +class Reg2Mem { +private: + Module *pModule; + IRBuilder *pBuilder; + +public: + Reg2Mem(Module *pMoudle, IRBuilder *pBuilder) : pModule(pMoudle), pBuilder(pBuilder) {} + + void DeletePhiInst(); + // 删除UD关系, 因为删除了phi指令会修改ud关系 + void usedelete(Instruction *instr); +}; + +} // namespace sysy \ No newline at end of file diff --git a/src/sysyc.cpp b/src/sysyc.cpp index f2f68a3..acb553e 100644 --- a/src/sysyc.cpp +++ b/src/sysyc.cpp @@ -12,6 +12,7 @@ using namespace antlr4; #include "SysYIROptPre.h" #include "SysYIRAnalyser.h" #include "Mem2Reg.h" +#include "Reg2Mem.h" // #include "LLVMIRGenerator.h" using namespace sysy; @@ -88,6 +89,9 @@ int main(int argc, char **argv) { Mem2Reg mem2reg(moduleIR, builder); mem2reg.mem2regPipeline(); printer.printIR(); + Reg2Mem reg2mem(moduleIR, builder); + reg2mem.DeletePhiInst(); + printer.printIR(); return EXIT_SUCCESS; } return EXIT_SUCCESS; From 1e06c5a446818530485cd573ea62cf0d00af807e Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Wed, 25 Jun 2025 14:00:27 +0800 Subject: [PATCH 08/10] debugging --- src/DeadCodeElimination.cpp | 182 ++++++++++++++++++++++++++++++ src/include/DeadCodeElimination.h | 30 +++++ 2 files changed, 212 insertions(+) create mode 100644 src/DeadCodeElimination.cpp create mode 100644 src/include/DeadCodeElimination.h diff --git a/src/DeadCodeElimination.cpp b/src/DeadCodeElimination.cpp new file mode 100644 index 0000000..80b0022 --- /dev/null +++ b/src/DeadCodeElimination.cpp @@ -0,0 +1,182 @@ +#include "DeadCodeElimination.h" + +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); + } + } +} + +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 (isGlobal(pointer) || + (isArr(pointer) && + std::find(func->getEntryBlock()->getArguments().begin(), + func->getEntryBlock()->getArguments().end(), + pointer) != func->getEntryBlock()->getArguments().end())) { + ++iter; + continue; + } + + bool tag = true; + for (auto& use : pointer->getUses()) { + auto user = use->getUser(); + auto userInst = dynamic_cast(user); + if (userInst != nullptr && !userInst->isAlloca() && !userInst->isStore()) { + tag = false; + break; + } + } + + if (tag) { + changed = true; + usedelete(storeInst); + iter = instrs.erase(iter); + } else { + ++iter; + } + } + } +} + +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; + usedelete(inst); + iter = instrs.erase(iter); + continue; + } + } + ++iter; + } + } +} + +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; + usedelete(inst); + iter = instrs.erase(iter); + continue; + } + } + ++iter; + } + } + + // for (auto it = func->getIndirectAllocas().begin(); it != func->getIndirectAllocas().end();) { + // auto& allocaInst = *it; + // if (allocaInst->getUses().empty()) { + // changed = true; + // it = func->getIndirectAllocas().erase(it); + // } else { + // ++it; + // } + // } +} + +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; + it = globals.erase(it); + } else { + ++it; + } + } +} + +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; + } + } + if (tag) { + changed = true; + usedelete(inst); + iter = instrs.erase(iter); + continue; + } + } else if (inst->isMemset()) { + auto memsetInst = dynamic_cast(inst); + auto pointer = memsetInst->getPointer(); + if (pointer->getUses().empty()) { + changed = true; + usedelete(inst); + iter = instrs.erase(iter); + continue; + } + } + ++iter; + } + } +} + + +bool DeadCodeElimination::isGlobal(Value *val){ + auto gval = dynamic_cast(val); + return gval != nullptr; +} + +bool DeadCodeElimination::isArr(Value *val){ + auto aval = dynamic_cast(val); + return aval != nullptr && aval->getNumDims() != 0; +} + +void DeadCodeElimination::usedelete(Instruction *instr){ + for (auto &use1 : instr->getOperands()) { + auto val1 = use1->getValue(); + val1->removeUse(use1); + } +} + +} // namespace sysy \ No newline at end of file diff --git a/src/include/DeadCodeElimination.h b/src/include/DeadCodeElimination.h new file mode 100644 index 0000000..5b127a1 --- /dev/null +++ b/src/include/DeadCodeElimination.h @@ -0,0 +1,30 @@ +#pragma once + +#include "IR.h" + +namespace sysy { + +class DeadCodeElimination { + private: + Module *pModule; + + public: + explicit DeadCodeElimination(Module *pMoudle) : pModule(pMoudle) {} // 初始化函数 + + // 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 eliminateDeadRedundantLoadStore(Function* func, bool& changed); // 消除冗余加载和存储 + bool isGlobal(Value *val); + bool isArr(Value *val); + void usedelete(Instruction *instr); + +}; +} // namespace sysy From b12732f10dcbdd528d6909484537fc6f8cc85237 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Wed, 25 Jun 2025 15:30:28 +0800 Subject: [PATCH 09/10] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=88=86=E6=9E=90?= =?UTF-8?q?=E5=99=A8=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BF=9D=E8=AF=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E9=81=8D=E5=85=B1=E4=BA=AB=E4=B8=80=E4=B8=AA=E5=88=86?= =?UTF-8?q?=E6=9E=90=E5=99=A8=EF=BC=88=E4=B8=BB=E8=A6=81=E6=98=AF=E5=9C=A8?= =?UTF-8?q?mem2reg=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Mem2Reg.cpp | 5 ++--- src/include/Mem2Reg.h | 7 ++++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Mem2Reg.cpp b/src/Mem2Reg.cpp index 968e4f3..bf7e541 100644 --- a/src/Mem2Reg.cpp +++ b/src/Mem2Reg.cpp @@ -745,11 +745,10 @@ auto Mem2Reg::renameAll() -> void { */ auto Mem2Reg::mem2regPipeline() -> void { // 首先进行mem2reg的前置分析 - controlFlowAnalysis = new ControlFlowAnalysis(pModule); - activeVarAnalysis = new ActiveVarAnalysis(); - // 控制流分析 + controlFlowAnalysis->clear(); controlFlowAnalysis->runControlFlowAnalysis(); // 活跃变量分析 + activeVarAnalysis->clear(); dataFlowAnalysisUtils.addBackwardAnalyzer(activeVarAnalysis); dataFlowAnalysisUtils.backwardAnalyze(pModule); diff --git a/src/include/Mem2Reg.h b/src/include/Mem2Reg.h index f3b54ff..0004708 100644 --- a/src/include/Mem2Reg.h +++ b/src/include/Mem2Reg.h @@ -17,13 +17,14 @@ class Mem2Reg { private: Module *pModule; IRBuilder *pBuilder; - ActiveVarAnalysis *activeVarAnalysis; // 活跃变量分析 ControlFlowAnalysis *controlFlowAnalysis; // 控制流分析 + ActiveVarAnalysis *activeVarAnalysis; // 活跃变量分析 DataFlowAnalysisUtils dataFlowAnalysisUtils; public: - Mem2Reg(Module *pMoudle, IRBuilder *pBuilder) : - pModule(pMoudle), pBuilder(pBuilder), activeVarAnalysis(nullptr), controlFlowAnalysis(nullptr), dataFlowAnalysisUtils() + Mem2Reg(Module *pMoudle, IRBuilder *pBuilder, + ControlFlowAnalysis *pCFA = nullptr, ActiveVarAnalysis *pAVA = nullptr) : + pModule(pMoudle), pBuilder(pBuilder), controlFlowAnalysis(pCFA), activeVarAnalysis(pAVA), dataFlowAnalysisUtils() {} // 初始化函数 void mem2regPipeline(); ///< mem2reg From 0d23475aa1f1524599ccd26b18b0dd8eb519b085 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Wed, 25 Jun 2025 15:33:25 +0800 Subject: [PATCH 10/10] =?UTF-8?q?[=E6=AD=BB=E4=BB=A3=E7=A0=81=E5=88=A0?= =?UTF-8?q?=E9=99=A4]:=E4=BF=9D=E8=AF=81=E6=89=A9=E5=B1=95=E6=80=A7?= =?UTF-8?q?=E3=80=81=E6=A8=A1=E5=9D=97=E5=8C=96=E6=9E=84=E5=BB=BA=E6=AD=BB?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=88=A0=E9=99=A4=EF=BC=8C=E5=8C=85=E6=8B=AC?= =?UTF-8?q?=E6=B6=88=E9=99=A4=E6=97=A0=E7=94=A8store,alloca,load,globalval?= =?UTF-8?q?,mem2reg=E5=BC=95=E5=85=A5=E7=9A=84=E6=97=A0=E7=94=A8alloca?= =?UTF-8?q?=E4=BB=A5=E5=8F=8Areg2mem=E5=AF=BC=E8=87=B4=E7=9A=84store-load-?= =?UTF-8?q?store=E5=86=97=E4=BD=99=E5=AD=98=E5=82=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CMakeLists.txt | 1 + src/DeadCodeElimination.cpp | 99 ++++++++++++++++++++++++++----- src/include/DeadCodeElimination.h | 11 +++- src/include/IRBuilder.h | 2 +- src/sysyc.cpp | 15 ++++- 5 files changed, 108 insertions(+), 20 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b1a2f00..e7bebb7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable(sysyc SysYIRPrinter.cpp SysYIROptPre.cpp SysYIRAnalyser.cpp + DeadCodeElimination.cpp Mem2Reg.cpp Reg2Mem.cpp RISCv32Backend.cpp diff --git a/src/DeadCodeElimination.cpp b/src/DeadCodeElimination.cpp index 80b0022..9abca1c 100644 --- a/src/DeadCodeElimination.cpp +++ b/src/DeadCodeElimination.cpp @@ -19,6 +19,10 @@ void DeadCodeElimination::runDCEPipeline() { } } +// 消除无用存储 消除条件: +// 存储的目标指针(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(); @@ -31,8 +35,8 @@ void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) { auto storeInst = dynamic_cast(inst); auto pointer = storeInst->getPointer(); - if (isGlobal(pointer) || - (isArr(pointer) && + // 如果是全局变量或者是函数的数组参数 + if (isGlobal(pointer) || (isArr(pointer) && std::find(func->getEntryBlock()->getArguments().begin(), func->getEntryBlock()->getArguments().end(), pointer) != func->getEntryBlock()->getArguments().end())) { @@ -40,17 +44,19 @@ void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) { continue; } - bool tag = true; + 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()) { - tag = false; + changetag = false; break; } } - if (tag) { + if (changetag) { changed = true; usedelete(storeInst); iter = instrs.erase(iter); @@ -60,7 +66,8 @@ void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) { } } } - +// 消除无用加载 消除条件: +// 该指令的结果未被使用(inst->getUses().empty())。 void DeadCodeElimination::eliminateDeadLoads(Function* func, bool& changed) { for (const auto& block : func->getBasicBlocks()) { auto& instrs = block->getInstructions(); @@ -79,6 +86,9 @@ void DeadCodeElimination::eliminateDeadLoads(Function* func, bool& changed) { } } +// 消除无用加载 消除条件: +// 该 alloca 未被任何指令使用(allocaInst->getUses().empty())。 +// 该 alloca 不是函数的参数(不在 entry 块的参数列表里)。 void DeadCodeElimination::eliminateDeadAllocas(Function* func, bool& changed) { for (const auto& block : func->getBasicBlocks()) { auto& instrs = block->getInstructions(); @@ -99,18 +109,23 @@ void DeadCodeElimination::eliminateDeadAllocas(Function* func, bool& changed) { ++iter; } } - - // for (auto it = func->getIndirectAllocas().begin(); it != func->getIndirectAllocas().end();) { - // auto& allocaInst = *it; - // if (allocaInst->getUses().empty()) { - // changed = true; - // it = func->getIndirectAllocas().erase(it); - // } else { - // ++it; - // } - // } } +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; + 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();) { @@ -124,6 +139,10 @@ void DeadCodeElimination::eliminateDeadGlobals(bool& changed) { } } +// 消除冗余加载和存储 消除条件: +// 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(); @@ -140,12 +159,14 @@ void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool& break; } } + /// 如果 pointer 仅被该 phi 使用,可以删除 ph if (tag) { changed = true; usedelete(inst); iter = instrs.erase(iter); continue; } + // 数组指令还不完善,不保证memset优化效果 } else if (inst->isMemset()) { auto memsetInst = dynamic_cast(inst); auto pointer = memsetInst->getPointer(); @@ -155,6 +176,52 @@ void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool& 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); + usedelete(loadInst); + iter = instrs.erase(iter); + // 删除 prevStore 这里是不是可以留给删除无用store处理? + // if (prevStore->getUses().empty()) { + // usedelete(prevStore); + // instrs.erase(prevIter); // 删除 prevStore + // } + continue; // 跳过 ++iter,因为已经移动迭代器 + } + } + } + } + } + } + } } ++iter; } diff --git a/src/include/DeadCodeElimination.h b/src/include/DeadCodeElimination.h index 5b127a1..2d614bd 100644 --- a/src/include/DeadCodeElimination.h +++ b/src/include/DeadCodeElimination.h @@ -1,15 +1,21 @@ #pragma once #include "IR.h" - +#include "SysYIRAnalyser.h" namespace sysy { class DeadCodeElimination { private: Module *pModule; + ControlFlowAnalysis *pCFA; // 控制流分析指针 + ActiveVarAnalysis *pAVA; // 活跃变量分析指针 + DataFlowAnalysisUtils dataFlowAnalysisUtils; // 数据流分析工具类 public: - explicit DeadCodeElimination(Module *pMoudle) : pModule(pMoudle) {} // 初始化函数 + 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 = { @@ -21,6 +27,7 @@ class DeadCodeElimination { 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); // 消除冗余加载和存储 bool isGlobal(Value *val); bool isArr(Value *val); diff --git a/src/include/IRBuilder.h b/src/include/IRBuilder.h index 088427f..aab9a1d 100644 --- a/src/include/IRBuilder.h +++ b/src/include/IRBuilder.h @@ -263,7 +263,7 @@ class IRBuilder { 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()) { diff --git a/src/sysyc.cpp b/src/sysyc.cpp index acb553e..f21fb49 100644 --- a/src/sysyc.cpp +++ b/src/sysyc.cpp @@ -11,6 +11,7 @@ using namespace antlr4; #include "SysYIRPrinter.h" #include "SysYIROptPre.h" #include "SysYIRAnalyser.h" +#include "DeadCodeElimination.h" #include "Mem2Reg.h" #include "Reg2Mem.h" // #include "LLVMIRGenerator.h" @@ -86,12 +87,24 @@ int main(int argc, char **argv) { auto builder = generator.getBuilder(); SysYOptPre optPre(moduleIR, builder); optPre.SysYOptimizateAfterIR(); - Mem2Reg mem2reg(moduleIR, builder); + ControlFlowAnalysis cfa(moduleIR); + cfa.init(); + ActiveVarAnalysis ava; + ava.init(moduleIR); + printer.printIR(); + + + DeadCodeElimination dce(moduleIR, &cfa, &ava); + dce.runDCEPipeline(); + + Mem2Reg mem2reg(moduleIR, builder, &cfa, &ava); mem2reg.mem2regPipeline(); printer.printIR(); Reg2Mem reg2mem(moduleIR, builder); reg2mem.DeletePhiInst(); printer.printIR(); + dce.runDCEPipeline(); + printer.printIR(); return EXIT_SUCCESS; } return EXIT_SUCCESS;