mem2reg流程基本跑通,修复phi函数打印,需要删除调试print
This commit is contained in:
241
src/Mem2Reg.cpp
241
src/Mem2Reg.cpp
@ -46,42 +46,116 @@ std::unordered_set<BasicBlock *> 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<Instruction *>(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<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);
|
||||
std::cout << " Load source: ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(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<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
|
||||
*
|
||||
@ -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<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();) {
|
||||
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是value2DefBlocks,vToUseB是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 &&
|
||||
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<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());
|
||||
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<Instruction *>(val));
|
||||
std::cout << std::endl;
|
||||
|
||||
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);
|
||||
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<Instruction *>((*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<Instruction *>(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();
|
||||
|
||||
@ -264,7 +264,7 @@ std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) {
|
||||
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()));
|
||||
Type* variableType = dynamic_cast<PointerType *>(variable->getType())->getBaseType();
|
||||
|
||||
|
||||
@ -438,14 +438,16 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
|
||||
case Kind::kPhi: {
|
||||
auto phiInst = dynamic_cast<PhiInst *>(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<BasicBlock*>(phiInst->getOperand(i+1))->getName() << " ]";
|
||||
std::cout << " ]";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
} break;
|
||||
|
||||
@ -94,7 +94,7 @@ public:
|
||||
std::set<Function*> callees; ///< 函数调用集合
|
||||
Loop_list loops; ///< 所有循环
|
||||
Loop_list topLoops; ///< 顶层循环
|
||||
block_loop_map basicblock2Loop; ///< 基本块到循环映射
|
||||
// block_loop_map basicblock2Loop; ///< 基本块到循环映射
|
||||
std::list<std::unique_ptr<AllocaInst>> indirectAllocas; ///< 间接分配内存
|
||||
|
||||
// 值定义/使用信息
|
||||
@ -198,7 +198,7 @@ public:
|
||||
callees.clear();
|
||||
loops.clear();
|
||||
topLoops.clear();
|
||||
basicblock2Loop.clear();
|
||||
// basicblock2Loop.clear();
|
||||
indirectAllocas.clear();
|
||||
value2AllocBlocks.clear();
|
||||
value2DefBlocks.clear();
|
||||
|
||||
Reference in New Issue
Block a user