[midend]合并了SCCP和backend,修复了支配树的错误求解,修复了Mem2Reg的重命名alloca的栈管理

This commit is contained in:
rain2133
2025-08-01 15:18:33 +08:00
parent 999f2c6615
commit a0b69f20fb
3 changed files with 232 additions and 105 deletions

View File

@ -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: 清理

View File

@ -1,5 +1,7 @@
#include "Dom.h"
#include <limits> // for std::numeric_limits
#include <algorithm> // for std::set_intersection, std::set_difference, std::set_union
#include <iostream> // for debug output
#include <limits> // for std::numeric_limits
#include <queue>
namespace sysy {
@ -38,45 +40,80 @@ const std::set<BasicBlock *> *DominatorTree::getDominanceFrontier(BasicBlock *BB
return nullptr;
}
const std::set<BasicBlock*>* DominatorTree::getDominatorTreeChildren(BasicBlock* BB) const {
auto it = DominatorTreeChildren.find(BB);
if (it != DominatorTreeChildren.end()) {
return &(it->second);
}
return nullptr;
const std::set<BasicBlock *> *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<BasicBlock *> &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<BasicBlock *> 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<BasicBlock *> 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<BasicBlock *> 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<BasicBlock *> *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<BasicBlock *> *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<BasicBlock *> *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<BasicBlock *> *domsOfY = getDominators(Y);
if (domsOfY && domsOfY->find(X) == domsOfY->end()) {
DominanceFrontiers[X].insert(Y);
}
}
const std::set<BasicBlock *> *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<BasicBlock *> *domsOfZ = getDominators(Z);
if (domsOfZ && domsOfZ->count(X) && Z != X) {
for (BasicBlock *Y : Z->getSuccessors()) {
const std::set<BasicBlock *> *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<BasicBlock *> *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<DominatorTree>(F);
// 不需要手动清空mapunique_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<AnalysisResultBase> DominatorTreeAnalysisPass::getResult() {

View File

@ -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<Bas
}
// 对支配树进行深度优先遍历,重命名变量并替换 load/store 指令
void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *currentBB) {
// 维护一个局部栈,用于存储当前基本块中为 Phi 和 Store 创建的 SSA 值,以便在退出时弹出
std::stack<Value *> localStackPushed;
// 移除了 AllocaInst *currentAlloca 参数,因为这个函数是为整个基本块处理所有可提升的 Alloca
void Mem2RegContext::renameVariables(BasicBlock *currentBB) {
// 1. 在函数开始时,记录每个 promotableAlloca 的当前栈深度。
// 这将用于在函数返回时精确地回溯栈状态。
std::map<AllocaInst *, size_t> 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<PhiInst *>(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<LoadInst *>(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<GetElementPtrInst *>(ptrOperand) &&
dynamic_cast<GetElementPtrInst *>(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<StoreInst *>(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<GetElementPtrInst *>(ptrOperand) &&
dynamic_cast<GetElementPtrInst *>(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<BasicBlock *> *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