diff --git a/src/DeadCodeElimination.cpp b/src/DeadCodeElimination.cpp index ffe6022..a986b18 100644 --- a/src/DeadCodeElimination.cpp +++ b/src/DeadCodeElimination.cpp @@ -37,7 +37,7 @@ void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) { auto storeInst = dynamic_cast(inst); auto pointer = storeInst->getPointer(); // 如果是全局变量或者是函数的数组参数 - if (isGlobal(pointer) || (isArr(pointer) && + if (SysYIROptUtils::isGlobal(pointer) || (SysYIROptUtils::isArr(pointer) && std::find(func->getEntryBlock()->getArguments().begin(), func->getEntryBlock()->getArguments().end(), pointer) != func->getEntryBlock()->getArguments().end())) { @@ -63,7 +63,7 @@ void DeadCodeElimination::eliminateDeadStores(Function* func, bool& changed) { std::cout << "=== Dead Store Found ===\n"; SysYPrinter::printInst(storeInst); } - usedelete(storeInst); + SysYIROptUtils::usedelete(storeInst); iter = instrs.erase(iter); } else { ++iter; @@ -85,7 +85,7 @@ void DeadCodeElimination::eliminateDeadLoads(Function* func, bool& changed) { std::cout << "=== Dead Load Binary Unary Found ===\n"; SysYPrinter::printInst(inst); } - usedelete(inst); + SysYIROptUtils::usedelete(inst); iter = instrs.erase(iter); continue; } @@ -114,7 +114,7 @@ void DeadCodeElimination::eliminateDeadAllocas(Function* func, bool& changed) { std::cout << "=== Dead Alloca Found ===\n"; SysYPrinter::printInst(inst); } - usedelete(inst); + SysYIROptUtils::usedelete(inst); iter = instrs.erase(iter); continue; } @@ -183,7 +183,7 @@ void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool& /// 如果 pointer 仅被该 phi 使用,可以删除 ph if (tag) { changed = true; - usedelete(inst); + SysYIROptUtils::usedelete(inst); iter = instrs.erase(iter); continue; } @@ -193,7 +193,7 @@ void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool& auto pointer = memsetInst->getPointer(); if (pointer->getUses().empty()) { changed = true; - usedelete(inst); + SysYIROptUtils::usedelete(inst); iter = instrs.erase(iter); continue; } @@ -234,7 +234,7 @@ void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool& SysYPrinter::printInst(loadInst); SysYPrinter::printInst(nextStore); } - usedelete(loadInst); + SysYIROptUtils::usedelete(loadInst); iter = instrs.erase(iter); // 删除 prevStore 这里是不是可以留给删除无用store处理? // if (prevStore->getUses().empty()) { @@ -256,21 +256,4 @@ void DeadCodeElimination::eliminateDeadRedundantLoadStore(Function* func, bool& } -bool DeadCodeElimination::isGlobal(Value *val){ - auto gval = dynamic_cast(val); - return gval != nullptr; -} - -bool DeadCodeElimination::isArr(Value *val){ - auto aval = dynamic_cast(val); - return aval != nullptr && aval->getNumDims() != 0; -} - -void DeadCodeElimination::usedelete(Instruction *instr){ - for (auto &use1 : instr->getOperands()) { - auto val1 = use1->getValue(); - val1->removeUse(use1); - } -} - } // namespace sysy \ No newline at end of file diff --git a/src/Mem2Reg.cpp b/src/Mem2Reg.cpp index db584ed..fd7a239 100644 --- a/src/Mem2Reg.cpp +++ b/src/Mem2Reg.cpp @@ -75,7 +75,7 @@ auto Mem2Reg::computeValue2Blocks() -> void { // std::cout << std::endl; if (instr->isAlloca()) { - if (!(isArr(instr.get()) || isGlobal(instr.get()))) { + if (!(SysYIROptUtils::isArr(instr.get()) || SysYIROptUtils::isGlobal(instr.get()))) { // std::cout << " Found alloca: "; // printer.printInst(instr.get()); // std::cout << " -> Adding to allocBlocks" << std::endl; @@ -92,7 +92,7 @@ auto Mem2Reg::computeValue2Blocks() -> void { // std::cout << " Store target: "; // printer.printInst(dynamic_cast(val)); - if (!(isArr(val) || isGlobal(val))) { + if (!(SysYIROptUtils::isArr(val) || SysYIROptUtils::isGlobal(val))) { // std::cout << " Adding store to defBlocks for value: "; // printer.printInst(dynamic_cast(instr.get())); // std::cout << std::endl; @@ -108,7 +108,7 @@ auto Mem2Reg::computeValue2Blocks() -> void { // printer.printInst(dynamic_cast(val)); // std::cout << std::endl; - if (!(isArr(val) || isGlobal(val))) { + if (!(SysYIROptUtils::isArr(val) || SysYIROptUtils::isGlobal(val))) { // std::cout << " Adding load to useBlocks for value: "; // printer.printInst(dynamic_cast(val)); // std::cout << std::endl; @@ -199,7 +199,7 @@ auto Mem2Reg::cascade(Instruction *instr, bool &changed, Function *func, BasicBl auto tofind = std::find_if(instrs.begin(), instrs.end(), [&top](const auto &instr) { return instr.get() == top; }); assert(tofind != instrs.end()); - usedelete(tofind->get()); + SysYIROptUtils::usedelete(tofind->get()); instrs.erase(tofind); } } @@ -291,7 +291,7 @@ auto Mem2Reg::preOptimize1() -> void { continue; } - usedelete(tofind->get()); + SysYIROptUtils::usedelete(tofind->get()); bb->getInstructions().erase(tofind); iter = vToAllocB.erase(iter); } else { @@ -334,7 +334,7 @@ auto Mem2Reg::preOptimize1() -> void { std::cout << std::endl; auto valUsedByStore = dynamic_cast((*it)->getOperand(0)); - usedelete(it->get()); + SysYIROptUtils::usedelete(it->get()); if (valUsedByStore != nullptr && valUsedByStore->getUses().size() == 1 && @@ -370,7 +370,7 @@ auto Mem2Reg::preOptimize1() -> void { return instr.get() == val; }); if (tofind != bb->getInstructions().end()) { - usedelete(tofind->get()); + SysYIROptUtils::usedelete(tofind->get()); bb->getInstructions().erase(tofind); } else { std::cerr << "ERROR: Alloca not found in BB!" << std::endl; @@ -423,7 +423,7 @@ auto Mem2Reg::preOptimize2() -> void { for (auto curit = std::next(it); curit != instrs.end();) { if ((*curit)->isLoad() && (*curit)->getOperand(0) == val) { curit->get()->replaceAllUsesWith(propogationVal); - usedelete(curit->get()); + SysYIROptUtils::usedelete(curit->get()); curit = instrs.erase(curit); funcInfo->removeValue2UseBlock(val, block); } else { @@ -454,7 +454,7 @@ auto Mem2Reg::preOptimize2() -> void { for (auto childIter = childInstrs.begin(); childIter != childInstrs.end();) { if ((*childIter)->isLoad() && (*childIter)->getOperand(0) == val) { childIter->get()->replaceAllUsesWith(propogationVal); - usedelete(childIter->get()); + SysYIROptUtils::usedelete(childIter->get()); childIter = childInstrs.erase(childIter); funcInfo->removeValue2UseBlock(val, child); } else { @@ -465,7 +465,7 @@ auto Mem2Reg::preOptimize2() -> void { // 如果对该val的所有load均替换掉了,那么对于该val的defining block中的最后一个define也可以删除了 // 同时该块中前面对于该val的define也变成死代码了,可调用preOptimize1进行删除 if (funcInfo->getUseBlocksByValue(val).empty()) { - usedelete(it->get()); + SysYIROptUtils::usedelete(it->get()); instrs.erase(it); auto change = funcInfo->removeValue2DefBlock(val, block); if (change) { @@ -476,7 +476,7 @@ auto Mem2Reg::preOptimize2() -> void { assert(bb != nullptr); auto tofind = std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(), [val](const auto &instr) { return instr.get() == val; }); - usedelete(tofind->get()); + SysYIROptUtils::usedelete(tofind->get()); bb->getInstructions().erase(tofind); funcInfo->removeValue2AllocBlock(val); } @@ -529,7 +529,7 @@ auto Mem2Reg::preOptimize3() -> void { for (auto curit = std::next(it); curit != last;) { if ((*curit)->isLoad() && (*curit)->getOperand(0) == val) { curit->get()->replaceAllUsesWith(propogationVal); - usedelete(curit->get()); + SysYIROptUtils::usedelete(curit->get()); curit = instrs.erase(curit); funcInfo->removeValue2UseBlock(val, block); } else { @@ -541,14 +541,14 @@ auto Mem2Reg::preOptimize3() -> void { [val](const auto &instr) { return instr == val; }) != func->getEntryBlock()->getArguments().end()) && last == instrs.end()) { - usedelete(it->get()); + SysYIROptUtils::usedelete(it->get()); it = instrs.erase(it); if (funcInfo->removeValue2DefBlock(val, block)) { auto bb = funcInfo->getAllocBlockByValue(val); if (bb != nullptr) { auto tofind = std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(), [val](const auto &instr) { return instr.get() == val; }); - usedelete(tofind->get()); + SysYIROptUtils::usedelete(tofind->get()); bb->getInstructions().erase(tofind); funcInfo->removeValue2AllocBlock(val); } @@ -610,7 +610,7 @@ auto Mem2Reg::rename(BasicBlock *block, std::unordered_map &count, // 对于load指令,变量用最新的那个 if (instr->isLoad()) { auto val = instr->getOperand(0); - if (!(isArr(val) || isGlobal(val))) { + if (!(SysYIROptUtils::isArr(val) || SysYIROptUtils::isGlobal(val))) { if (!stacks[val].empty()) { instr->replaceOperand(0, stacks[val].top()); } @@ -621,7 +621,7 @@ auto Mem2Reg::rename(BasicBlock *block, std::unordered_map &count, if (instr->isAlloca()) { // alloca指令名字不改了,命名就按x,x_1,x_2...来就行 auto val = instr; - if (!(isArr(val) || isGlobal(val))) { + if (!(SysYIROptUtils::isArr(val) || SysYIROptUtils::isGlobal(val))) { ++valPop[val]; stacks[val].push(val); ++count[val]; @@ -629,11 +629,11 @@ auto Mem2Reg::rename(BasicBlock *block, std::unordered_map &count, } else if (instr->isPhi()) { // Phi指令也是一条特殊的define指令 auto val = dynamic_cast(instr)->getMapVal(); - if (!(isArr(val) || isGlobal(val))) { + if (!(SysYIROptUtils::isArr(val) || SysYIROptUtils::isGlobal(val))) { auto i = count[val]; if (i == 0) { // 对还未alloca就有phi的指令的处理,直接删除 - usedelete(iter->get()); + SysYIROptUtils::usedelete(iter->get()); iter = instrs.erase(iter); continue; } @@ -649,7 +649,7 @@ auto Mem2Reg::rename(BasicBlock *block, std::unordered_map &count, } else { // store指令看operand的名字,我们的实现是规定变量在operand的第二位,用一个新的alloca x_i代替 auto val = instr->getOperand(1); - if (!(isArr(val) || isGlobal(val))) { + if (!(SysYIROptUtils::isArr(val) || SysYIROptUtils::isGlobal(val))) { auto i = count[val]; auto newname = dynamic_cast(val)->getName() + "_" + std::to_string(i); auto newalloca = pBuilder->createAllocaInstWithoutInsert(val->getType(), {}, block, newname); @@ -773,29 +773,4 @@ auto Mem2Reg::getPredIndex(BasicBlock *n, BasicBlock *s) -> int { return index; } -/** - * 判断一个value是不是全局变量 - */ -auto Mem2Reg::isGlobal(Value *val) -> bool { - auto gval = dynamic_cast(val); - return gval != nullptr; -} - -/** - * 判断一个value是不是数组 - */ -auto Mem2Reg::isArr(Value *val) -> bool { - auto aval = dynamic_cast(val); - return aval != nullptr && aval->getNumDims() != 0; -} - -/** - * 删除一个指令的operand对应的value的该条use - */ -auto Mem2Reg::usedelete(Instruction *instr) -> void { - for (auto &use : instr->getOperands()) { - auto val = use->getValue(); - val->removeUse(use); - } -} } // namespace sysy diff --git a/src/Reg2Mem.cpp b/src/Reg2Mem.cpp index d44d1c8..70bdd14 100644 --- a/src/Reg2Mem.cpp +++ b/src/Reg2Mem.cpp @@ -103,7 +103,7 @@ void Reg2Mem::DeletePhiInst(){ } // 删除phi指令 auto &instructions = basicBlock->getInstructions(); - usedelete(iter->get()); + SysYIROptUtils::usedelete(iter->get()); iter = instructions.erase(iter); if (basicBlock->getNumInstructions() == 0) { if (basicBlock->getNumSuccessors() == 1) { @@ -119,11 +119,4 @@ void Reg2Mem::DeletePhiInst(){ } } -void Reg2Mem::usedelete(Instruction *instr) { - for (auto &use : instr->getOperands()) { - auto val = use->getValue(); - val->removeUse(use); - } -} - } // namespace sysy diff --git a/src/SysYIROptPre.cpp b/src/SysYIROptPre.cpp index fb05cb7..9eb495c 100644 --- a/src/SysYIROptPre.cpp +++ b/src/SysYIROptPre.cpp @@ -1,4 +1,5 @@ #include "SysYIROptPre.h" +#include "SysYIROptUtils.h" #include #include #include @@ -10,18 +11,6 @@ namespace sysy { -/** - * use删除operand,以免扰乱后续分析 - * instr: 要删除的指令 - */ -void SysYOptPre::usedelete(Instruction *instr) { - for (auto &use : instr->getOperands()) { - Value* val = use->getValue(); - // std::cout << delete << val->getName() << std::endl; - val->removeUse(use); - } -} - // 删除br后的无用指令 void SysYOptPre::SysYDelInstAfterBr() { @@ -34,7 +23,7 @@ void SysYOptPre::SysYDelInstAfterBr() { auto Branchiter = instructions.end(); for (auto iter = instructions.begin(); iter != instructions.end(); ++iter) { if (Branch) - usedelete(iter->get()); + SysYIROptUtils::usedelete(iter->get()); else if ((*iter)->isTerminator()){ Branch = true; Branchiter = iter; @@ -69,7 +58,7 @@ void SysYOptPre::SysYDelInstAfterBr() { } } - +// 合并空基本块 void SysYOptPre::SysYBlockMerge() { auto &functions = pModule->getFunctions(); //std::map> for (auto &function : functions) { @@ -91,12 +80,12 @@ void SysYOptPre::SysYBlockMerge() { auto thelastinstinst = block->end(); (--thelastinstinst); if (thelastinstinst->get()->isUnconditional()) { - usedelete(thelastinstinst->get()); + SysYIROptUtils::usedelete(thelastinstinst->get()); block->getInstructions().erase(thelastinstinst); } else if (thelastinstinst->get()->isConditional()) { // 如果是条件分支,判断条件是否相同,主要优化相同布尔表达式 if (thelastinstinst->get()->getOperand(1)->getName() == thelastinstinst->get()->getOperand(1)->getName()) { - usedelete(thelastinstinst->get()); + SysYIROptUtils::usedelete(thelastinstinst->get()); block->getInstructions().erase(thelastinstinst); } } @@ -170,7 +159,7 @@ void SysYOptPre::SysYDelNoPreBLock() { if (!blockIter->get()->getreachable()) for (auto &iterInst : blockIter->get()->getInstructions()) - usedelete(iterInst.get()); + SysYIROptUtils::usedelete(iterInst.get()); } @@ -303,7 +292,7 @@ void SysYOptPre::SysYDelEmptyBlock() { if (dynamic_cast(thelastinst->get()->getOperand(1)) == dynamic_cast(thelastinst->get()->getOperand(2))) { auto thebrBlock = dynamic_cast(thelastinst->get()->getOperand(1)); - usedelete(thelastinst->get()); + SysYIROptUtils::usedelete(thelastinst->get()); thelastinst = basicBlock->getInstructions().erase(thelastinst); pBuilder->setPosition(basicBlock.get(), basicBlock->end()); pBuilder->createUncondBrInst(thebrBlock, {}); @@ -344,7 +333,7 @@ void SysYOptPre::SysYDelEmptyBlock() { if (dynamic_cast(thelastinst->get()->getOperand(1)) == dynamic_cast(thelastinst->get()->getOperand(2))) { auto thebrBlock = dynamic_cast(thelastinst->get()->getOperand(1)); - usedelete(thelastinst->get()); + SysYIROptUtils::usedelete(thelastinst->get()); thelastinst = basicBlock->getInstructions().erase(thelastinst); pBuilder->setPosition(basicBlock.get(), basicBlock->end()); pBuilder->createUncondBrInst(thebrBlock, {}); @@ -420,7 +409,7 @@ void SysYOptPre::SysYDelEmptyBlock() { } for (auto &iterInst : iter->get()->getInstructions()) - usedelete(iterInst.get()); + SysYIROptUtils::usedelete(iterInst.get()); // 删除不可达基本块的phi指令的操作数 for (auto &succ : iter->get()->getSuccessors()) { int index = 0; diff --git a/src/include/DeadCodeElimination.h b/src/include/DeadCodeElimination.h index 72b9935..9864a2d 100644 --- a/src/include/DeadCodeElimination.h +++ b/src/include/DeadCodeElimination.h @@ -3,6 +3,7 @@ #include "IR.h" #include "SysYIRAnalyser.h" #include "SysYIRPrinter.h" +#include "SysYIROptUtils.h" namespace sysy { @@ -31,9 +32,5 @@ class DeadCodeElimination { void eliminateDeadGlobals(bool& changed); // 消除无用全局变量 void eliminateDeadIndirectiveAllocas(Function* func, bool& changed); // 消除无用间接内存分配(phi节点) void eliminateDeadRedundantLoadStore(Function* func, bool& changed); // 消除冗余加载和存储 - bool isGlobal(Value *val); - bool isArr(Value *val); - void usedelete(Instruction *instr); - }; } // namespace sysy diff --git a/src/include/Mem2Reg.h b/src/include/Mem2Reg.h index 0004708..919886a 100644 --- a/src/include/Mem2Reg.h +++ b/src/include/Mem2Reg.h @@ -8,6 +8,7 @@ #include "IR.h" #include "IRBuilder.h" #include "SysYIRAnalyser.h" +#include "SysYIROptUtils.h" namespace sysy { /** @@ -51,9 +52,6 @@ private: auto getPredIndex(BasicBlock *n, BasicBlock *s) -> int; ///< 获取前驱索引 auto cascade(Instruction *instr, bool &changed, Function *func, BasicBlock *block, std::list> &instrs) -> void; ///< 消除级联关系 - auto isGlobal(Value *val) -> bool; ///< 判断是否是全局变量 - auto isArr(Value *val) -> bool; ///< 判断是否是数组 - auto usedelete(Instruction *instr) -> void; ///< 删除指令相关的value-use-user关系 }; } // namespace sysy diff --git a/src/include/Reg2Mem.h b/src/include/Reg2Mem.h index 6249d71..8eec1b6 100644 --- a/src/include/Reg2Mem.h +++ b/src/include/Reg2Mem.h @@ -2,6 +2,7 @@ #include "IR.h" #include "IRBuilder.h" +#include "SysYIROptUtils.h" namespace sysy { /** @@ -16,8 +17,6 @@ public: Reg2Mem(Module *pMoudle, IRBuilder *pBuilder) : pModule(pMoudle), pBuilder(pBuilder) {} void DeletePhiInst(); - // 删除UD关系, 因为删除了phi指令会修改ud关系 - void usedelete(Instruction *instr); }; } // namespace sysy \ No newline at end of file diff --git a/src/include/SysYIROptPre.h b/src/include/SysYIROptPre.h index 4f0bdca..5cb0b34 100644 --- a/src/include/SysYIROptPre.h +++ b/src/include/SysYIROptPre.h @@ -10,6 +10,11 @@ namespace sysy { // 这些操作可以在SysY IR生成时就完成,但为了简化IR生成过程, // 这里将其放在SysY IR生成后进行预处理 // 同时兼容phi节点的处理,可以再mem2reg后再次调用优化 + +//TODO: 可增加的CFG优化 +// - 简化条件分支(Branch Simplification),如条件恒真/恒假转为直接跳转 +// - 合并连续的跳转指令(Jump Threading)在合并不可达块中似乎已经实现了 +// - 基本块重排序(Block Reordering),提升局部性 class SysYOptPre { private: Module *pModule; @@ -31,7 +36,6 @@ class SysYOptPre { void SysYBlockMerge(); // 合并基本块(主要针对嵌套if while的exit块, // 也可以修改IR生成实现回填机制 void SysYAddReturn(); // 添加return指令(主要针对Void函数) - void usedelete(Instruction *instr); // use删除 }; } // namespace sysy diff --git a/src/include/SysYIROptUtils.h b/src/include/SysYIROptUtils.h new file mode 100644 index 0000000..d2d2e55 --- /dev/null +++ b/src/include/SysYIROptUtils.h @@ -0,0 +1,33 @@ +#pragma once + +#include "IR.h" + +namespace sysy { + +// 优化工具类,包含一些通用的优化方法 +// 这些方法可以在不同的优化 pass 中复用 +// 例如:删除use关系,判断是否是全局变量等 +class SysYIROptUtils{ + +public: + // 删除use关系 + static void usedelete(Instruction *instr) { + for (auto &use : instr->getOperands()) { + Value* val = use->getValue(); + val->removeUse(use); + } + } + + // 判断是否是全局变量 + static bool isGlobal(Value *val) { + auto gval = dynamic_cast(val); + return gval != nullptr; + } + // 判断是否是数组 + static bool isArr(Value *val) { + auto aval = dynamic_cast(val); + return aval != nullptr && aval->getNumDims() != 0; + } +}; + +}// namespace sysy \ No newline at end of file