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] =?UTF-8?q?mem2reg=E6=B5=81=E7=A8=8B=E5=9F=BA=E6=9C=AC?= =?UTF-8?q?=E8=B7=91=E9=80=9A=EF=BC=8C=E4=BF=AE=E5=A4=8Dphi=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E6=89=93=E5=8D=B0=EF=BC=8C=E9=9C=80=E8=A6=81=E5=88=A0?= =?UTF-8?q?=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();