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 1/2] =?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); From 22cf18a1d649a8837161789b317e151863c8f0b5 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Sun, 3 Aug 2025 16:14:31 +0800 Subject: [PATCH 2/2] =?UTF-8?q?[midend-BuildCFG]=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/include/midend/Pass/Optimize/BuildCFG.h | 25 +-- src/midend/CMakeLists.txt | 1 + src/midend/Pass/Optimize/BuildCFG.cpp | 160 ++++++++------------ src/midend/Pass/Pass.cpp | 9 +- 4 files changed, 71 insertions(+), 124 deletions(-) diff --git a/src/include/midend/Pass/Optimize/BuildCFG.h b/src/include/midend/Pass/Optimize/BuildCFG.h index 4054c54..a7fb6cb 100644 --- a/src/include/midend/Pass/Optimize/BuildCFG.h +++ b/src/include/midend/Pass/Optimize/BuildCFG.h @@ -1,33 +1,20 @@ #pragma once -#include "Pass.h" #include "IR.h" -#include "Instruction.h" +#include "Pass.h" #include #include namespace sysy { -class DominatorTreeAnalysisPass; -class LivenessAnalysisPass; - class BuildCFG : public OptimizationPass { public: - // Pass的唯一ID,用于PassRegistry - static char ID; + static void *ID; + BuildCFG() : OptimizationPass("BuildCFG", Granularity::Function) {} + bool runOnFunction(Function *F, AnalysisManager &AM) override; + void getAnalysisUsage(std::set &analysisDependencies, std::set &analysisInvalidations) const override; + void *getPassID() const override { return &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/CMakeLists.txt b/src/midend/CMakeLists.txt index 3532818..f944a3c 100644 --- a/src/midend/CMakeLists.txt +++ b/src/midend/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(midend_lib STATIC Pass/Optimize/Reg2Mem.cpp Pass/Optimize/SysYIRCFGOpt.cpp Pass/Optimize/SCCP.cpp + Pass/Optimize/BuildCFG.cpp ) # 包含中端模块所需的头文件路径 diff --git a/src/midend/Pass/Optimize/BuildCFG.cpp b/src/midend/Pass/Optimize/BuildCFG.cpp index 823d126..07cdd4e 100644 --- a/src/midend/Pass/Optimize/BuildCFG.cpp +++ b/src/midend/Pass/Optimize/BuildCFG.cpp @@ -1,121 +1,79 @@ #include "BuildCFG.h" -#include "Instruction.h" -#include "IR.h" -#include "Liveness.h" // 包含活跃性分析的头文件以引用其ID -#include "Dom.h" // 包含支配树分析的头文件以引用其ID +#include "Dom.h" +#include "Liveness.h" #include #include #include namespace sysy { -char BuildCFG::ID = 0; +void *BuildCFG::ID = (void *)&BuildCFG::ID; // 定义唯一的 Pass ID // 声明Pass的分析使用 -void BuildCFG::getAnalysisUsage(std::set &analysisDependencies, - std::set &analysisInvalidations) { - // BuildCFG不依赖其他分析 - // analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); // 错误的例子 +void BuildCFG::getAnalysisUsage(std::set &analysisDependencies, std::set &analysisInvalidations) const { + // BuildCFG不依赖其他分析 + // analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); // 错误的例子 - // BuildCFG会使所有依赖于CFG的分析结果失效,所以它必须声明这些失效 - analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); - analysisInvalidations.insert(&LivenessAnalysisPass::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 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->getBasicBlocks()) { + bb->clearPredecessors(); + bb->clearSuccessors(); + } + + // 2. 遍历每个基本块,重建CFG + for (auto &bb : F->getBasicBlocks()) { + // 获取基本块的最后一条指令 + auto &inst = *bb->terminator(); + Instruction *termInst = inst.get(); + // 确保基本块有终结指令 + if (!termInst) { + continue; } - bool changed = false; + // 根据终结指令类型,建立前驱后继关系 + if (termInst->isBranch()) { + // 无条件跳转 + if (termInst->isUnconditional()) { + auto brInst = dynamic_cast(termInst); + BasicBlock *succ = dynamic_cast(brInst->getBlock()); + assert(succ && "Branch instruction's target must be a BasicBlock"); + bb->addSuccessor(succ); + succ->addPredecessor(bb.get()); + changed = true; - // 1. 清空所有基本块的前驱和后继列表 - for (auto &bb : *F) { - bb->predecessors.clear(); - bb->successors.clear(); + // 条件跳转 + } else if (termInst->isConditional()) { + auto brInst = dynamic_cast(termInst); + BasicBlock *trueSucc = dynamic_cast(brInst->getThenBlock()); + BasicBlock *falseSucc = dynamic_cast(brInst->getElseBlock()); + + assert(trueSucc && falseSucc && "Branch instruction's targets must be BasicBlocks"); + + bb->addSuccessor(trueSucc); + trueSucc->addPredecessor(bb.get()); + bb->addSuccessor(falseSucc); + falseSucc->addPredecessor(bb.get()); + changed = true; + } + } else if (auto retInst = dynamic_cast(termInst)) { + // RetInst没有后继,无需处理 + // ... } + } - // 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; + 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 c293853..c2c8371 100644 --- a/src/midend/Pass/Pass.cpp +++ b/src/midend/Pass/Pass.cpp @@ -36,11 +36,12 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR 3. 添加优化passid */ // 注册分析遍 - registerAnalysisPass(); - registerAnalysisPass(); + registerAnalysisPass(); + registerAnalysisPass(); // 注册优化遍 - registerOptimizationPass(builderIR); + registerOptimizationPass(); + registerOptimizationPass(); registerOptimizationPass(); registerOptimizationPass(); @@ -66,7 +67,7 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR } this->clearPasses(); - this->addPass(&&BuildCFG::ID); + this->addPass(&BuildCFG::ID); this->run(); this->clearPasses();