156 lines
4.7 KiB
C++
156 lines
4.7 KiB
C++
#pragma once
|
||
|
||
#include "Loop.h" // 循环分析依赖
|
||
#include "Dom.h" // 支配树分析依赖
|
||
#include "IR.h" // IR定义
|
||
#include "IRBuilder.h" // IR构建器
|
||
#include "Pass.h" // Pass框架
|
||
#include <memory>
|
||
#include <set>
|
||
#include <vector>
|
||
|
||
namespace sysy {
|
||
|
||
/**
|
||
* @brief 循环规范化转换Pass
|
||
*
|
||
* 该Pass在循环不变量提升等优化前运行,主要负责:
|
||
* 1. 为没有前置块(preheader)的循环创建前置块
|
||
* 2. 确保循环结构符合后续优化的要求
|
||
* 3. 规范化循环的控制流结构
|
||
*
|
||
* 前置块的作用:
|
||
* - 为循环不变量提升提供插入位置
|
||
* - 简化循环分析和优化
|
||
* - 确保循环有唯一的入口点
|
||
*/
|
||
class LoopNormalizationPass : public OptimizationPass {
|
||
public:
|
||
// 唯一的 Pass ID
|
||
static void *ID;
|
||
|
||
LoopNormalizationPass(IRBuilder* builder) : OptimizationPass("LoopNormalization", Pass::Granularity::Function), builder(builder) {}
|
||
|
||
// 实现 getPassID
|
||
void *getPassID() const override { return &ID; }
|
||
|
||
// 核心运行方法
|
||
bool runOnFunction(Function *F, AnalysisManager &AM) override;
|
||
|
||
// 声明分析依赖和失效信息
|
||
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
|
||
|
||
private:
|
||
// ========== IR构建器 ==========
|
||
IRBuilder* builder; // IR构建器
|
||
|
||
// ========== 缓存的分析结果 ==========
|
||
LoopAnalysisResult* loopAnalysis; // 循环结构分析结果
|
||
DominatorTree* domTree; // 支配树分析结果
|
||
|
||
// ========== 规范化统计 ==========
|
||
struct NormalizationStats {
|
||
size_t totalLoops; // 总循环数
|
||
size_t loopsNeedingPreheader; // 需要前置块的循环数
|
||
size_t preheadersCreated; // 创建的前置块数
|
||
size_t loopsNormalized; // 规范化的循环数
|
||
size_t redundantPhisRemoved; // 删除的冗余PHI节点数
|
||
|
||
NormalizationStats() : totalLoops(0), loopsNeedingPreheader(0),
|
||
preheadersCreated(0), loopsNormalized(0),
|
||
redundantPhisRemoved(0) {}
|
||
} stats;
|
||
|
||
// ========== 核心规范化方法 ==========
|
||
|
||
/**
|
||
* 规范化单个循环
|
||
* @param loop 要规范化的循环
|
||
* @return 是否进行了修改
|
||
*/
|
||
bool normalizeLoop(Loop* loop);
|
||
|
||
/**
|
||
* 为循环创建前置块
|
||
* @param loop 需要前置块的循环
|
||
* @return 创建的前置块,如果失败则返回nullptr
|
||
*/
|
||
BasicBlock* createPreheaderForLoop(Loop* loop);
|
||
|
||
/**
|
||
* 检查循环是否需要前置块(基于结构性需求)
|
||
* @param loop 要检查的循环
|
||
* @return true如果需要前置块
|
||
*/
|
||
bool needsPreheader(Loop* loop);
|
||
|
||
/**
|
||
* 检查循环是否已有合适的前置块
|
||
* @param loop 要检查的循环
|
||
* @return 现有的前置块,如果没有则返回nullptr
|
||
*/
|
||
BasicBlock* getExistingPreheader(Loop* loop);
|
||
|
||
/**
|
||
* 更新支配树关系(在创建新块后)
|
||
* @param newBlock 新创建的基本块
|
||
* @param loop 相关的循环
|
||
*/
|
||
void updateDominatorRelations(BasicBlock* newBlock, Loop* loop);
|
||
|
||
/**
|
||
* 重定向循环外的前驱块到新的前置块
|
||
* @param loop 目标循环
|
||
* @param preheader 新创建的前置块
|
||
* @param header 循环头部
|
||
*/
|
||
void redirectExternalPredecessors(Loop* loop, BasicBlock* preheader, BasicBlock* header, const std::vector<BasicBlock*>& externalPreds);
|
||
|
||
/**
|
||
* 为前置块生成合适的名称
|
||
* @param loop 相关的循环
|
||
* @return 生成的前置块名称
|
||
*/
|
||
std::string generatePreheaderName(Loop* loop);
|
||
|
||
/**
|
||
* 验证规范化结果的正确性
|
||
* @param loop 规范化后的循环
|
||
* @return true如果规范化正确
|
||
*/
|
||
bool validateNormalization(Loop* loop);
|
||
|
||
// ========== 辅助方法 ==========
|
||
|
||
/**
|
||
* 获取循环的外部前驱块(不在循环内的前驱)
|
||
* @param loop 目标循环
|
||
* @return 外部前驱块列表
|
||
*/
|
||
std::vector<BasicBlock*> getExternalPredecessors(Loop* loop);
|
||
|
||
/**
|
||
* 检查基本块是否适合作为前置块
|
||
* @param block 候选基本块
|
||
* @param loop 目标循环
|
||
* @return true如果适合作为前置块
|
||
*/
|
||
bool isSuitableAsPreheader(BasicBlock* block, Loop* loop);
|
||
|
||
/**
|
||
* 更新PHI节点以适应新的前置块
|
||
* @param header 循环头部
|
||
* @param preheader 新的前置块
|
||
* @param oldPreds 原来的外部前驱
|
||
*/
|
||
void updatePhiNodesForPreheader(BasicBlock* header, BasicBlock* preheader,
|
||
const std::vector<BasicBlock*>& oldPreds);
|
||
|
||
/**
|
||
* 打印规范化统计信息
|
||
*/
|
||
void printStats(Function* F);
|
||
};
|
||
|
||
} // namespace sysy
|