[midend]loop分析构建
This commit is contained in:
155
src/include/midend/Pass/Analysis/Loop.h
Normal file
155
src/include/midend/Pass/Analysis/Loop.h
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Dom.h" // 包含 DominatorTreeAnalysisPass 的依赖
|
||||||
|
#include "IR.h" // 包含 IR 定义
|
||||||
|
#include "Pass.h" // 包含 Pass 框架
|
||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <queue> // 用于循环体块的逆向遍历
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace sysy {
|
||||||
|
|
||||||
|
// 前向声明,防止循环引用
|
||||||
|
class LoopAnalysisResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 表示一个识别出的循环。
|
||||||
|
*/
|
||||||
|
class Loop {
|
||||||
|
public:
|
||||||
|
// 构造函数:指定循环头
|
||||||
|
Loop(BasicBlock *header) : Header(header) {}
|
||||||
|
|
||||||
|
// 获取循环头
|
||||||
|
BasicBlock *getHeader() const { return Header; }
|
||||||
|
|
||||||
|
// 获取循环体包含的所有基本块
|
||||||
|
const std::set<BasicBlock *> &getBlocks() const { return LoopBlocks; }
|
||||||
|
|
||||||
|
// 获取循环的出口基本块(即从循环内部跳转到循环外部的基本块)
|
||||||
|
const std::set<BasicBlock *> &getExitBlocks() const { return ExitBlocks; }
|
||||||
|
|
||||||
|
// 获取循环前置块(如果存在),可以为 nullptr
|
||||||
|
BasicBlock *getPreHeader() const { return PreHeader; }
|
||||||
|
|
||||||
|
// 获取直接包含此循环的父循环(如果存在),可以为 nullptr
|
||||||
|
Loop *getParentLoop() const { return ParentLoop; }
|
||||||
|
|
||||||
|
// 获取直接嵌套在此循环内的子循环
|
||||||
|
const std::vector<Loop *> &getNestedLoops() const { return NestedLoops; }
|
||||||
|
|
||||||
|
// 获取循环的层级 (0 表示最外层循环,1 表示嵌套一层,以此类推)
|
||||||
|
int getLoopLevel() const { return Level; }
|
||||||
|
|
||||||
|
// 检查一个基本块是否属于当前循环
|
||||||
|
bool contains(BasicBlock *BB) const { return LoopBlocks.count(BB); }
|
||||||
|
|
||||||
|
// 判断当前循环是否是最内层循环 (没有嵌套子循环)
|
||||||
|
bool isInnermost() const { return NestedLoops.empty(); }
|
||||||
|
|
||||||
|
// 判断当前循环是否是最外层循环 (没有父循环)
|
||||||
|
bool isOutermost() const { return ParentLoop == nullptr; }
|
||||||
|
|
||||||
|
// --- 供 LoopAnalysisPass 内部调用的方法,用于构建 Loop 对象 ---
|
||||||
|
void addBlock(BasicBlock *BB) { LoopBlocks.insert(BB); }
|
||||||
|
void addExitBlock(BasicBlock *BB) { ExitBlocks.insert(BB); }
|
||||||
|
void setPreHeader(BasicBlock *BB) { PreHeader = BB; }
|
||||||
|
void setParentLoop(Loop *loop) { ParentLoop = loop; }
|
||||||
|
void addNestedLoop(Loop *loop) { NestedLoops.push_back(loop); }
|
||||||
|
void setLoopLevel(int level) { Level = level; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
BasicBlock *Header; // 循环头基本块
|
||||||
|
std::set<BasicBlock *> LoopBlocks; // 循环体包含的基本块集合
|
||||||
|
std::set<BasicBlock *> ExitBlocks; // 循环出口基本块集合
|
||||||
|
BasicBlock *PreHeader = nullptr; // 循环前置块 (Optional)
|
||||||
|
Loop *ParentLoop = nullptr; // 父循环 (用于嵌套)
|
||||||
|
std::vector<Loop *> NestedLoops; // 嵌套的子循环
|
||||||
|
int Level = -1; // 循环的层级,-1表示未计算
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 循环分析结果类。
|
||||||
|
* 包含一个函数中所有识别出的循环。
|
||||||
|
*/
|
||||||
|
class LoopAnalysisResult : public AnalysisResultBase {
|
||||||
|
public:
|
||||||
|
LoopAnalysisResult(Function *F) : AssociatedFunction(F) {}
|
||||||
|
~LoopAnalysisResult() override = default;
|
||||||
|
|
||||||
|
// 添加一个识别出的循环到结果中
|
||||||
|
void addLoop(std::unique_ptr<Loop> loop) {
|
||||||
|
AllLoops.push_back(std::move(loop));
|
||||||
|
// 也可以选择将 Loop* 存储到 map 中,方便通过 header 查找
|
||||||
|
LoopMap[AllLoops.back()->getHeader()] = AllLoops.back().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取所有识别出的循环(unique_ptr 管理内存)
|
||||||
|
const std::vector<std::unique_ptr<Loop>> &getAllLoops() const { return AllLoops; }
|
||||||
|
|
||||||
|
// 获取所有最外层循环
|
||||||
|
const std::vector<Loop *> &getOutermostLoops() const { return OutermostLoops; }
|
||||||
|
|
||||||
|
// 获取所有最内层循环
|
||||||
|
const std::vector<Loop *> &getInnermostLoops() const { return InnermostLoops; }
|
||||||
|
|
||||||
|
// 通过循环头获取 Loop 对象
|
||||||
|
Loop *getLoopForHeader(BasicBlock *header) const {
|
||||||
|
auto it = LoopMap.find(header);
|
||||||
|
return (it != LoopMap.end()) ? it->second : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通过某个基本块获取包含它的最内层循环
|
||||||
|
Loop *getLoopContainingBlock(BasicBlock *BB) const {
|
||||||
|
// 遍历所有循环,找到包含 BB 且层级最深的循环
|
||||||
|
Loop *innermostContainingLoop = nullptr;
|
||||||
|
for (const auto &loop_ptr : AllLoops) {
|
||||||
|
if (loop_ptr->contains(BB)) {
|
||||||
|
if (!innermostContainingLoop || loop_ptr->getLoopLevel() > innermostContainingLoop->getLoopLevel()) {
|
||||||
|
innermostContainingLoop = loop_ptr.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return innermostContainingLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 供 LoopAnalysisPass 内部调用的方法,用于构建 LoopAnalysisResult 对象 ---
|
||||||
|
void addOutermostLoop(Loop *loop) { OutermostLoops.push_back(loop); }
|
||||||
|
void addInnermostLoop(Loop *loop) { InnermostLoops.push_back(loop); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Function *AssociatedFunction; // 结果关联的函数
|
||||||
|
std::vector<std::unique_ptr<Loop>> AllLoops; // 所有识别出的循环
|
||||||
|
std::map<BasicBlock *, Loop *> LoopMap; // 循环头到 Loop* 的映射,方便查找
|
||||||
|
std::vector<Loop *> OutermostLoops; // 最外层循环的列表
|
||||||
|
std::vector<Loop *> InnermostLoops; // 最内层循环的列表
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 循环分析遍。
|
||||||
|
* 识别函数中的所有循环,并生成 LoopAnalysisResult。
|
||||||
|
*/
|
||||||
|
class LoopAnalysisPass : public AnalysisPass {
|
||||||
|
public:
|
||||||
|
// 唯一的 Pass ID,需要在 .cpp 文件中定义
|
||||||
|
static void *ID;
|
||||||
|
|
||||||
|
LoopAnalysisPass() : AnalysisPass("LoopAnalysis", Pass::Granularity::Function) {}
|
||||||
|
|
||||||
|
// 实现 getPassID
|
||||||
|
void *getPassID() const override { return &ID; }
|
||||||
|
|
||||||
|
// 核心运行方法:在每个函数上执行循环分析
|
||||||
|
bool runOnFunction(Function *F, AnalysisManager &AM) override;
|
||||||
|
|
||||||
|
// 获取分析结果
|
||||||
|
std::unique_ptr<AnalysisResultBase> getResult() override { return std::move(CurrentResult); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<LoopAnalysisResult> CurrentResult; // 当前函数的分析结果
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sysy
|
||||||
179
src/midend/Pass/Analysis/Loop.cpp
Normal file
179
src/midend/Pass/Analysis/Loop.cpp
Normal 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
|
||||||
Reference in New Issue
Block a user