[midend-Loop]循环分析构建,增加很多统计方法和循环信息方法

This commit is contained in:
rain2133
2025-08-06 22:29:39 +08:00
parent ef9d7c4d03
commit f083e38615
5 changed files with 223 additions and 32 deletions

View File

@ -1375,6 +1375,17 @@ protected:
auto is_same_ptr = [blockToRemove](const std::unique_ptr<BasicBlock> &ptr) { return ptr.get() == blockToRemove; };
blocks.remove_if(is_same_ptr);
}
BasicBlock* addBasicBlock(const std::string &name, BasicBlock *before) {
// 在指定的基本块之前添加一个新的基本块
auto it = std::find_if(blocks.begin(), blocks.end(),
[before](const std::unique_ptr<BasicBlock> &ptr) { return ptr.get() == before; });
if (it != blocks.end()) {
blocks.emplace(it, new BasicBlock(this, name));
return it->get(); // 返回新添加的基本块指针
}
assert(false && "BasicBlock to insert before not found!");
return nullptr; // 如果没有找到指定的基本块则返回nullptr
} ///< 添加一个新的基本块到某个基本块之前
BasicBlock* addBasicBlock(const std::string &name = "") {
blocks.emplace_back(new BasicBlock(this, name));
return blocks.back().get();

View File

@ -19,13 +19,18 @@ class LoopAnalysisResult;
* @brief 表示一个识别出的循环。
*/
class Loop {
private:
static int NextLoopID; // 静态变量用于分配唯一ID
int LoopID;
public:
// 构造函数:指定循环头
Loop(BasicBlock *header) : Header(header) {}
Loop(BasicBlock *header) : Header(header), LoopID(NextLoopID++) {}
// 获取循环头
BasicBlock *getHeader() const { return Header; }
// 获取循环的名称 基于ID
std::string getName() const { return "loop_" + std::to_string(LoopID); }
// 获取循环体包含的所有基本块
const std::set<BasicBlock *> &getBlocks() const { return LoopBlocks; }
@ -50,8 +55,42 @@ public:
// 判断当前循环是否是最内层循环 (没有嵌套子循环)
bool isInnermost() const { return NestedLoops.empty(); }
// 判断当前循环是否是最外层循环 (没有父循环)
bool isOutermost() const { return ParentLoop == nullptr; }
// 获取循环的深度(从最外层开始计算)
int getLoopDepth() const { return Level + 1; }
// 获取循环体的大小(基本块数量)
size_t getLoopSize() const { return LoopBlocks.size(); }
// 检查循环是否有唯一的外部前驱(即是否有前置块)
bool hasUniquePreHeader() const { return PreHeader != nullptr; }
// 检查循环是否是最外层循环(没有父循环)
bool isOutermost() const { return getParentLoop() == nullptr; }
// 获取循环的所有出口(从循环内到循环外的基本块)
std::vector<BasicBlock*> getExitingBlocks() const {
std::vector<BasicBlock*> exitingBlocks;
for (BasicBlock* bb : LoopBlocks) {
for (BasicBlock* succ : bb->getSuccessors()) {
if (!contains(succ)) {
exitingBlocks.push_back(bb);
break; // 每个基本块只添加一次
}
}
}
return exitingBlocks;
}
// 判断循环是否是简单循环(只有一个回边)
bool isSimpleLoop() const {
int backEdgeCount = 0;
for (BasicBlock* pred : Header->getPredecessors()) {
if (contains(pred)) {
backEdgeCount++;
}
}
return backEdgeCount == 1;
}
// --- 供 LoopAnalysisPass 内部调用的方法,用于构建 Loop 对象 ---
void addBlock(BasicBlock *BB) { LoopBlocks.insert(BB); }
@ -93,9 +132,36 @@ public:
// 获取所有最外层循环
const std::vector<Loop *> &getOutermostLoops() const { return OutermostLoops; }
// 获取所有最内层循环
const std::vector<Loop *> &getInnermostLoops() const { return InnermostLoops; }
// 获取循环总数
size_t getLoopCount() const { return AllLoops.size(); }
// 获取最大循环嵌套深度
int getMaxLoopDepth() const {
int maxDepth = 0;
for (const auto& loop : AllLoops) {
if (loop->getLoopDepth() > maxDepth) {
maxDepth = loop->getLoopDepth();
}
}
return maxDepth;
}
// 获取指定深度的循环数量
size_t getLoopCountAtDepth(int depth) const {
size_t count = 0;
for (const auto& loop : AllLoops) {
if (loop->getLoopDepth() == depth) {
count++;
}
}
return count;
}
// 检查函数是否包含循环
bool hasLoops() const { return !AllLoops.empty(); }
// 通过循环头获取 Loop 对象
Loop *getLoopForHeader(BasicBlock *header) const {
auto it = LoopMap.find(header);
@ -122,6 +188,11 @@ public:
void clearOutermostLoops() { OutermostLoops.clear(); }
void clearInnermostLoops() { InnermostLoops.clear(); }
// 打印分析结果
void print() const;
void printBBSet(const std::string &prefix, const std::set<BasicBlock *> &s) const;
void printLoopVector(const std::string &prefix, const std::vector<Loop *> &loops) const;
private:
Function *AssociatedFunction; // 结果关联的函数
std::vector<std::unique_ptr<Loop>> AllLoops; // 所有识别出的循环

View File

@ -6,6 +6,7 @@ add_library(midend_lib STATIC
Pass/Pass.cpp
Pass/Analysis/Dom.cpp
Pass/Analysis/Liveness.cpp
Pass/Analysis/Loop.cpp
Pass/Optimize/DCE.cpp
Pass/Optimize/Mem2Reg.cpp
Pass/Optimize/Reg2Mem.cpp

View File

@ -1,14 +1,110 @@
// Loop.cpp (完整内容,包含所有修改)
#include "Dom.h" // 确保包含 DominatorTreeAnalysisPass 的定义
#include "Loop.h" //
#include <iostream>
#include <queue> // 用于 BFS 遍历设置循环层级
// 调试模式开关
#ifndef DEBUG
#define DEBUG 0
#endif
namespace sysy {
// 定义 Pass 的唯一 ID
void *LoopAnalysisPass::ID = (void *)&LoopAnalysisPass::ID;
// 定义 Loop 类的静态变量
int Loop::NextLoopID = 0;
// **实现 LoopAnalysisResult::print() 方法**
void LoopAnalysisResult::printBBSet(const std::string &prefix, const std::set<BasicBlock *> &s) const{
if (!DEBUG) return;
std::cout << prefix << "{";
bool first = true;
for (const auto &bb : s) {
if (!first) std::cout << ", ";
std::cout << bb->getName();
first = false;
}
std::cout << "}";
}
// **辅助函数:打印 Loop 指针向量**
void LoopAnalysisResult::printLoopVector(const std::string &prefix, const std::vector<Loop *> &loops) const {
if (!DEBUG) return;
std::cout << prefix << "[";
bool first = true;
for (const auto &loop : loops) {
if (!first) std::cout << ", ";
std::cout << loop->getName(); // 假设 Loop::getName() 存在
first = false;
}
std::cout << "]";
}
void LoopAnalysisResult::print() const {
if (!DEBUG) return; // 只有在 DEBUG 模式下才打印
std::cout << "\n--- Loop Analysis Results for Function: " << AssociatedFunction->getName() << " ---" << std::endl;
if (AllLoops.empty()) {
std::cout << " No loops found." << std::endl;
return;
}
std::cout << "Total Loops Found: " << AllLoops.size() << std::endl;
// 1. 按层级分组循环
std::map<int, std::vector<Loop*>> loopsByLevel;
int maxLevel = 0;
for (const auto& loop_ptr : AllLoops) {
if (loop_ptr->getLoopLevel() != -1) { // 确保层级已计算
loopsByLevel[loop_ptr->getLoopLevel()].push_back(loop_ptr.get());
if (loop_ptr->getLoopLevel() > maxLevel) {
maxLevel = loop_ptr->getLoopLevel();
}
}
}
// 2. 打印循环层次结构
std::cout << "\n--- Loop Hierarchy ---" << std::endl;
for (int level = 0; level <= maxLevel; ++level) {
if (loopsByLevel.count(level)) {
std::cout << "Level " << level << " Loops:" << std::endl;
for (Loop* loop : loopsByLevel[level]) {
std::string indent(level * 2, ' '); // 根据层级缩进
std::cout << indent << "- Loop Header: " << loop->getName() << std::endl;
std::cout << indent << " Blocks: ";
printBBSet("", loop->getBlocks());
std::cout << std::endl;
std::cout << indent << " Exit Blocks: ";
printBBSet("", loop->getExitBlocks());
std::cout << std::endl;
std::cout << indent << " Pre-Header: " << (loop->getPreHeader() ? loop->getPreHeader()->getName() : "None") << std::endl;
std::cout << indent << " Parent Loop: " << (loop->getParentLoop() ? loop->getParentLoop()->getName() : "None (Outermost)") << std::endl;
std::cout << indent << " Nested Loops: ";
printLoopVector("", loop->getNestedLoops());
std::cout << std::endl;
}
}
}
// 3. 打印最外层/最内层循环摘要
std::cout << "\n--- Loop Summary ---" << std::endl;
std::cout << "Outermost Loops: ";
printLoopVector("", getOutermostLoops());
std::cout << std::endl;
std::cout << "Innermost Loops: ";
printLoopVector("", getInnermostLoops());
std::cout << std::endl;
std::cout << "-----------------------------------------------" << std::endl;
}
bool LoopAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
if (F->getBasicBlocks().empty()) {
CurrentResult = std::make_unique<LoopAnalysisResult>(F);
@ -35,42 +131,54 @@ bool LoopAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
// 回边 (N -> D) 定义D 支配 N
std::vector<std::pair<BasicBlock *, BasicBlock *>> backEdges;
for (auto &BB : F->getBasicBlocks()) {
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({Blcok, Succ});
auto Block = BB.get();
for (BasicBlock *Succ : Block->getSuccessors()) {
if (DT->getDominators(Block) && DT->getDominators(Block)->count(Succ)) {
// Succ 支配 Block,所以 (Block -> Succ) 是一条回边
backEdges.push_back({Block, Succ});
if (DEBUG)
std::cout << "Found back edge: " << Block->getName() << " -> " << Succ->getName() << std::endl;
}
}
}
if (DEBUG)
std::cout << "Total back edges found: " << backEdges.size() << std::endl;
// 步骤 2: 为每条回边构建自然循环
std::map<BasicBlock*, std::unique_ptr<Loop>> loopMap; // 按循环头分组
for (auto &edge : backEdges) {
BasicBlock *N = edge.first; // 回边的尾部
BasicBlock *D = edge.second; // 回边的头部 (循环头)
// 创建新的 Loop 对象
std::unique_ptr<Loop> currentLoop = std::make_unique<Loop>(D);
// 检查是否已经为此循环头创建了循环
if (loopMap.find(D) == loopMap.end()) {
// 创建新的 Loop 对象
loopMap[D] = std::make_unique<Loop>(D);
}
Loop* currentLoop = loopMap[D].get();
// 收集循环体块:从 N 逆向遍历到 D (不包括中间的 D)
// 收集此回边对应的循环体块:从 N 逆向遍历到 D
std::set<BasicBlock *> loopBlocks; // 临时存储循环块
std::queue<BasicBlock *> q;
q.push(N);
loopBlocks.insert(N); // 回边的尾部首先是循环块
// 循环头总是循环体的一部分
loopBlocks.insert(D);
// 如果回边的尾部不是循环头本身,则将其加入队列进行遍历
if (N != D) {
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);
@ -78,10 +186,15 @@ bool LoopAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
}
}
// 将收集到的块添加到 Loop 对象中
// 将收集到的块添加到 Loop 对象中(合并所有回边的结果)
for (BasicBlock *loopBB : loopBlocks) {
currentLoop->addBlock(loopBB);
}
}
// 处理每个合并后的循环
for (auto &[header, currentLoop] : loopMap) {
const auto &loopBlocks = currentLoop->getBlocks();
// 步骤 3: 识别循环出口块 (Exit Blocks)
for (BasicBlock *loopBB : loopBlocks) {
@ -93,10 +206,10 @@ bool LoopAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
}
}
// 步骤 4: 识别循环前置块 (Pre-Header) - 您的前端已做很多工作,这里是确认和规范化
// 步骤 4: 识别循环前置块 (Pre-Header)
BasicBlock *candidatePreHeader = nullptr;
int externalPredecessorCount = 0;
for (BasicBlock *predOfHeader : D->getPredecessors()) {
for (BasicBlock *predOfHeader : header->getPredecessors()) {
// 使用 currentLoop->contains() 来检查前驱是否在循环体内
if (!currentLoop->contains(predOfHeader)) {
// 如果前驱不在循环体内,则是一个外部前驱
@ -107,14 +220,7 @@ 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。
}
CurrentResult->addLoop(std::move(currentLoop));
}

View File

@ -1,5 +1,6 @@
#include "Dom.h"
#include "Liveness.h"
#include "Loop.h"
#include "SysYIRCFGOpt.h"
#include "SysYIRPrinter.h"
#include "DCE.h"
@ -37,6 +38,7 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
// 注册分析遍
registerAnalysisPass<sysy::DominatorTreeAnalysisPass>();
registerAnalysisPass<sysy::LivenessAnalysisPass>();
registerAnalysisPass<LoopAnalysisPass>();
// 注册优化遍
registerOptimizationPass<SysYDelInstAfterBrPass>();