From a1cf60c420f17386232deaf3c7194a9fa1aac468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AD=AA=E6=AF=94=E6=AD=AA=E6=AF=94?= <15734459+yzllzyaaa@user.noreply.gitee.com> Date: Sat, 2 Aug 2025 22:48:21 +0800 Subject: [PATCH] =?UTF-8?q?[midend-BuildCFG]=E6=96=B0=E5=A2=9EBuildCFG?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=80=9A=E9=81=93=EF=BC=8C=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E6=B5=81=E5=9B=BE=E7=9A=84=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E4=B8=8E=E5=88=86=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/midend/Pass/Optimize/BuildCFG.h | 33 ++++++ src/midend/Pass/Optimize/BuildCFG.cpp | 121 ++++++++++++++++++++ src/midend/Pass/Pass.cpp | 11 ++ 3 files changed, 165 insertions(+) create mode 100644 src/include/midend/Pass/Optimize/BuildCFG.h create mode 100644 src/midend/Pass/Optimize/BuildCFG.cpp diff --git a/src/include/midend/Pass/Optimize/BuildCFG.h b/src/include/midend/Pass/Optimize/BuildCFG.h new file mode 100644 index 0000000..4054c54 --- /dev/null +++ b/src/include/midend/Pass/Optimize/BuildCFG.h @@ -0,0 +1,33 @@ +#pragma once + +#include "Pass.h" +#include "IR.h" +#include "Instruction.h" +#include +#include + +namespace sysy { + +class DominatorTreeAnalysisPass; +class LivenessAnalysisPass; + +class BuildCFG : public OptimizationPass { +public: + // Pass的唯一ID,用于PassRegistry + static char ID; + + BuildCFG() : OptimizationPass("BuildCFG", Pass::Granularity::Function, Pass::PassKind::Optimization) {} + + // 重载 runOnFunction 方法,实现具体的优化逻辑 + bool runOnFunction(Function *F, AnalysisManager& AM) override; + + // 提供PassID + void *getPassID() const override { return &ID; } + + // 声明Pass的分析使用 + // BuildCFG不依赖任何分析,但会使其他依赖CFG的分析失效 + void getAnalysisUsage(std::set &analysisDependencies, + std::set &analysisInvalidations) override; +}; + +} // namespace sysy \ No newline at end of file diff --git a/src/midend/Pass/Optimize/BuildCFG.cpp b/src/midend/Pass/Optimize/BuildCFG.cpp new file mode 100644 index 0000000..823d126 --- /dev/null +++ b/src/midend/Pass/Optimize/BuildCFG.cpp @@ -0,0 +1,121 @@ +#include "BuildCFG.h" +#include "Instruction.h" +#include "IR.h" +#include "Liveness.h" // 包含活跃性分析的头文件以引用其ID +#include "Dom.h" // 包含支配树分析的头文件以引用其ID +#include +#include +#include + +namespace sysy { + +char BuildCFG::ID = 0; + +// 声明Pass的分析使用 +void BuildCFG::getAnalysisUsage(std::set &analysisDependencies, + std::set &analysisInvalidations) { + // BuildCFG不依赖其他分析 + // analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); // 错误的例子 + + // BuildCFG会使所有依赖于CFG的分析结果失效,所以它必须声明这些失效 + analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); + analysisInvalidations.insert(&LivenessAnalysisPass::ID); +} + +bool BuildCFG::runOnFunction(Function *F, AnalysisManager& AM) { + if (DEBUG) { + std::cout << "Running BuildCFG pass on function: " << F->getName() << std::endl; + } + + bool changed = false; + + // 1. 清空所有基本块的前驱和后继列表 + for (auto &bb : *F) { + bb->predecessors.clear(); + bb->successors.clear(); + } + + // 2. 遍历每个基本块,重建CFG + for (auto &bb : *F) { + // 获取基本块的最后一条指令 + Instruction *termInst = bb->getTerminator(); + + // 确保基本块有终结指令 + if (!termInst) { + continue; + } + + // 根据终结指令类型,建立前驱后继关系 + if (auto brInst = dynamic_cast(termInst)) { + // 无条件跳转 + if (brInst->getNumOperands() == 1) { + BasicBlock *succ = dynamic_cast(brInst->getOperand(0)); + assert(succ && "Branch instruction's target must be a BasicBlock"); + + bb->successors.push_back(succ); + succ->predecessors.push_back(bb.get()); + changed = true; + + // 条件跳转 + } else if (brInst->getNumOperands() == 3) { + BasicBlock *trueSucc = dynamic_cast(brInst->getOperand(1)); + BasicBlock *falseSucc = dynamic_cast(brInst->getOperand(2)); + + assert(trueSucc && falseSucc && "Branch instruction's targets must be BasicBlocks"); + + bb->successors.push_back(trueSucc); + trueSucc->predecessors.push_back(bb.get()); + + bb->successors.push_back(falseSucc); + falseSucc->predecessors.push_back(bb.get()); + changed = true; + } + } else if (auto retInst = dynamic_cast(termInst)) { + // RetInst没有后继,无需处理 + // ... + } + } + + // 3. 额外处理:可达性分析,标记不可达基本块 + std::queue q; + std::set visited; + + // 默认所有块不可达 + for (auto &bb : *F) { + bb->setreachableFalse(); + } + + // 从函数入口基本块开始 + BasicBlock* entryBB = F->getEntryBlock(); + if (entryBB) { + q.push(entryBB); + visited.insert(entryBB); + entryBB->setreachableTrue(); + } + + // 广度优先搜索 (BFS) 遍历所有可达的基本块 + while (!q.empty()) { + BasicBlock* currentBB = q.front(); + q.pop(); + + for (auto& succ : currentBB->successors) { + if (visited.find(succ) == visited.end()) { + q.push(succ); + visited.insert(succ); + succ->setreachableTrue(); + } + } + } + + // 将未访问到的基本块标记为不可达 + for (auto& bb : *F) { + if (visited.find(bb.get()) == visited.end()) { + bb->setreachableFalse(); + changed = true; // 发现不可达块,视为改变 + } + } + + return changed; +} + +} // namespace sysy \ No newline at end of file diff --git a/src/midend/Pass/Pass.cpp b/src/midend/Pass/Pass.cpp index f4ec5ab..c293853 100644 --- a/src/midend/Pass/Pass.cpp +++ b/src/midend/Pass/Pass.cpp @@ -6,6 +6,7 @@ #include "Mem2Reg.h" #include "Reg2Mem.h" #include "SCCP.h" +#include "BuildCFG.h" #include "Pass.h" #include #include @@ -39,6 +40,7 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR registerAnalysisPass(); // 注册优化遍 + registerOptimizationPass(builderIR); registerOptimizationPass(); registerOptimizationPass(); registerOptimizationPass(); @@ -58,6 +60,15 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR if (DEBUG) std::cout << "Applying -O1 optimizations.\n"; if (DEBUG) std::cout << "--- Running custom optimization sequence ---\n"; + if(DEBUG) { + std::cout << "=== IR Before CFGOpt Optimizations ===\n"; + printPasses(); + } + + this->clearPasses(); + this->addPass(&&BuildCFG::ID); + this->run(); + this->clearPasses(); this->addPass(&SysYDelInstAfterBrPass::ID); this->addPass(&SysYDelNoPreBLockPass::ID);