mem2reg流程基本跑通,修复phi函数打印,需要删除调试print

This commit is contained in:
rain2133
2025-06-25 12:23:59 +08:00
parent bd0b624e87
commit 4fabcc9952
4 changed files with 214 additions and 41 deletions

View File

@@ -46,42 +46,116 @@ std::unordered_set<BasicBlock *> Mem2Reg::computeIterDf(const std::unordered_set
* 这里的value2AllocBlocks、value2DefBlocks和value2UseBlocks改变了函数级别的分析信息 * 这里的value2AllocBlocks、value2DefBlocks和value2UseBlocks改变了函数级别的分析信息
*/ */
auto Mem2Reg::computeValue2Blocks() -> void { auto Mem2Reg::computeValue2Blocks() -> void {
SysYPrinter printer(pModule); // 初始化打印机
std::cout << "===== Start computeValue2Blocks =====" << std::endl;
auto &functions = pModule->getFunctions(); auto &functions = pModule->getFunctions();
for (const auto &function : functions) { for (const auto &function : functions) {
auto func = function.second.get(); auto func = function.second.get();
auto basicBlocks = func->getBasicBlocks(); std::cout << "\nProcessing function: " << func->getName() << std::endl;
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func); 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) { for (auto &it : basicBlocks) {
auto basicBlock = it.get(); auto basicBlock = it.get();
std::cout << "\nProcessing BB: " << basicBlock->getName() << std::endl;
// printer.printBlock(basicBlock); // 打印基本块内容
auto &instrs = basicBlock->getInstructions(); auto &instrs = basicBlock->getInstructions();
for (auto &instr : instrs) { for (auto &instr : instrs) {
// 如果指令本身就是alloca指令则加到allocblocks中 std::cout << " Analyzing instruction: ";
printer.printInst(instr.get());
std::cout << std::endl;
if (instr->isAlloca()) { if (instr->isAlloca()) {
if (!(isArr(instr.get()) || isGlobal(instr.get()))) { 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); 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); auto val = instr->getOperand(1);
std::cout << " Store target: ";
printer.printInst(dynamic_cast<Instruction *>(val));
if (!(isArr(val) || isGlobal(val))) { if (!(isArr(val) || isGlobal(val))) {
funcInfo->addValue2DefBlocks(instr.get(), basicBlock); std::cout << " Adding store to defBlocks for value: ";
// func->addValue2DefBlocks(val, basicBlock); printer.printInst(dynamic_cast<Instruction *>(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); auto val = instr->getOperand(0);
std::cout << " Load source: ";
printer.printInst(dynamic_cast<Instruction *>(val));
std::cout << std::endl;
if (!(isArr(val) || isGlobal(val))) { if (!(isArr(val) || isGlobal(val))) {
funcInfo->addValue2UseBlocks(instr.get(), basicBlock); std::cout << " Adding load to useBlocks for value: ";
// func->addValue2UseBlocks(val, basicBlock); printer.printInst(dynamic_cast<Instruction *>(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<Instruction *>(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<Instruction *>(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<Instruction *>(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 * @brief 级联关系的顺带消除用于llvm mem2reg类预优化1
* *
@@ -148,22 +222,80 @@ auto Mem2Reg::cascade(Instruction *instr, bool &changed, Function *func, BasicBl
* @return 无返回值,但满足条件的情况下会对指令进行删除 * @return 无返回值,但满足条件的情况下会对指令进行删除
*/ */
auto Mem2Reg::preOptimize1() -> void { auto Mem2Reg::preOptimize1() -> void {
SysYPrinter printer(pModule); // 初始化打印机
auto &functions = pModule->getFunctions(); auto &functions = pModule->getFunctions();
std::cout << "===== Start preOptimize1 =====" << std::endl;
for (const auto &function : functions) { for (const auto &function : functions) {
auto func = function.second.get(); auto func = function.second.get();
std::cout << "\nProcessing function: " << func->getName() << std::endl;
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func); 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 &vToDefB = funcInfo->getValue2DefBlocks();
auto &vToUseB = funcInfo->getValue2UseBlocks(); auto &vToUseB = funcInfo->getValue2UseBlocks();
// 先删除孤零零的alloca即没有store的alloca
auto &vToAllocB = funcInfo->getValue2AllocBlocks(); auto &vToAllocB = funcInfo->getValue2AllocBlocks();
// 打印初始状态
std::cout << "Initial allocas: " << vToAllocB.size() << std::endl;
for (auto &[val, bb] : vToAllocB) {
std::cout << " Alloca: ";
printer.printInst(dynamic_cast<Instruction *>(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();) { for (auto iter = vToAllocB.begin(); iter != vToAllocB.end();) {
auto val = iter->first; auto val = iter->first;
auto bb = iter->second;
std::cout << "Checking alloca: ";
printer.printInst(dynamic_cast<Instruction *>(val));
std::cout << " in BB: " << bb->getName() << std::endl;
// 如果该alloca没有对应的store指令且不在函数参数中
// 这里的vToDefB是value2DefBlocksvToUseB是value2UseBlocks
// 打印vToDefB
std::cout << "DefBlocks (" << vToDefB.size() << "):" << std::endl;
for (auto &[val, bbs] : vToDefB) {
std::cout << " ";
printer.printInst(dynamic_cast<Instruction *>(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 && if (vToDefB.count(val) == 0U &&
std::find(func->getEntryBlock()->getArguments().begin(), func->getEntryBlock()->getArguments().end(), val) == std::find(func->getEntryBlock()->getArguments().begin(),
func->getEntryBlock()->getArguments().end()) { func->getEntryBlock()->getArguments().end(),
auto bb = iter->second; val) == func->getEntryBlock()->getArguments().end()) {
auto tofind = std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(),
[val](const auto &instr) { return instr.get() == val; }); std::cout << " Removing unused alloca: ";
printer.printInst(dynamic_cast<Instruction *>(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()); usedelete(tofind->get());
bb->getInstructions().erase(tofind); bb->getInstructions().erase(tofind);
iter = vToAllocB.erase(iter); iter = vToAllocB.erase(iter);
@@ -171,45 +303,83 @@ auto Mem2Reg::preOptimize1() -> void {
++iter; ++iter;
} }
} }
// 阶段2删除无load的store
std::cout << "\nPhase 2: Remove dead stores" << std::endl;
bool changed = true; bool changed = true;
// 不动点法 int iteration = 0;
while (changed) { while (changed) {
changed = false; changed = false;
iteration++;
std::cout << "\nIteration " << iteration << std::endl;
for (auto iter = vToDefB.begin(); iter != vToDefB.end();) { for (auto iter = vToDefB.begin(); iter != vToDefB.end();) {
auto val = iter->first; auto val = iter->first;
// 找到没有load的变量删除关于该变量的store
std::cout << "Checking value: ";
printer.printInst(dynamic_cast<Instruction *>(val));
std::cout << std::endl;
if (vToUseB.count(val) == 0U) { if (vToUseB.count(val) == 0U) {
std::cout << " Found dead store for value: ";
printer.printInst(dynamic_cast<Instruction *>(val));
std::cout << std::endl;
auto blocks = funcInfo->getDefBlocksByValue(val); auto blocks = funcInfo->getDefBlocksByValue(val);
for (auto block : blocks) { for (auto block : blocks) {
std::cout << " Processing BB: " << block->getName() << std::endl;
// printer.printBlock(block); // 打印基本块内容
auto &instrs = block->getInstructions(); auto &instrs = block->getInstructions();
for (auto it = instrs.begin(); it != instrs.end();) { for (auto it = instrs.begin(); it != instrs.end();) {
if (((*it)->isStore() && (*it)->getOperand(1) == val)) { if ((*it)->isStore() && (*it)->getOperand(1) == val) {
// 关于该变量的store指令删除了那对于之前的用于作store指令第0个操作数的那些指令就冗余了也要删除 std::cout << " Removing store: ";
// 只考虑为指令,不考虑字面量和常数,因为它们与之前的指令无关了 printer.printInst(it->get());
// 同时考虑指令的话,该指令可能又与前面的指令可能有较强的级联关系,级联之间又有级联,因此又要考虑前面指令的删除 std::cout << std::endl;
auto valUsedByStore = dynamic_cast<Instruction *>((*it)->getOperand(0)); auto valUsedByStore = dynamic_cast<Instruction *>((*it)->getOperand(0));
usedelete(it->get()); 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()) { valUsedByStore->getUses().front()->getUser() == (*it).get()) {
std::cout << " Cascade deleting: ";
printer.printInst(valUsedByStore);
std::cout << std::endl;
cascade(valUsedByStore, changed, func, block, instrs); cascade(valUsedByStore, changed, func, block, instrs);
} }
it = instrs.erase(it); it = instrs.erase(it);
changed = true;
} else { } else {
++it; ++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()) { val) == func->getEntryBlock()->getArguments().end()) {
auto bb = funcInfo->getAllocBlockByValue(val); auto bb = funcInfo->getAllocBlockByValue(val);
if (bb != nullptr) { if (bb != nullptr) {
std::cout << " Removing alloca: ";
printer.printInst(dynamic_cast<Instruction *>(val));
std::cout << " in BB: " << bb->getName() << std::endl;
funcInfo->removeValue2AllocBlock(val); funcInfo->removeValue2AllocBlock(val);
auto tofind = std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(), auto tofind = std::find_if(bb->getInstructions().begin(),
[val](const auto &instr) { return instr.get() == val; }); bb->getInstructions().end(),
usedelete(tofind->get()); [val](const auto &instr) {
bb->getInstructions().erase(tofind); 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); 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的定义映射 // 计算所有valueToBlocks的定义映射
computeValue2Blocks(); computeValue2Blocks();
SysYPrinter printer(pModule); // SysYPrinter printer(pModule);
// 参考llvm的mem2reg遍在插入phi结点之前先做些优化 // 参考llvm的mem2reg遍在插入phi结点之前先做些优化
preOptimize1(); preOptimize1();
printer.printIR(); // printer.printIR();
preOptimize2(); preOptimize2();
printer.printIR(); // printer.printIR();
// 优化三 可能会针对局部变量优化而删除整个块的alloca/store // 优化三 可能会针对局部变量优化而删除整个块的alloca/store
preOptimize3(); preOptimize3();
//再进行活跃变量分析 //再进行活跃变量分析
// 报错? // 报错?
printer.printIR(); // printer.printIR();
dataFlowAnalysisUtils.backwardAnalyze(pModule); dataFlowAnalysisUtils.backwardAnalyze(pModule);
// 为所有变量插入phi结点 // 为所有变量插入phi结点
insertPhi(); insertPhi();

View File

@@ -264,7 +264,7 @@ std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) {
dims.push_back(std::any_cast<Value *>(visitExp(exp))); dims.push_back(std::any_cast<Value *>(visitExp(exp)));
} }
User* variable = module->getVariable(name); auto variable = module->getVariable(name);
Value* value = std::any_cast<Value *>(visitExp(ctx->exp())); Value* value = std::any_cast<Value *>(visitExp(ctx->exp()));
Type* variableType = dynamic_cast<PointerType *>(variable->getType())->getBaseType(); Type* variableType = dynamic_cast<PointerType *>(variable->getType())->getBaseType();

View File

@@ -438,14 +438,16 @@ void SysYPrinter::printInst(Instruction *pInst) {
case Kind::kPhi: { case Kind::kPhi: {
auto phiInst = dynamic_cast<PhiInst *>(pInst); auto phiInst = dynamic_cast<PhiInst *>(pInst);
std::cout << "%" << phiInst->getName() << " = phi "; std::cout << "%";
printValue(phiInst->getOperand(0));
std::cout << " = phi ";
printType(phiInst->getType()); 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 << ", "; if (i > 0) std::cout << ", ";
std::cout << "[ "; std::cout << "[ ";
printValue(phiInst->getOperand(i)); printValue(phiInst->getOperand(i));
std::cout << ", %" << dynamic_cast<BasicBlock*>(phiInst->getOperand(i+1))->getName() << " ]"; std::cout << " ]";
} }
std::cout << std::endl; std::cout << std::endl;
} break; } break;

View File

@@ -94,7 +94,7 @@ public:
std::set<Function*> callees; ///< 函数调用集合 std::set<Function*> callees; ///< 函数调用集合
Loop_list loops; ///< 所有循环 Loop_list loops; ///< 所有循环
Loop_list topLoops; ///< 顶层循环 Loop_list topLoops; ///< 顶层循环
block_loop_map basicblock2Loop; ///< 基本块到循环映射 // block_loop_map basicblock2Loop; ///< 基本块到循环映射
std::list<std::unique_ptr<AllocaInst>> indirectAllocas; ///< 间接分配内存 std::list<std::unique_ptr<AllocaInst>> indirectAllocas; ///< 间接分配内存
// 值定义/使用信息 // 值定义/使用信息
@@ -198,7 +198,7 @@ public:
callees.clear(); callees.clear();
loops.clear(); loops.clear();
topLoops.clear(); topLoops.clear();
basicblock2Loop.clear(); // basicblock2Loop.clear();
indirectAllocas.clear(); indirectAllocas.clear();
value2AllocBlocks.clear(); value2AllocBlocks.clear();
value2DefBlocks.clear(); value2DefBlocks.clear();