diff --git a/src/backend/RISCv64/Optimize/Peephole.cpp b/src/backend/RISCv64/Optimize/Peephole.cpp index 936af92..0571f50 100644 --- a/src/backend/RISCv64/Optimize/Peephole.cpp +++ b/src/backend/RISCv64/Optimize/Peephole.cpp @@ -634,6 +634,22 @@ void PeepholeOptimizer::runOnMachineFunction(MachineFunction *mfunc) { } } } + // 8. 消除无用移动指令: mv a, a -> (删除) + else if (mi1->getOpcode() == RVOpcodes::MV && + mi1->getOperands().size() == 2) { + if (mi1->getOperands()[0]->getKind() == MachineOperand::KIND_REG && + mi1->getOperands()[1]->getKind() == MachineOperand::KIND_REG) { + auto *dst = static_cast(mi1->getOperands()[0].get()); + auto *src = static_cast(mi1->getOperands()[1].get()); + + // 检查源和目标寄存器是否相同 + if (areRegsEqual(dst, src)) { + // 删除这条无用指令 + instrs.erase(instrs.begin() + i); + changed = true; + } + } + } // 根据是否发生变化调整遍历索引 if (!changed) { diff --git a/src/include/midend/Pass/Optimize/TailCallOpt.h b/src/include/midend/Pass/Optimize/TailCallOpt.h new file mode 100644 index 0000000..5d258ed --- /dev/null +++ b/src/include/midend/Pass/Optimize/TailCallOpt.h @@ -0,0 +1,39 @@ +#pragma once + +#include "Pass.h" +#include "Dom.h" +#include "Loop.h" + +namespace sysy { + +/** + * @class TailCallOpt + * @brief 优化尾调用的中端优化通道。 + * + * 该类实现了一个针对函数级别的尾调用优化的优化通道(OptimizationPass)。 + * 通过分析和转换 IR(中间表示),将可优化的尾调用转换为更高效的形式, + * 以减少函数调用的开销,提升程序性能。 + * + * @note 需要传入 IRBuilder 指针用于 IR 构建和修改。 + * + * @method runOnFunction + * 对指定函数进行尾调用优化。 + * + * @method getPassID + * 获取当前优化通道的唯一标识符。 + * + * @method getAnalysisUsage + * 指定该优化通道所依赖和失效的分析集合。 + */ +class TailCallOpt : public OptimizationPass { +private: + IRBuilder* builder; +public: + TailCallOpt(IRBuilder* builder) : OptimizationPass("TailCallOpt", Granularity::Function), builder(builder) {} + static void *ID; + bool runOnFunction(Function *F, AnalysisManager &AM) override; + void *getPassID() const override { return &ID; } + void getAnalysisUsage(std::set &analysisDependencies, std::set &analysisInvalidations) const override; +}; + +} // namespace sysy diff --git a/src/midend/CMakeLists.txt b/src/midend/CMakeLists.txt index 8243a63..73bafde 100644 --- a/src/midend/CMakeLists.txt +++ b/src/midend/CMakeLists.txt @@ -25,6 +25,7 @@ add_library(midend_lib STATIC Pass/Optimize/GlobalStrengthReduction.cpp Pass/Optimize/BuildCFG.cpp Pass/Optimize/LargeArrayToGlobal.cpp + Pass/Optimize/TailCallOpt.cpp ) # 包含中端模块所需的头文件路径 diff --git a/src/midend/Pass/Optimize/TailCallOpt.cpp b/src/midend/Pass/Optimize/TailCallOpt.cpp new file mode 100644 index 0000000..df2d0aa --- /dev/null +++ b/src/midend/Pass/Optimize/TailCallOpt.cpp @@ -0,0 +1,125 @@ +#include "TailCallOpt.h" +#include "IR.h" +#include "IRBuilder.h" +#include "SysYIROptUtils.h" +#include +// #include +#include + +namespace sysy { + +void *TailCallOpt::ID = (void *)&TailCallOpt::ID; + +void TailCallOpt::getAnalysisUsage(std::set &analysisDependencies, std::set &analysisInvalidations) const { + analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); + analysisInvalidations.insert(&LoopAnalysisPass::ID); +} + +bool TailCallOpt::runOnFunction(Function *F, AnalysisManager &AM) { + std::vector tailCallInsts; + // 遍历函数的所有基本块 + for (auto &bb_ptr : F->getBasicBlocks()) { + auto BB = bb_ptr.get(); + if (BB->getInstructions().empty()) continue; // 跳过空基本块 + + auto term_iter = BB->terminator(); + if (term_iter == BB->getInstructions().end()) continue; // 没有终结指令则跳过 + auto term = (*term_iter).get(); + + if (!term || !term->isReturn()) continue; // 不是返回指令则跳过 + auto retInst = static_cast(term); + + Instruction *prevInst = nullptr; + if (BB->getInstructions().size() > 1) { + auto it = term_iter; + --it; // 获取返回指令前的指令 + prevInst = (*it).get(); + } + + if (!prevInst || !prevInst->isCall()) continue; // 前一条不是调用指令则跳过 + auto callInst = static_cast(prevInst); + + // 检查是否为尾递归调用:被调用函数与当前函数相同且返回值与调用结果匹配 + if (callInst->getCallee() == F) { + // 对于尾递归,返回值应为调用结果或为 void 类型 + if (retInst->getReturnValue() == callInst || + (retInst->getReturnValue() == nullptr && callInst->getType()->isVoid())) { + tailCallInsts.push_back(callInst); + } + } + } + + if (tailCallInsts.empty()) { + return false; + } + + // 创建一个新的入口基本块,作为循环的前置块 + auto original_entry = F->getEntryBlock(); + auto new_entry = F->addBasicBlock("tco.entry"); + auto loop_header = F->addBasicBlock("tco.loop_header"); + + // 将原入口块中的所有指令移动到循环头块 + loop_header->getInstructions().splice(loop_header->end(), original_entry->getInstructions()); + original_entry->setName("tco.pre_header"); + + // 为函数参数创建 phi 节点 + builder->setPosition(loop_header, loop_header->begin()); + std::vector phis; + auto original_args = F->getArguments(); + for (auto &arg : original_args) { + auto phi = builder->createPhiInst(arg->getType(), {}, {}, "tco.phi."+arg->getName()); + phis.push_back(phi); + } + + // 用 phi 节点替换所有原始参数的使用 + for (size_t i = 0; i < original_args.size(); ++i) { + original_args[i]->replaceAllUsesWith(phis[i]); + } + + // 设置 phi 节点的输入值 + for (size_t i = 0; i < phis.size(); ++i) { + phis[i]->addIncoming(original_args[i], new_entry); + } + + // 连接各个基本块 + builder->setPosition(original_entry, original_entry->end()); + builder->createUncondBrInst(new_entry); + original_entry->addSuccessor(new_entry); + + builder->setPosition(new_entry, new_entry->end()); + builder->createUncondBrInst(loop_header); + new_entry->addSuccessor(loop_header); + loop_header->addPredecessor(new_entry); + + // 处理每一个尾递归调用 + for (auto callInst : tailCallInsts) { + auto tail_call_block = callInst->getParent(); + + // 收集尾递归调用的参数 + auto args_range = callInst->getArguments(); + std::vector args; + std::transform(args_range.begin(), args_range.end(), std::back_inserter(args), + [](auto& use_ptr){ return use_ptr->getValue(); }); + + // 用新的参数值更新 phi 节点 + for (size_t i = 0; i < phis.size(); ++i) { + phis[i]->addIncoming(args[i], tail_call_block); + } + + // 移除原有的调用和返回指令 + auto term_iter = tail_call_block->terminator(); + SysYIROptUtils::usedelete(term_iter); + auto call_iter = tail_call_block->findInstIterator(callInst); + SysYIROptUtils::usedelete(call_iter); + + // 添加跳转回循环头块的分支指令 + builder->setPosition(tail_call_block, tail_call_block->end()); + builder->createUncondBrInst(loop_header); + tail_call_block->addSuccessor(loop_header); + loop_header->addPredecessor(tail_call_block); + } + + return true; +} + +} // namespace sysy diff --git a/src/midend/Pass/Pass.cpp b/src/midend/Pass/Pass.cpp index aee29b0..f711ba6 100644 --- a/src/midend/Pass/Pass.cpp +++ b/src/midend/Pass/Pass.cpp @@ -19,6 +19,7 @@ #include "LoopStrengthReduction.h" #include "InductionVariableElimination.h" #include "GlobalStrengthReduction.h" +#include "TailCallOpt.h" #include "Pass.h" #include #include @@ -81,6 +82,7 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR registerOptimizationPass(builderIR); registerOptimizationPass(builderIR); + registerOptimizationPass(builderIR); registerOptimizationPass(builderIR); @@ -139,6 +141,16 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR this->addPass(&GVN::ID); this->run(); + this->clearPasses(); + this->addPass(&TailCallOpt::ID); + this->run(); + + if(DEBUG) { + std::cout << "=== IR After TailCallOpt ===\n"; + SysYPrinter printer(moduleIR); + printer.printIR(); + } + if(DEBUG) { std::cout << "=== IR After GVN Optimizations ===\n"; printPasses(); @@ -192,9 +204,9 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR printPasses(); } - // this->clearPasses(); - // this->addPass(&Reg2Mem::ID); - // this->run(); + this->clearPasses(); + this->addPass(&Reg2Mem::ID); + this->run(); if(DEBUG) { std::cout << "=== IR After Reg2Mem Optimizations ===\n";