From 97410d941753916355d9edfce25dbf272877be9d Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Wed, 25 Jun 2025 16:07:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=E8=B0=83=E8=AF=95=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E8=BE=93=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/IR.cpp | 60 +++---------- src/Mem2Reg.cpp | 233 ++++++++++++++++++++++-------------------------- 2 files changed, 119 insertions(+), 174 deletions(-) diff --git a/src/IR.cpp b/src/IR.cpp index 1483bf3..540f974 100644 --- a/src/IR.cpp +++ b/src/IR.cpp @@ -135,7 +135,7 @@ auto Function::getCalleesWithNoExternalAndSelf() -> std::set { } return result; } - +// 函数克隆,后续函数级优化(内联等)需要用到 Function * Function::clone(const std::string &suffix) const { std::stringstream ss; std::map oldNewBlockMap; @@ -527,11 +527,7 @@ Function * Function::clone(const std::string &suffix) const { return newFunction; } /** - * @brief 设置操作数 - * - * @param [in] index 所要设置的操作数的位置 - * @param [in] value 所要设置成的value - * @return 无返回值 + * 设置操作数 */ void User::setOperand(unsigned index, Value *value) { assert(index < getNumOperands()); @@ -539,11 +535,7 @@ void User::setOperand(unsigned index, Value *value) { value->addUse(operands[index]); } /** - * @brief 替换操作数 - * - * @param [in] index 所要替换的操作数的位置 - * @param [in] value 所要替换成的value - * @return 无返回值 + * 替换操作数 */ void User::replaceOperand(unsigned index, Value *value) { assert(index < getNumOperands()); @@ -561,17 +553,12 @@ CallInst::CallInst(Function *callee, const std::vector &args, BasicBloc } } /** - * @brief 获取被调用函数的指针 - * - * @return 被调用函数的指针 + * 获取被调用函数的指针 */ Function * CallInst::getCallee() const { return dynamic_cast(getOperand(0)); } /** - * @brief 获取变量指针 - * - * @param [in] name 变量名字 - * @return 变量指针 + * 获取变量指针 */ auto SymbolTable::getVariable(const std::string &name) const -> User * { auto node = curNode; @@ -586,11 +573,7 @@ auto SymbolTable::getVariable(const std::string &name) const -> User * { return nullptr; } /** - * @brief 添加变量 - * - * @param [in] name 变量名字 - * @param [in] variable 变量指针 - * @return 变量指针 + * 添加变量到符号表 */ auto SymbolTable::addVariable(const std::string &name, User *variable) -> User * { User *result = nullptr; @@ -621,21 +604,15 @@ auto SymbolTable::addVariable(const std::string &name, User *variable) -> User * return result; } /** - * @brief 获取全局变量 - * - * @return 全局变量列表 + * 获取全局变量 */ auto SymbolTable::getGlobals() -> std::vector> & { return globals; } /** - * @brief 获取常量 - * - * @return 常量列表 + * 获取常量 */ auto SymbolTable::getConsts() const -> const std::vector> & { return consts; } /** - * @brief 进入新的作用域 - * - * @return 无返回值 + * 进入新的作用域 */ void SymbolTable::enterNewScope() { auto newNode = new SymbolTableNode; @@ -647,31 +624,20 @@ void SymbolTable::enterNewScope() { curNode = newNode; } /** - * @brief 进入全局作用域 - * - * @return 无返回值 + * 进入全局作用域 */ void SymbolTable::enterGlobalScope() { curNode = nodeList.front().get(); } /** - * @brief 离开作用域 - * - * @return 无返回值 + * 离开作用域 */ void SymbolTable::leaveScope() { curNode = curNode->pNode; } /** - * @brief 是否位于全局作用域 - * - * @return 布尔值 + * 是否位于全局作用域 */ auto SymbolTable::isInGlobalScope() const -> bool { return curNode->pNode == nullptr; } /** - * @brief 移动指令 - * - * @param [in] sourcePos 源指令列表位置 - * @param [in] targetPos 目的指令列表位置 - * @param [in] block 目标基本块 - * @return 无返回值 + *移动指令 */ auto BasicBlock::moveInst(iterator sourcePos, iterator targetPos, BasicBlock *block) -> iterator { auto inst = sourcePos->release(); diff --git a/src/Mem2Reg.cpp b/src/Mem2Reg.cpp index bf7e541..db584ed 100644 --- a/src/Mem2Reg.cpp +++ b/src/Mem2Reg.cpp @@ -47,12 +47,12 @@ std::unordered_set Mem2Reg::computeIterDf(const std::unordered_set */ auto Mem2Reg::computeValue2Blocks() -> void { SysYPrinter printer(pModule); // 初始化打印机 - std::cout << "===== Start computeValue2Blocks =====" << std::endl; + // std::cout << "===== Start computeValue2Blocks =====" << std::endl; auto &functions = pModule->getFunctions(); for (const auto &function : functions) { auto func = function.second.get(); - std::cout << "\nProcessing function: " << func->getName() << std::endl; + // std::cout << "\nProcessing function: " << func->getName() << std::endl; FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func); if (!funcInfo) { @@ -61,98 +61,98 @@ auto Mem2Reg::computeValue2Blocks() -> void { } auto basicBlocks = func->getBasicBlocks(); - std::cout << "BasicBlocks count: " << basicBlocks.size() << std::endl; + // std::cout << "BasicBlocks count: " << basicBlocks.size() << std::endl; for (auto &it : basicBlocks) { auto basicBlock = it.get(); - std::cout << "\nProcessing BB: " << basicBlock->getName() << std::endl; + // std::cout << "\nProcessing BB: " << basicBlock->getName() << std::endl; // printer.printBlock(basicBlock); // 打印基本块内容 auto &instrs = basicBlock->getInstructions(); for (auto &instr : instrs) { - std::cout << " Analyzing instruction: "; - printer.printInst(instr.get()); - std::cout << std::endl; + // 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; + // std::cout << " Found alloca: "; + // printer.printInst(instr.get()); + // std::cout << " -> Adding to allocBlocks" << std::endl; funcInfo->addValue2AllocBlocks(instr.get(), basicBlock); } else { - std::cout << " Skip array/global alloca: "; - printer.printInst(instr.get()); - std::cout << std::endl; + // std::cout << " Skip array/global alloca: "; + // printer.printInst(instr.get()); + // std::cout << std::endl; } } else if (instr->isStore()) { auto val = instr->getOperand(1); - std::cout << " Store target: "; - printer.printInst(dynamic_cast(val)); + // std::cout << " Store target: "; + // printer.printInst(dynamic_cast(val)); if (!(isArr(val) || isGlobal(val))) { - std::cout << " Adding store to defBlocks for value: "; - printer.printInst(dynamic_cast(instr.get())); - std::cout << std::endl; + // 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; + // std::cout << " Skip array/global store" << std::endl; } } else if (instr->isLoad()) { auto val = instr->getOperand(0); - std::cout << " Load source: "; - printer.printInst(dynamic_cast(val)); - std::cout << std::endl; + // std::cout << " Load source: "; + // printer.printInst(dynamic_cast(val)); + // std::cout << std::endl; if (!(isArr(val) || isGlobal(val))) { - std::cout << " Adding load to useBlocks for value: "; - printer.printInst(dynamic_cast(val)); - std::cout << std::endl; + // 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 << " Skip array/global load" << std::endl; } } } } // 打印分析结果 - std::cout << "\nAnalysis results for function " << func->getName() << ":" << 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 &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 &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 << ")"; - } - } + // 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; + // std::cout << "===== End computeValue2Blocks =====" << std::endl; } @@ -207,33 +207,31 @@ auto Mem2Reg::cascade(Instruction *instr, bool &changed, Function *func, BasicBl } /** - * @brief llvm mem2reg预优化1: 删除不含load的alloc和store + * 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 { SysYPrinter printer(pModule); // 初始化打印机 auto &functions = pModule->getFunctions(); - std::cout << "===== Start preOptimize1 =====" << std::endl; + // std::cout << "===== Start preOptimize1 =====" << std::endl; for (const auto &function : functions) { auto func = function.second.get(); - std::cout << "\nProcessing function: " << func->getName() << std::endl; + // 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; + // std::cerr << "ERROR: No analysis info for function " << func->getName() << std::endl; continue; } @@ -242,48 +240,45 @@ auto Mem2Reg::preOptimize1() -> void { 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; - } + // 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; + // 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; + // 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; - - + // 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; if (vToDefB.count(val) == 0U && 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; + // 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(), @@ -291,7 +286,7 @@ auto Mem2Reg::preOptimize1() -> void { return instr.get() == val; }); if (tofind == bb->getInstructions().end()) { - std::cerr << "ERROR: Alloca not found in BB!" << std::endl; + // std::cerr << "ERROR: Alloca not found in BB!" << std::endl; ++iter; continue; } @@ -305,37 +300,37 @@ auto Mem2Reg::preOptimize1() -> void { } // 阶段2:删除无load的store - std::cout << "\nPhase 2: Remove dead stores" << std::endl; + // 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; + // std::cout << "\nIteration " << iteration << std::endl; for (auto iter = vToDefB.begin(); iter != vToDefB.end();) { auto val = iter->first; - std::cout << "Checking value: "; - printer.printInst(dynamic_cast(val)); - std::cout << std::endl; + // 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; + // 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; + // 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) { - std::cout << " Removing store: "; - printer.printInst(it->get()); + // std::cout << " Removing store: "; + // printer.printInst(it->get()); std::cout << std::endl; auto valUsedByStore = dynamic_cast((*it)->getOperand(0)); @@ -344,9 +339,9 @@ auto Mem2Reg::preOptimize1() -> void { if (valUsedByStore != nullptr && valUsedByStore->getUses().size() == 1 && valUsedByStore->getUses().front()->getUser() == (*it).get()) { - std::cout << " Cascade deleting: "; - printer.printInst(valUsedByStore); - std::cout << std::endl; + // std::cout << " Cascade deleting: "; + // printer.printInst(valUsedByStore); + // std::cout << std::endl; cascade(valUsedByStore, changed, func, block, instrs); } @@ -364,9 +359,9 @@ auto Mem2Reg::preOptimize1() -> void { 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; + // 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(), @@ -389,11 +384,11 @@ auto Mem2Reg::preOptimize1() -> void { } } } - std::cout << "===== End preOptimize1 =====" << std::endl; + // std::cout << "===== End preOptimize1 =====" << std::endl; } /** - * @brief llvm mem2reg预优化2: 针对某个变量的Defblocks只有一个块的情况 + * llvm mem2reg预优化2: 针对某个变量的Defblocks只有一个块的情况 * * 1. 该基本块最后一次对该变量的store指令后的所有对该变量的load指令都可以替换为该基本块最后一次store指令的第0个操作数; * 2. 以该基本块为必经结点的结点集合中的对该变量的load指令都可以替换为该基本块最后一次对该变量的store指令的第0个操作数; @@ -402,12 +397,9 @@ auto Mem2Reg::preOptimize1() -> void { * 4. * 如果对该value的所有load都替换掉了,对于该变量剩下还有store的话,就转换成了preOptimize1的情况,再调用preOptimize1进行删除; * - * @note 额外说明:同样有点儿激进; * 同样不考虑数组和全局变量,因为这些变量不会被mem2reg优化,在value2blocks中已经考虑了,所以不用显式指明; * 替换的操作采用了UD链进行简化和效率的提升 * - * @param [in] void - * @return 无返回值,但满足条件的情况下会对指令的操作数进行替换以及对指令进行删除 */ auto Mem2Reg::preOptimize2() -> void { auto &functions = pModule->getFunctions(); @@ -570,14 +562,12 @@ auto Mem2Reg::preOptimize3() -> void { } /** - * @brief 为所有变量的定义块集合的迭代支配边界插入phi结点 + * 为所有变量的定义块集合的迭代支配边界插入phi结点 * * insertPhi是mem2reg的核心之一,这里是对所有变量的迭代支配边界的phi结点插入,无参数也无返回值; * 同样跳过对数组和全局变量的处理,因为这些变量不会被mem2reg优化,刚好这里在计算value2DefBlocks时已经跳过了,所以不需要再显式处理了; * 同时我们进行了剪枝处理,只有在基本块入口活跃的变量,才插入phi函数 * - * @param [in] void - * @return 无返回值,但是会在每个变量的迭代支配边界上插入phi结点 */ auto Mem2Reg::insertPhi() -> void { auto &functions = pModule->getFunctions(); @@ -604,15 +594,11 @@ auto Mem2Reg::insertPhi() -> void { } /** - * @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 { @@ -712,12 +698,10 @@ auto Mem2Reg::rename(BasicBlock *block, std::unordered_map &count, } /** - * @brief 重命名所有块 + * 重命名所有块 * * 调用rename,自上而下实现所有rename * - * @param [in] void - * @return 无返回值 */ auto Mem2Reg::renameAll() -> void { auto &functions = pModule->getFunctions(); @@ -736,12 +720,10 @@ auto Mem2Reg::renameAll() -> void { } /** - * @brief mem2reg,对外的接口 + * mem2reg,对外的接口 * * 静态单一赋值 + mem2reg等pass的逻辑组合 * - * @param [in] void - * @return 无返回值 */ auto Mem2Reg::mem2regPipeline() -> void { // 首先进行mem2reg的前置分析 @@ -774,13 +756,10 @@ auto Mem2Reg::mem2regPipeline() -> void { } /** - * @brief 计算块n是块s的第几个前驱 + * 计算块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;