[midend-BuildCFG]新增BuildCFG优化通道,实现控制流图的构建与分析
This commit is contained in:
33
src/include/midend/Pass/Optimize/BuildCFG.h
Normal file
33
src/include/midend/Pass/Optimize/BuildCFG.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "Pass.h"
|
||||
#include "IR.h"
|
||||
#include "Instruction.h"
|
||||
#include <queue>
|
||||
#include <set>
|
||||
|
||||
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<void *> &analysisDependencies,
|
||||
std::set<void *> &analysisInvalidations) override;
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
121
src/midend/Pass/Optimize/BuildCFG.cpp
Normal file
121
src/midend/Pass/Optimize/BuildCFG.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
#include "BuildCFG.h"
|
||||
#include "Instruction.h"
|
||||
#include "IR.h"
|
||||
#include "Liveness.h" // 包含活跃性分析的头文件以引用其ID
|
||||
#include "Dom.h" // 包含支配树分析的头文件以引用其ID
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
char BuildCFG::ID = 0;
|
||||
|
||||
// 声明Pass的分析使用
|
||||
void BuildCFG::getAnalysisUsage(std::set<void *> &analysisDependencies,
|
||||
std::set<void *> &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<BrInst *>(termInst)) {
|
||||
// 无条件跳转
|
||||
if (brInst->getNumOperands() == 1) {
|
||||
BasicBlock *succ = dynamic_cast<BasicBlock *>(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<BasicBlock *>(brInst->getOperand(1));
|
||||
BasicBlock *falseSucc = dynamic_cast<BasicBlock *>(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<RetInst *>(termInst)) {
|
||||
// RetInst没有后继,无需处理
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 额外处理:可达性分析,标记不可达基本块
|
||||
std::queue<BasicBlock*> q;
|
||||
std::set<BasicBlock*> 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
|
||||
@ -6,6 +6,7 @@
|
||||
#include "Mem2Reg.h"
|
||||
#include "Reg2Mem.h"
|
||||
#include "SCCP.h"
|
||||
#include "BuildCFG.h"
|
||||
#include "Pass.h"
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
@ -39,6 +40,7 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
||||
registerAnalysisPass<sysy::LivenessAnalysisPass>();
|
||||
|
||||
// 注册优化遍
|
||||
registerOptimizationPass<BuildCFG>(builderIR);
|
||||
registerOptimizationPass<SysYDelInstAfterBrPass>();
|
||||
registerOptimizationPass<SysYDelNoPreBLockPass>();
|
||||
registerOptimizationPass<SysYBlockMergePass>();
|
||||
@ -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);
|
||||
|
||||
Reference in New Issue
Block a user