diff --git a/src/include/midend/Pass/Optimize/Mem2Reg.h b/src/include/midend/Pass/Optimize/Mem2Reg.h index 52a64fd..451509e 100644 --- a/src/include/midend/Pass/Optimize/Mem2Reg.h +++ b/src/include/midend/Pass/Optimize/Mem2Reg.h @@ -75,11 +75,7 @@ private: // -------------------------------------------------------------------- // 对支配树进行深度优先遍历,重命名变量并替换 load/store 指令 - // alloca: 当前正在处理的 AllocaInst - // currentBB: 当前正在遍历的基本块 - // dt: 支配树分析结果 - // valueStack: 存储当前 AllocaInst 在当前路径上可见的 SSA 值栈 - void renameVariables(AllocaInst* alloca, BasicBlock* currentBB); + void renameVariables(BasicBlock* currentBB); // -------------------------------------------------------------------- // 阶段4: 清理 diff --git a/src/midend/Pass/Analysis/Dom.cpp b/src/midend/Pass/Analysis/Dom.cpp index 73726c5..77b2bba 100644 --- a/src/midend/Pass/Analysis/Dom.cpp +++ b/src/midend/Pass/Analysis/Dom.cpp @@ -1,5 +1,7 @@ #include "Dom.h" -#include // for std::numeric_limits +#include // for std::set_intersection, std::set_difference, std::set_union +#include // for debug output +#include // for std::numeric_limits #include namespace sysy { @@ -38,45 +40,80 @@ const std::set *DominatorTree::getDominanceFrontier(BasicBlock *BB return nullptr; } -const std::set* DominatorTree::getDominatorTreeChildren(BasicBlock* BB) const { - auto it = DominatorTreeChildren.find(BB); - if (it != DominatorTreeChildren.end()) { - return &(it->second); - } - return nullptr; +const std::set *DominatorTree::getDominatorTreeChildren(BasicBlock *BB) const { + auto it = DominatorTreeChildren.find(BB); + if (it != DominatorTreeChildren.end()) { + return &(it->second); + } + return nullptr; +} + +// 辅助函数:打印 BasicBlock 集合 +void printBBSet(const std::string &prefix, const std::set &s) { + if (!DEBUG) + return; + std::cout << prefix << "{"; + bool first = true; + for (const auto &bb : s) { + if (!first) + std::cout << ", "; + std::cout << bb->getName(); + first = false; + } + std::cout << "}" << std::endl; } void DominatorTree::computeDominators(Function *F) { - // 经典的迭代算法计算支配者集合 - // TODO: 可以替换为更高效的算法,如 Lengauer-Tarjan 算法 - BasicBlock *entryBlock = F->getEntryBlock(); + if (DEBUG) + std::cout << "--- Computing Dominators ---" << std::endl; + BasicBlock *entryBlock = F->getEntryBlock(); + std::vector bbs_in_order; // 用于确定遍历顺序,如果需要的话 + + // 初始化:入口块只被自己支配,其他块被所有块支配 for (const auto &bb_ptr : F->getBasicBlocks()) { BasicBlock *bb = bb_ptr.get(); + bbs_in_order.push_back(bb); // 收集所有块 if (bb == entryBlock) { Dominators[bb].insert(bb); + if (DEBUG) + std::cout << "Init Dominators[" << bb->getName() << "]: {" << bb->getName() << "}" << std::endl; } else { for (const auto &all_bb_ptr : F->getBasicBlocks()) { Dominators[bb].insert(all_bb_ptr.get()); } + if (DEBUG) { + std::cout << "Init Dominators[" << bb->getName() << "]: "; + printBBSet("", Dominators[bb]); + } } } bool changed = true; + int iteration = 0; while (changed) { changed = false; - for (const auto &bb_ptr : F->getBasicBlocks()) { + iteration++; + if (DEBUG) + std::cout << "Iteration " << iteration << std::endl; + + // 确保遍历顺序一致性,例如可以按照DFS或BFS顺序,或者简单的迭代器顺序 + // 如果Function::getBasicBlocks()返回的迭代器顺序稳定,则无需bbs_in_order + for (const auto &bb_ptr : F->getBasicBlocks()) { // 假设这个迭代器顺序稳定 BasicBlock *bb = bb_ptr.get(); if (bb == entryBlock) continue; + // 计算所有前驱的支配者集合的交集 std::set newDom; - bool firstPred = true; + bool firstPredProcessed = false; + for (BasicBlock *pred : bb->getPredecessors()) { + // 确保前驱的支配者集合已经计算过 if (Dominators.count(pred)) { - if (firstPred) { + if (!firstPredProcessed) { newDom = Dominators[pred]; - firstPred = false; + firstPredProcessed = true; } else { std::set intersection; std::set_intersection(newDom.begin(), newDom.end(), Dominators[pred].begin(), Dominators[pred].end(), @@ -85,21 +122,32 @@ void DominatorTree::computeDominators(Function *F) { } } } - newDom.insert(bb); + newDom.insert(bb); // BB 永远支配自己 if (newDom != Dominators[bb]) { + if (DEBUG) { + std::cout << " Dominators[" << bb->getName() << "] changed from "; + printBBSet("", Dominators[bb]); + std::cout << " to "; + printBBSet("", newDom); + } Dominators[bb] = newDom; changed = true; } } } + if (DEBUG) + std::cout << "--- Dominators Computation Finished ---" << std::endl; } void DominatorTree::computeIDoms(Function *F) { - // 采用与之前类似的简化实现。TODO:Lengauer-Tarjan等算法。 - BasicBlock *entryBlock = F->getEntryBlock(); - IDoms[entryBlock] = nullptr; + if (DEBUG) + std::cout << "--- Computing Immediate Dominators (IDoms) ---" << std::endl; + BasicBlock *entryBlock = F->getEntryBlock(); + IDoms[entryBlock] = nullptr; // 入口块没有即时支配者 + + // 遍历所有非入口块 for (const auto &bb_ptr : F->getBasicBlocks()) { BasicBlock *bb = bb_ptr.get(); if (bb == entryBlock) @@ -107,91 +155,138 @@ void DominatorTree::computeIDoms(Function *F) { BasicBlock *currentIDom = nullptr; const std::set *domsOfBB = getDominators(bb); - if (!domsOfBB) + if (!domsOfBB) { + if (DEBUG) + std::cerr << "Warning: Dominators for " << bb->getName() << " not found!" << std::endl; continue; + } - for (BasicBlock *D : *domsOfBB) { - if (D == bb) - continue; + // 遍历bb的所有严格支配者 D (即 bb 的支配者中除了 bb 自身) + for (BasicBlock *D_candidate : *domsOfBB) { + if (D_candidate == bb) + continue; // 跳过bb自身 - bool isCandidateIDom = true; - for (BasicBlock *candidate : *domsOfBB) { - if (candidate == bb || candidate == D) - continue; - const std::set *domsOfCandidate = getDominators(candidate); - if (domsOfCandidate && domsOfCandidate->count(D) == 0 && domsOfBB->count(candidate)) { - isCandidateIDom = false; + bool D_candidate_is_IDom = true; + // 检查是否存在另一个块 X,使得 D_candidate 严格支配 X 且 X 严格支配 bb + // 或者更直接的,检查 D_candidate 是否被 bb 的所有其他严格支配者所支配 + for (BasicBlock *X_other_dom : *domsOfBB) { + if (X_other_dom == bb || X_other_dom == D_candidate) + continue; // 跳过bb自身和D_candidate + + // 如果 X_other_dom 严格支配 bb (它在 domsOfBB 中且不是bb自身) + // 并且 X_other_dom 不被 D_candidate 支配,那么 D_candidate 就不是 IDom + const std::set *domsOfX_other_dom = getDominators(X_other_dom); + if (domsOfX_other_dom && domsOfX_other_dom->count(D_candidate)) { // X_other_dom 支配 D_candidate + // D_candidate 被另一个支配者 X_other_dom 支配 + // 这说明 D_candidate 位于 X_other_dom 的“下方”,X_other_dom 更接近 bb + // 因此 D_candidate 不是 IDom + D_candidate_is_IDom = false; break; } } - if (isCandidateIDom) { - currentIDom = D; - break; + if (D_candidate_is_IDom) { + currentIDom = D_candidate; + break; // 找到即时支配者,可以退出循环,因为它是唯一的 } } IDoms[bb] = currentIDom; + if (DEBUG) { + std::cout << " IDom[" << bb->getName() << "] = " << (currentIDom ? currentIDom->getName() : "nullptr") + << std::endl; + } } + if (DEBUG) + std::cout << "--- Immediate Dominators Computation Finished ---" << std::endl; } +/* +for each node n in a postorder traversal of the dominator tree: + df[n] = empty set + // compute DF_local(n) + for each child y of n in the CFG: + if idom[y] != n: + df[n] = df[n] U {y} + // compute DF_up(n) + for each child c of n in the dominator tree: + for each element w in df[c]: + if idom[w] != n: + df[n] = df[n] U {w} +*/ + void DominatorTree::computeDominanceFrontiers(Function *F) { - // 经典的支配边界计算算法 + if (DEBUG) + std::cout << "--- Computing Dominance Frontiers ---" << std::endl; + for (const auto &bb_ptr_X : F->getBasicBlocks()) { BasicBlock *X = bb_ptr_X.get(); DominanceFrontiers[X].clear(); - for (BasicBlock *Y : X->getSuccessors()) { - const std::set *domsOfY = getDominators(Y); - if (domsOfY && domsOfY->find(X) == domsOfY->end()) { - DominanceFrontiers[X].insert(Y); - } - } - - const std::set *domsOfX = getDominators(X); - if (!domsOfX) - continue; + // 遍历所有可能的 Z (X支配Z,或者Z就是X) for (const auto &bb_ptr_Z : F->getBasicBlocks()) { BasicBlock *Z = bb_ptr_Z.get(); - if (Z == X) - continue; const std::set *domsOfZ = getDominators(Z); - if (domsOfZ && domsOfZ->count(X) && Z != X) { - for (BasicBlock *Y : Z->getSuccessors()) { - const std::set *domsOfY = getDominators(Y); - if (domsOfY && domsOfY->find(X) == domsOfY->end()) { - DominanceFrontiers[X].insert(Y); - } + // 如果 X 不支配 Z,则 Z 与 DF(X) 无关 + if (!domsOfZ || domsOfZ->find(X) == domsOfZ->end()) { + continue; + } + + // 遍历 Z 的所有后继 Y + for (BasicBlock *Y : Z->getSuccessors()) { + // 如果 Y 不被 X 严格支配,则 Y 在 DF(X) 中 + // Y 不被 X 严格支配意味着 (Y不被X支配) 或 (Y就是X) + const std::set *domsOfY = getDominators(Y); + if (Y == X || (domsOfY && domsOfY->find(X) == domsOfY->end())) { + DominanceFrontiers[X].insert(Y); } } } + if (DEBUG) { + std::cout << " DF(" << X->getName() << "): "; + printBBSet("", DominanceFrontiers[X]); + } } + if (DEBUG) + std::cout << "--- Dominance Frontiers Computation Finished ---" << std::endl; } void DominatorTree::computeDominatorTreeChildren(Function *F) { + if (DEBUG) + std::cout << "--- Computing Dominator Tree Children ---" << std::endl; + // 首先清空,确保重新计算时是空的 + for (auto &bb_ptr : F->getBasicBlocks()) { + DominatorTreeChildren[bb_ptr.get()].clear(); + } + for (auto &bb_ptr : F->getBasicBlocks()) { BasicBlock *B = bb_ptr.get(); - auto it = getImmediateDominator(B); - if (it != nullptr) { - BasicBlock *A = it; - if (A) { - DominatorTreeChildren[A].insert(B); + BasicBlock *A = getImmediateDominator(B); // A 是 B 的即时支配者 + + if (A) { // 如果 B 有即时支配者 A (即 B 不是入口块) + DominatorTreeChildren[A].insert(B); + if (DEBUG) { + std::cout << " " << B->getName() << " is child of " << A->getName() << std::endl; } } } + if (DEBUG) + std::cout << "--- Dominator Tree Children Computation Finished ---" << std::endl; } // ============================================================== // DominatorTreeAnalysisPass 的实现 // ============================================================== - -bool DominatorTreeAnalysisPass::runOnFunction(Function* F, AnalysisManager &AM) { +bool DominatorTreeAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) { + // 每次运行时清空旧数据,确保重新计算 CurrentDominatorTree = std::make_unique(F); + // 不需要手动清空map,unique_ptr会创建新的DominatorTree对象,其map是空的 + CurrentDominatorTree->computeDominators(F); - CurrentDominatorTree->computeIDoms(F); + CurrentDominatorTree->computeIDoms(F); // 修正后的IDoms算法 CurrentDominatorTree->computeDominanceFrontiers(F); CurrentDominatorTree->computeDominatorTreeChildren(F); - return false; + return false; // 分析遍通常返回 false,表示不修改 IR } std::unique_ptr DominatorTreeAnalysisPass::getResult() { diff --git a/src/midend/Pass/Optimize/Mem2Reg.cpp b/src/midend/Pass/Optimize/Mem2Reg.cpp index 89b66af..7570b30 100644 --- a/src/midend/Pass/Optimize/Mem2Reg.cpp +++ b/src/midend/Pass/Optimize/Mem2Reg.cpp @@ -60,7 +60,7 @@ void Mem2RegContext::run(Function *func, AnalysisManager *AM) { } // 从入口基本块开始,对支配树进行 DFS 遍历,进行变量重命名 - renameVariables(nullptr, func->getEntryBlock()); // 第一个参数 alloca 在这里不使用,因为是递归入口点 + renameVariables(func->getEntryBlock()); // 第一个参数 alloca 在这里不使用,因为是递归入口点 // -------------------------------------------------------------------- // 阶段4: 清理 @@ -209,16 +209,21 @@ void Mem2RegContext::insertPhis(AllocaInst *alloca, const std::unordered_set localStackPushed; +// 移除了 AllocaInst *currentAlloca 参数,因为这个函数是为整个基本块处理所有可提升的 Alloca +void Mem2RegContext::renameVariables(BasicBlock *currentBB) { + // 1. 在函数开始时,记录每个 promotableAlloca 的当前栈深度。 + // 这将用于在函数返回时精确地回溯栈状态。 + std::map originalStackSizes; + for (auto alloca : promotableAllocas) { + originalStackSizes[alloca] = allocaToValueStackMap[alloca].size(); + } // -------------------------------------------------------------------- // 处理当前基本块的指令 // -------------------------------------------------------------------- for (auto instIter = currentBB->getInstructions().begin(); instIter != currentBB->getInstructions().end();) { Instruction *inst = instIter->get(); - bool instDeleted = false; + bool instDeleted = false; // 处理 Phi 指令 (如果是当前 alloca 的 Phi) if (auto phiInst = dynamic_cast(inst)) { @@ -227,55 +232,69 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr if (allocaToPhiMap[alloca].count(currentBB) && allocaToPhiMap[alloca][currentBB] == phiInst) { // 为 Phi 指令的输出创建一个新的 SSA 值,并压入值栈 allocaToValueStackMap[alloca].push(phiInst); - localStackPushed.push(phiInst); // 记录以便弹出 - break; // 找到对应的 alloca,处理下一个指令 + if (DEBUG) { + std::cout << "Mem2Reg: Pushed Phi " << (phiInst->getName().empty() ? "anonymous" : phiInst->getName()) << " for alloca " << alloca->getName() + << ". Stack size: " << allocaToValueStackMap[alloca].size() << std::endl; + } + break; // 找到对应的 alloca,处理下一个指令 } } } // 处理 LoadInst else if (auto loadInst = dynamic_cast(inst)) { - // 检查这个 LoadInst 是否是为某个可提升的 alloca for (auto alloca : promotableAllocas) { - if (loadInst->getPointer() == alloca) { - // loadInst->getPointer() 返回 AllocaInst* - // 将 LoadInst 的所有用途替换为当前 alloca 值栈顶部的 SSA 值 + // 检查 LoadInst 的指针是否直接是 alloca,或者是指向 alloca 的 GEP + Value *ptrOperand = loadInst->getPointer(); + if (ptrOperand == alloca || (dynamic_cast(ptrOperand) && + dynamic_cast(ptrOperand)->getBasePointer() == alloca)) { assert(!allocaToValueStackMap[alloca].empty() && "Value stack empty for alloca during load replacement!"); - if(DEBUG){ - std::cout << "Mem2Reg: Replacing load " << loadInst->getPointer()->getName() << " with SSA value." << std::endl; + if (DEBUG) { + std::cout << "Mem2Reg: Replacing load " + << (ptrOperand->getName().empty() ? "anonymous" : ptrOperand->getName()) << " with SSA value " + << (allocaToValueStackMap[alloca].top()->getName().empty() + ? "anonymous" + : allocaToValueStackMap[alloca].top()->getName()) + << " for alloca " << alloca->getName() << std::endl; + std::cout << "Mem2Reg: allocaToValueStackMap[" << alloca->getName() + << "] size: " << allocaToValueStackMap[alloca].size() << std::endl; } loadInst->replaceAllUsesWith(allocaToValueStackMap[alloca].top()); instIter = SysYIROptUtils::usedelete(instIter); instDeleted = true; - // std::cerr << "Mem2Reg: Replaced load " << loadInst->name() << " with SSA value." << std::endl; break; } } } // 处理 StoreInst else if (auto storeInst = dynamic_cast(inst)) { - // 检查这个 StoreInst 是否是为某个可提升的 alloca for (auto alloca : promotableAllocas) { - if (storeInst->getPointer() == alloca) { - // 假设 storeInst->getPointer() 返回 AllocaInst* - // 将 StoreInst 存储的值作为新的 SSA 值,压入值栈 - if(DEBUG){ - std::cout << "Mem2Reg: Replacing store to " << storeInst->getPointer()->getName() << " with SSA value." << std::endl; + // 检查 StoreInst 的指针是否直接是 alloca,或者是指向 alloca 的 GEP + Value *ptrOperand = storeInst->getPointer(); + if (ptrOperand == alloca || (dynamic_cast(ptrOperand) && + dynamic_cast(ptrOperand)->getBasePointer() == alloca)) { + if (DEBUG) { + std::cout << "Mem2Reg: Replacing store to " + << (ptrOperand->getName().empty() ? "anonymous" : ptrOperand->getName()) << " with SSA value " + << (storeInst->getValue()->getName().empty() ? "anonymous" : storeInst->getValue()->getName()) + << " for alloca " << alloca->getName() << std::endl; + std::cout << "Mem2Reg: allocaToValueStackMap[" << alloca->getName() + << "] size before push: " << allocaToValueStackMap[alloca].size() << std::endl; } allocaToValueStackMap[alloca].push(storeInst->getValue()); - localStackPushed.push(storeInst->getValue()); // 记录以便弹出 instIter = SysYIROptUtils::usedelete(instIter); instDeleted = true; - // std::cerr << "Mem2Reg: Replaced store to " << storeInst->ptr()->name() << " with SSA value." << std::endl; + if (DEBUG) { + std::cout << "Mem2Reg: allocaToValueStackMap[" << alloca->getName() + << "] size after push: " << allocaToValueStackMap[alloca].size() << std::endl; + } break; } } } - if (!instDeleted) { ++instIter; // 如果指令没有被删除,移动到下一个 } } - // -------------------------------------------------------------------- // 处理后继基本块的 Phi 指令参数 // -------------------------------------------------------------------- @@ -290,40 +309,57 @@ void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *curr // 参数值是当前 alloca 值栈顶部的 SSA 值 assert(!allocaToValueStackMap[alloca].empty() && "Value stack empty for alloca when setting phi operand!"); phiInst->addIncoming(allocaToValueStackMap[alloca].top(), currentBB); + if (DEBUG) { + std::cout << "Mem2Reg: Added incoming arg to Phi " + << (phiInst->getName().empty() ? "anonymous" : phiInst->getName()) << " from " + << currentBB->getName() << " with value " + << (allocaToValueStackMap[alloca].top()->getName().empty() + ? "anonymous" + : allocaToValueStackMap[alloca].top()->getName()) + << std::endl; + } } } } - // -------------------------------------------------------------------- // 递归访问支配树的子节点 // -------------------------------------------------------------------- const std::set *dominatedBlocks = dt->getDominatorTreeChildren(currentBB); - if(dominatedBlocks){ + if (dominatedBlocks) { // 检查是否存在子节点 + if(DEBUG){ + std::cout << "Mem2Reg: Processing dominated blocks for " << currentBB->getName() << std::endl; + for (auto dominatedBB : *dominatedBlocks) { + std::cout << "Mem2Reg: Dominated block: " << (dominatedBB ? dominatedBB->getName() : "null") << std::endl; + } + } for (auto dominatedBB : *dominatedBlocks) { - if (dominatedBB) { - if(DEBUG){ - std::cout << "Mem2Reg: Recursively renaming variables in dominated block: " << dominatedBB->getName() << std::endl; + if (dominatedBB) { // 确保子块有效 + if (DEBUG) { + std::cout << "Mem2Reg: Recursively renaming variables in dominated block: " << dominatedBB->getName() + << std::endl; } - renameVariables(currentAlloca, dominatedBB); + renameVariables(dominatedBB); // 递归调用,不再传递 currentAlloca } } } - // -------------------------------------------------------------------- - // 退出基本块时,弹出在此块中压入值栈的 SSA 值 + // 退出基本块时,弹出在此块中压入值栈的 SSA 值,恢复栈到进入该块时的状态 // -------------------------------------------------------------------- - while (!localStackPushed.empty()) { - Value *val = localStackPushed.top(); - localStackPushed.pop(); - // 找到是哪个 alloca 对应的栈 - for (auto alloca : promotableAllocas) { - if (!allocaToValueStackMap[alloca].empty() && allocaToValueStackMap[alloca].top() == val) { - allocaToValueStackMap[alloca].pop(); - break; + for (auto alloca : promotableAllocas) { + while (allocaToValueStackMap[alloca].size() > originalStackSizes[alloca]) { + if (DEBUG) { + std::cout << "Mem2Reg: Popping value " + << (allocaToValueStackMap[alloca].top()->getName().empty() + ? "anonymous" + : allocaToValueStackMap[alloca].top()->getName()) + << " for alloca " << alloca->getName() << ". Stack size: " << allocaToValueStackMap[alloca].size() + << " -> " << (allocaToValueStackMap[alloca].size() - 1) << std::endl; } + allocaToValueStackMap[alloca].pop(); } } + } // 删除所有原始的 AllocaInst、LoadInst 和 StoreInst