diff --git a/src/include/midend/Pass/Analysis/Loop.h b/src/include/midend/Pass/Analysis/Loop.h new file mode 100644 index 0000000..5895152 --- /dev/null +++ b/src/include/midend/Pass/Analysis/Loop.h @@ -0,0 +1,155 @@ +#pragma once + +#include "Dom.h" // 包含 DominatorTreeAnalysisPass 的依赖 +#include "IR.h" // 包含 IR 定义 +#include "Pass.h" // 包含 Pass 框架 +#include +#include +#include +#include // 用于循环体块的逆向遍历 +#include +#include + +namespace sysy { + +// 前向声明,防止循环引用 +class LoopAnalysisResult; + +/** + * @brief 表示一个识别出的循环。 + */ +class Loop { +public: + // 构造函数:指定循环头 + Loop(BasicBlock *header) : Header(header) {} + + // 获取循环头 + BasicBlock *getHeader() const { return Header; } + + // 获取循环体包含的所有基本块 + const std::set &getBlocks() const { return LoopBlocks; } + + // 获取循环的出口基本块(即从循环内部跳转到循环外部的基本块) + const std::set &getExitBlocks() const { return ExitBlocks; } + + // 获取循环前置块(如果存在),可以为 nullptr + BasicBlock *getPreHeader() const { return PreHeader; } + + // 获取直接包含此循环的父循环(如果存在),可以为 nullptr + Loop *getParentLoop() const { return ParentLoop; } + + // 获取直接嵌套在此循环内的子循环 + const std::vector &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 LoopBlocks; // 循环体包含的基本块集合 + std::set ExitBlocks; // 循环出口基本块集合 + BasicBlock *PreHeader = nullptr; // 循环前置块 (Optional) + Loop *ParentLoop = nullptr; // 父循环 (用于嵌套) + std::vector 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) { + AllLoops.push_back(std::move(loop)); + // 也可以选择将 Loop* 存储到 map 中,方便通过 header 查找 + LoopMap[AllLoops.back()->getHeader()] = AllLoops.back().get(); + } + + // 获取所有识别出的循环(unique_ptr 管理内存) + const std::vector> &getAllLoops() const { return AllLoops; } + + // 获取所有最外层循环 + const std::vector &getOutermostLoops() const { return OutermostLoops; } + + // 获取所有最内层循环 + const std::vector &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> AllLoops; // 所有识别出的循环 + std::map LoopMap; // 循环头到 Loop* 的映射,方便查找 + std::vector OutermostLoops; // 最外层循环的列表 + std::vector 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 getResult() override { return std::move(CurrentResult); } + +private: + std::unique_ptr CurrentResult; // 当前函数的分析结果 +}; + +} // namespace sysy \ No newline at end of file diff --git a/src/midend/Pass/Analysis/Loop.cpp b/src/midend/Pass/Analysis/Loop.cpp new file mode 100644 index 0000000..684d19c --- /dev/null +++ b/src/midend/Pass/Analysis/Loop.cpp @@ -0,0 +1,179 @@ +#include "Dom.h" // 确保包含 DominatorTreeAnalysisPass 的定义 +#include "Loop.h" +#include + +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(F); + return false; // 空函数,没有循环 + } + + if (DEBUG) + std::cout << "Running LoopAnalysisPass on function: " << F->getName() << std::endl; + + // 获取支配树分析结果 + // 这是循环分析的关键依赖 + DominatorTree *DT = AM.getAnalysisResult(F); + if (!DT) { + // 无法获取支配树,无法进行循环分析 + std::cerr << "Error: DominatorTreeAnalysisResult not available for function " << F->getName() << std::endl; + CurrentResult = std::make_unique(F); + return false; + } + + CurrentResult = std::make_unique(F); + bool changed = false; // 循环分析本身不修改IR,所以通常返回false + + // 步骤 1: 识别回边和对应的自然循环 + // 回边 (N -> D) 定义:D 支配 N + std::vector> 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 currentLoop = std::make_unique(D); + + // 收集循环体块:从 N 逆向遍历到 D (不包括中间的 D) + std::set loopBlocks; // 临时存储循环块 + std::queue 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 \ No newline at end of file