[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

@@ -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