[midend-LoopAnalysis]增加维护循环层级的逻辑,修改父子循环关系求解的逻辑。

This commit is contained in:
rain2133
2025-08-03 15:22:18 +08:00
parent 1c7c85dd2f
commit ef9d7c4d03
2 changed files with 99 additions and 54 deletions

View File

@@ -60,7 +60,7 @@ public:
void setParentLoop(Loop *loop) { ParentLoop = loop; }
void addNestedLoop(Loop *loop) { NestedLoops.push_back(loop); }
void setLoopLevel(int level) { Level = level; }
void clearNestedLoops() { NestedLoops.clear(); }
private:
BasicBlock *Header; // 循环头基本块
std::set<BasicBlock *> LoopBlocks; // 循环体包含的基本块集合
@@ -119,6 +119,8 @@ public:
// --- 供 LoopAnalysisPass 内部调用的方法,用于构建 LoopAnalysisResult 对象 ---
void addOutermostLoop(Loop *loop) { OutermostLoops.push_back(loop); }
void addInnermostLoop(Loop *loop) { InnermostLoops.push_back(loop); }
void clearOutermostLoops() { OutermostLoops.clear(); }
void clearInnermostLoops() { InnermostLoops.clear(); }
private:
Function *AssociatedFunction; // 结果关联的函数

View File

@@ -1,6 +1,8 @@
// Loop.cpp (完整内容,包含所有修改)
#include "Dom.h" // 确保包含 DominatorTreeAnalysisPass 的定义
#include "Loop.h"
#include "Loop.h" //
#include <iostream>
#include <queue> // 用于 BFS 遍历设置循环层级
namespace sysy {
@@ -33,10 +35,11 @@ bool LoopAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
// 回边 (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)) {
auto Blcok = BB.get();
for (BasicBlock *Succ : Blcok->getSuccessors()) {
if (DT->getDominators(Blcok) && DT->getDominators(Blcok)->count(Succ)) {
// Succ 支配 BB所以 (BB -> Succ) 是一条回边
backEdges.push_back({BB.get(), Succ});
backEdges.push_back({Blcok, Succ});
}
}
}
@@ -94,7 +97,8 @@ bool LoopAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
BasicBlock *candidatePreHeader = nullptr;
int externalPredecessorCount = 0;
for (BasicBlock *predOfHeader : D->getPredecessors()) {
if (loopBlocks.find(predOfHeader) == loopBlocks.end()) {
// 使用 currentLoop->contains() 来检查前驱是否在循环体内
if (!currentLoop->contains(predOfHeader)) {
// 如果前驱不在循环体内,则是一个外部前驱
externalPredecessorCount++;
candidatePreHeader = predOfHeader;
@@ -104,6 +108,8 @@ bool LoopAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
if (externalPredecessorCount == 1) {
currentLoop->setPreHeader(candidatePreHeader);
} else {
assert(externalPredecessorCount == 0 || externalPredecessorCount > 1 &&
"Loop header should have exactly one external predecessor or none.");
// TODO: 如果有多个外部前驱或没有,这里应该插入新的基本块作为前置块,
// 并调整控制流。这会修改 IR需要返回 true。
// 目前,我们只是简单地不设置 preHeader。
@@ -112,64 +118,101 @@ bool LoopAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
CurrentResult->addLoop(std::move(currentLoop));
}
// 步骤 5: 处理嵌套循环 (确定父子关系)
// 遍历所有已识别的循环,确定它们的嵌套关系
// 步骤 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();
// 1. 首先,清除所有循环已设置的父子关系和嵌套子循环列表,确保重新计算
for (const auto &loop_ptr : allLoops) {
loop_ptr->setParentLoop(nullptr); // 清除父指针
loop_ptr->clearNestedLoops(); // 清除子循环列表
loop_ptr->setLoopLevel(-1); // 重置循环层级
}
// 2. 遍历所有循环,为每个循环找到其直接父循环并建立关系
for (const auto &innerLoop_ptr : allLoops) {
Loop *innerLoop = innerLoop_ptr.get();
Loop *immediateParent = nullptr; // 用于存储当前 innerLoop 的最近父循环
for (const auto &outerLoop_ptr : allLoops) {
Loop *outerLoop = outerLoop_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 头支配的最近的循环头
// 检查 outerLoop 是否包含 innerLoop 的所有条件:
// Condition 1: outerLoop 的头支配 innerLoop 的
if (!(DT->getDominators(innerLoop->getHeader()) &&
DT->getDominators(innerLoop->getHeader())->count(outerLoop->getHeader()))) {
continue; // outerLoop 不支配 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);
}
}
// Condition 2: innerLoop 的所有基本块都在 outerLoop 的基本块集合中
bool allInnerBlocksInOuter = true;
for (BasicBlock *innerBB : innerLoop->getBlocks()) {
if (!outerLoop->contains(innerBB)) { //
allInnerBlocksInOuter = false;
break;
}
}
if (!allInnerBlocksInOuter) {
continue; // outerLoop 不包含 innerLoop 的所有块
}
// 到此为止outerLoop 已经被确认为 innerLoop 的一个“候选父循环”(即它包含了 innerLoop
if (immediateParent == nullptr) {
// 这是找到的第一个候选父循环
immediateParent = outerLoop;
} else {
// 已经有了一个 immediateParent需要判断哪个是更“紧密”的父循环
// 更紧密的父循环是那个包含另一个候选父循环的。
// 如果当前的 immediateParent 包含了 outerLoop 的头,那么 outerLoop 是更深的循环(更接近 innerLoop
if (immediateParent->contains(outerLoop->getHeader())) { //
immediateParent = outerLoop; // outerLoop 是更紧密的父循环
}
// 否则outerLoop 包含了 immediateParent 的头),说明 immediateParent 更紧密,保持不变
// 或者它们互不包含(不应该发生,因为它们都包含了 innerLoop也保持 immediateParent
}
}
// 设置 innerLoop 的直接父循环,并添加到父循环的嵌套列表中
if (immediateParent) {
innerLoop->setParentLoop(immediateParent);
immediateParent->addNestedLoop(innerLoop);
}
}
// 3. 计算循环层级 (Level) 并填充最外层/最内层循环列表
std::queue<Loop *> q_level;
// 查找所有最外层循环没有父循环的设置其层级为0并加入队列
CurrentResult->clearOutermostLoops(); // 清空最外层循环列表
for (const auto &loop_ptr : allLoops) {
if (loop_ptr->isOutermost()) {
loop_ptr->setLoopLevel(0);
q_level.push(loop_ptr.get());
CurrentResult->addOutermostLoop(loop_ptr.get());
}
}
// 使用 BFS 遍历循环树,计算所有嵌套循环的层级
while (!q_level.empty()) {
Loop *current = q_level.front();
q_level.pop();
for (Loop *nestedLoop : current->getNestedLoops()) {
nestedLoop->setLoopLevel(current->getLoopLevel() + 1);
q_level.push(nestedLoop);
}
}
// 填充最内层循环列表
CurrentResult->clearInnermostLoops(); // 清空最内层循环列表
for (const auto &loop_ptr : allLoops) {
if (loop_ptr->isInnermost()) {
CurrentResult->addInnermostLoop(loop_ptr.get());
}
}