#pragma once #include "Loop.h" // 循环分析依赖 #include "Dom.h" // 支配树分析依赖 #include "IR.h" // IR定义 #include "IRBuilder.h" // IR构建器 #include "Pass.h" // Pass框架 #include #include #include 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 &analysisDependencies, std::set &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& externalPreds); /** * 为前置块生成合适的名称 * @param loop 相关的循环 * @return 生成的前置块名称 */ std::string generatePreheaderName(Loop* loop); /** * 验证规范化结果的正确性 * @param loop 规范化后的循环 * @return true如果规范化正确 */ bool validateNormalization(Loop* loop); // ========== 辅助方法 ========== /** * 获取循环的外部前驱块(不在循环内的前驱) * @param loop 目标循环 * @return 外部前驱块列表 */ std::vector 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& oldPreds); /** * 打印规范化统计信息 */ void printStats(Function* F); }; } // namespace sysy