[midend]loop分析构建

This commit is contained in:
rain2133
2025-08-02 17:42:43 +08:00
parent e48cddab9f
commit aa7f2bb0f5
2 changed files with 334 additions and 0 deletions

View File

@@ -0,0 +1,179 @@
#include "Dom.h" // 确保包含 DominatorTreeAnalysisPass 的定义
#include "Loop.h"
#include <iostream>
namespace sysy {
// 定义 Pass 的唯一 ID
void *LoopAnalysisPass::ID = (void *)&LoopAnalysisPass::ID;
bool LoopAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
if (F->getBasicBlocks().empty()) {
CurrentResult = std::make_unique<LoopAnalysisResult>(F);
return false; // 空函数,没有循环
}
if (DEBUG)
std::cout << "Running LoopAnalysisPass on function: " << F->getName() << std::endl;
// 获取支配树分析结果
// 这是循环分析的关键依赖
DominatorTree *DT = AM.getAnalysisResult<DominatorTree, DominatorTreeAnalysisPass>(F);
if (!DT) {
// 无法获取支配树,无法进行循环分析
std::cerr << "Error: DominatorTreeAnalysisResult not available for function " << F->getName() << std::endl;
CurrentResult = std::make_unique<LoopAnalysisResult>(F);
return false;
}
CurrentResult = std::make_unique<LoopAnalysisResult>(F);
bool changed = false; // 循环分析本身不修改IR所以通常返回false
// 步骤 1: 识别回边和对应的自然循环
// 回边 (N -> D) 定义D 支配 N
std::vector<std::pair<BasicBlock *, BasicBlock *>> backEdges;
for (auto &BB : F->getBasicBlocks()) {
for (BasicBlock *Succ : BB->getSuccessors()) {
if (DT->getDominators(BB.get()) && DT->getDominators(BB.get())->count(Succ)) {
// Succ 支配 BB所以 (BB -> Succ) 是一条回边
backEdges.push_back({BB.get(), Succ});
}
}
}
// 步骤 2: 为每条回边构建自然循环
for (auto &edge : backEdges) {
BasicBlock *N = edge.first; // 回边的尾部
BasicBlock *D = edge.second; // 回边的头部 (循环头)
// 创建新的 Loop 对象
std::unique_ptr<Loop> currentLoop = std::make_unique<Loop>(D);
// 收集循环体块:从 N 逆向遍历到 D (不包括中间的 D)
std::set<BasicBlock *> loopBlocks; // 临时存储循环块
std::queue<BasicBlock *> q;
q.push(N);
loopBlocks.insert(N); // 回边的尾部首先是循环块
while (!q.empty()) {
BasicBlock *current = q.front();
q.pop();
for (BasicBlock *pred : current->getPredecessors()) {
if (pred == D) {
// 找到循环头,将其加入循环块集合,但不继续逆向遍历它的前驱,
// 因为我们是从 N 到 D 的路径D 已经是终点。
loopBlocks.insert(D);
continue;
}
// 如果是 D 自身,并且它已经在循环块集合中,也不再处理
if (loopBlocks.find(pred) == loopBlocks.end()) {
loopBlocks.insert(pred);
q.push(pred);
}
}
}
// 将收集到的块添加到 Loop 对象中
for (BasicBlock *loopBB : loopBlocks) {
currentLoop->addBlock(loopBB);
}
// 步骤 3: 识别循环出口块 (Exit Blocks)
for (BasicBlock *loopBB : loopBlocks) {
for (BasicBlock *succ : loopBB->getSuccessors()) {
if (loopBlocks.find(succ) == loopBlocks.end()) {
// 如果后继不在循环体内,则 loopBB 是一个出口块
currentLoop->addExitBlock(loopBB);
}
}
}
// 步骤 4: 识别循环前置块 (Pre-Header) - 您的前端已做很多工作,这里是确认和规范化
BasicBlock *candidatePreHeader = nullptr;
int externalPredecessorCount = 0;
for (BasicBlock *predOfHeader : D->getPredecessors()) {
if (loopBlocks.find(predOfHeader) == loopBlocks.end()) {
// 如果前驱不在循环体内,则是一个外部前驱
externalPredecessorCount++;
candidatePreHeader = predOfHeader;
}
}
if (externalPredecessorCount == 1) {
currentLoop->setPreHeader(candidatePreHeader);
} else {
// TODO: 如果有多个外部前驱或没有,这里应该插入新的基本块作为前置块,
// 并调整控制流。这会修改 IR需要返回 true。
// 目前,我们只是简单地不设置 preHeader。
}
CurrentResult->addLoop(std::move(currentLoop));
}
// 步骤 5: 处理嵌套循环 (确定父子关系)
// 遍历所有已识别的循环,确定它们的嵌套关系
const auto &allLoops = CurrentResult->getAllLoops();
for (const auto &outerLoop_ptr : allLoops) {
Loop *outerLoop = outerLoop_ptr.get();
for (const auto &innerLoop_ptr : allLoops) {
Loop *innerLoop = innerLoop_ptr.get();
// 一个循环不能是它自己的父循环
if (outerLoop == innerLoop) {
continue;
}
// 判断 innerLoop 是否嵌套在 outerLoop 内
// 条件innerLoop 的头被 outerLoop 的头支配,且 innerLoop 的所有块都在 outerLoop 内
if (DT->getDominators(innerLoop->getHeader()) &&
DT->getDominators(innerLoop->getHeader())->count(outerLoop->getHeader())) {
bool allInnerBlocksInOuter = true;
for (BasicBlock *innerBB : innerLoop->getBlocks()) {
if (!outerLoop->contains(innerBB)) {
allInnerBlocksInOuter = false;
break;
}
}
if (allInnerBlocksInOuter) {
// 找到了一个嵌套关系,但还需要确定是直接嵌套还是多层嵌套
// 简单方法:如果 innerLoop 没有其他父循环,或者这个 outerLoop 是其最近的父循环
// 更精确的做法是找支配 innerLoop 头的,且被 innerLoop 头支配的最近的循环头
// 简单的直接嵌套判断:如果 innerLoop 还没有父循环,或者当前 outerLoop 比现有父循环更“紧密”
if (!innerLoop->getParentLoop()) { // 还没设置父循环
innerLoop->setParentLoop(outerLoop);
outerLoop->addNestedLoop(innerLoop);
} else {
// 如果 innerLoop 已经有父循环,判断 outerLoop 是否是更直接的父循环
// (outerLoop 的头是否支配 innerLoop->getParentLoop() 的头)
if (DT->getDominators(innerLoop->getParentLoop()->getHeader()) &&
DT->getDominators(innerLoop->getParentLoop()->getHeader())->count(outerLoop->getHeader())) {
// outerLoop 支配 innerLoop 现有父循环的头,说明 outerLoop 更外层
// 保持现有父循环不变
} else if (DT->getDominators(outerLoop->getHeader()) &&
DT->getDominators(outerLoop->getHeader())->count(innerLoop->getParentLoop()->getHeader())) {
// outerLoop 被 innerLoop 现有父循环的头支配,说明 outerLoop 更内层
// 这种情况不应该发生,因为我们已经判断 outerLoop 支配 innerLoop 的头
// 可能是 bug 或复杂情况,需要进一步分析
} else {
// 否则outerLoop 可能是更直接的父循环,需要更新
// TODO 用更复杂的算法来构建循环树
// innerLoop->getParentLoop()->NestedLoops.erase(
// std::remove(innerLoop->getParentLoop()->NestedLoops.begin(),
// innerLoop->getParentLoop()->NestedLoops.Loops.end(), innerLoop),
// innerLoop->getParentLoop()->NestedLoops.end());
// innerLoop->setParentLoop(outerLoop);
outerLoop->addNestedLoop(innerLoop);
}
}
}
}
}
}
return changed;
}
} // namespace sysy