From 6a7355ed281054bdef1517bb153185f4d7809763 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Sat, 9 Aug 2025 17:53:41 +0800 Subject: [PATCH] =?UTF-8?q?[midend-Loop]=E5=88=9D=E6=AD=A5=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E5=BE=AA=E7=8E=AF=E8=A7=84=E8=8C=83=E9=81=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../midend/Pass/Optimize/LoopNormalization.h | 155 +++++++ src/midend/CMakeLists.txt | 1 + .../Pass/Optimize/LoopNormalization.cpp | 432 ++++++++++++++++++ 3 files changed, 588 insertions(+) create mode 100644 src/include/midend/Pass/Optimize/LoopNormalization.h create mode 100644 src/midend/Pass/Optimize/LoopNormalization.cpp diff --git a/src/include/midend/Pass/Optimize/LoopNormalization.h b/src/include/midend/Pass/Optimize/LoopNormalization.h new file mode 100644 index 0000000..c676b97 --- /dev/null +++ b/src/include/midend/Pass/Optimize/LoopNormalization.h @@ -0,0 +1,155 @@ +#pragma once + +#include "Loop.h" // 循环分析依赖 +#include "LoopCharacteristics.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; // 循环结构分析结果 + LoopCharacteristicsResult* loopCharacteristics; // 循环特征分析结果 + DominatorTree* domTree; // 支配树分析结果 + + // ========== 规范化统计 ========== + struct NormalizationStats { + size_t totalLoops; // 总循环数 + size_t loopsNeedingPreheader; // 需要前置块的循环数 + size_t preheadersCreated; // 创建的前置块数 + size_t loopsNormalized; // 规范化的循环数 + + NormalizationStats() : totalLoops(0), loopsNeedingPreheader(0), + preheadersCreated(0), loopsNormalized(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); + + /** + * 为前置块生成合适的名称 + * @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 diff --git a/src/midend/CMakeLists.txt b/src/midend/CMakeLists.txt index 251408b..4a5d121 100644 --- a/src/midend/CMakeLists.txt +++ b/src/midend/CMakeLists.txt @@ -17,6 +17,7 @@ add_library(midend_lib STATIC Pass/Optimize/Reg2Mem.cpp Pass/Optimize/SysYIRCFGOpt.cpp Pass/Optimize/SCCP.cpp + Pass/Optimize/LoopNormalization.cpp ) # 包含中端模块所需的头文件路径 diff --git a/src/midend/Pass/Optimize/LoopNormalization.cpp b/src/midend/Pass/Optimize/LoopNormalization.cpp new file mode 100644 index 0000000..f82be5d --- /dev/null +++ b/src/midend/Pass/Optimize/LoopNormalization.cpp @@ -0,0 +1,432 @@ +#include "LoopNormalization.h" +#include "Dom.h" +#include "Loop.h" +#include "LoopCharacteristics.h" +#include +#include +#include + +// 使用全局调试开关 +extern int DEBUG; + +namespace sysy { + +// 定义 Pass 的唯一 ID +void *LoopNormalizationPass::ID = (void *)&LoopNormalizationPass::ID; + +bool LoopNormalizationPass::runOnFunction(Function *F, AnalysisManager &AM) { + if (F->getBasicBlocks().empty()) { + return false; // 空函数 + } + + if (DEBUG) + std::cout << "Running LoopNormalizationPass on function: " << F->getName() << std::endl; + + // 获取并缓存所有需要的分析结果 + loopAnalysis = AM.getAnalysisResult(F); + if (!loopAnalysis || !loopAnalysis->hasLoops()) { + if (DEBUG) + std::cout << "No loops found in function " << F->getName() << ", skipping normalization" << std::endl; + return false; // 没有循环需要规范化 + } + + loopCharacteristics = AM.getAnalysisResult(F); + domTree = AM.getAnalysisResult(F); + + if (!domTree) { + std::cerr << "Error: DominatorTree not available for function " << F->getName() << std::endl; + return false; + } + + // 重置统计信息 + stats = NormalizationStats(); + + bool modified = false; + const auto& allLoops = loopAnalysis->getAllLoops(); + stats.totalLoops = allLoops.size(); + + if (DEBUG) { + std::cout << "Found " << stats.totalLoops << " loops to analyze for normalization" << std::endl; + } + + // 按循环深度从外到内处理,确保外层循环先规范化 + std::vector sortedLoops; + for (const auto& loop_ptr : allLoops) { + sortedLoops.push_back(loop_ptr.get()); + } + + std::sort(sortedLoops.begin(), sortedLoops.end(), [](Loop* a, Loop* b) { + return a->getLoopDepth() < b->getLoopDepth(); // 按深度升序排列 + }); + + // 逐个规范化循环 + for (Loop* loop : sortedLoops) { + if (needsPreheader(loop)) { + stats.loopsNeedingPreheader++; + + if (DEBUG) { + std::cout << " Loop " << loop->getName() << " needs preheader (depth=" + << loop->getLoopDepth() << ")" << std::endl; + } + + if (normalizeLoop(loop)) { + modified = true; + stats.loopsNormalized++; + + // 验证规范化结果 + if (!validateNormalization(loop)) { + std::cerr << "Warning: Loop normalization validation failed for loop " + << loop->getName() << std::endl; + } + } + } else { + if (DEBUG) { + auto* preheader = getExistingPreheader(loop); + if (preheader) { + std::cout << " Loop " << loop->getName() << " already has preheader: " + << preheader->getName() << std::endl; + } + } + } + } + + if (DEBUG && modified) { + printStats(F); + } + + return modified; +} + +bool LoopNormalizationPass::normalizeLoop(Loop* loop) { + if (DEBUG) + std::cout << " Normalizing loop: " << loop->getName() << std::endl; + + // 创建前置块 + BasicBlock* preheader = createPreheaderForLoop(loop); + if (!preheader) { + if (DEBUG) + std::cout << " Failed to create preheader for loop " << loop->getName() << std::endl; + return false; + } + + stats.preheadersCreated++; + + if (DEBUG) { + std::cout << " Successfully created preheader " << preheader->getName() + << " for loop " << loop->getName() << std::endl; + } + + return true; +} + +BasicBlock* LoopNormalizationPass::createPreheaderForLoop(Loop* loop) { + BasicBlock* header = loop->getHeader(); + if (!header) { + if (DEBUG) + std::cerr << " Error: Loop has no header block" << std::endl; + return nullptr; + } + + // 获取循环外的前驱块 + std::vector externalPreds = getExternalPredecessors(loop); + if (externalPreds.empty()) { + if (DEBUG) + std::cout << " Loop " << loop->getName() << " has no external predecessors" << std::endl; + return nullptr; + } + + if (DEBUG) { + std::cout << " Found " << externalPreds.size() << " external predecessors for loop " + << loop->getName() << std::endl; + for (auto* pred : externalPreds) { + std::cout << " External pred: " << pred->getName() << std::endl; + } + } + + // 生成前置块名称 + std::string preheaderName = generatePreheaderName(loop); + + // 创建新的前置块 + Function* parentFunction = header->getParent(); + BasicBlock* preheader = parentFunction->addBasicBlock(preheaderName); + + if (!preheader) { + if (DEBUG) + std::cerr << " Error: Failed to create basic block " << preheaderName << std::endl; + return nullptr; + } + + // 在前置块中创建一个简单的跳转指令到循环头部 + builder->setPosition(preheader, preheader->end()); + UncondBrInst* br = builder->createUncondBrInst(header); + + // 重定向外部前驱到新的前置块 + redirectExternalPredecessors(loop, preheader, header); + + // 更新PHI节点 + updatePhiNodesForPreheader(header, preheader, externalPreds); + + // 更新支配树关系 + updateDominatorRelations(preheader, loop); + + return preheader; +} + +bool LoopNormalizationPass::needsPreheader(Loop* loop) { + // 检查是否已有合适的前置块 + if (getExistingPreheader(loop) != nullptr) { + return false; + } + + // 检查是否有外部前驱(如果没有外部前驱,不需要前置块) + std::vector externalPreds = getExternalPredecessors(loop); + if (externalPreds.empty()) { + return false; + } + + // 如果有多个外部前驱,或者单个外部前驱不适合作为前置块,则需要创建前置块 + if (externalPreds.size() > 1) { + return true; + } + + // 检查唯一的外部前驱是否适合作为前置块 + return !isSuitableAsPreheader(externalPreds[0], loop); +} + +BasicBlock* LoopNormalizationPass::getExistingPreheader(Loop* loop) { + BasicBlock* header = loop->getHeader(); + if (!header) return nullptr; + + std::vector externalPreds = getExternalPredecessors(loop); + + // 如果只有一个外部前驱,且适合作为前置块,则返回它 + if (externalPreds.size() == 1 && isSuitableAsPreheader(externalPreds[0], loop)) { + return externalPreds[0]; + } + + return nullptr; +} + +void LoopNormalizationPass::updateDominatorRelations(BasicBlock* newBlock, Loop* loop) { + // 这里需要更新支配树关系 + // 新的前置块应该支配循环头部,并且被循环外的前驱支配 + if (DEBUG) { + std::cout << " Updating dominator relations for new preheader " << newBlock->getName() << std::endl; + } + // 实际的支配树更新逻辑在这里实现 + // 由于支配树分析通常在Pass运行后重新计算,这里主要是标记需要更新 +} + +void LoopNormalizationPass::redirectExternalPredecessors(Loop* loop, BasicBlock* preheader, BasicBlock* header) { + std::vector externalPreds = getExternalPredecessors(loop); + + if (DEBUG) { + std::cout << " Redirecting " << externalPreds.size() << " external predecessors" << std::endl; + } + + for (BasicBlock* pred : externalPreds) { + // 获取前驱块的终止指令 + auto termIt = pred->terminator(); + if (termIt == pred->end()) continue; + + Instruction* terminator = termIt->get(); + if (!terminator) continue; + + // 更新跳转目标 + if (auto* br = dynamic_cast(terminator)) { + // 无条件跳转 + if (br->getBlock() == header) { + // 需要更新操作数 + br->setOperand(0, preheader); + // 更新CFG关系 + header->removePredecessor(pred); + preheader->addPredecessor(pred); + pred->removeSuccessor(header); + pred->addSuccessor(preheader); + + if (DEBUG) + std::cout << " Updated unconditional branch from " << pred->getName() + << " to " << preheader->getName() << std::endl; + } + } else if (auto* condBr = dynamic_cast(terminator)) { + // 条件跳转 + bool updated = false; + if (condBr->getThenBlock() == header) { + condBr->setOperand(1, preheader); // 第1个操作数是then分支 + updated = true; + } + if (condBr->getElseBlock() == header) { + condBr->setOperand(2, preheader); // 第2个操作数是else分支 + updated = true; + } + if (updated) { + // 更新CFG关系 + header->removePredecessor(pred); + preheader->addPredecessor(pred); + pred->removeSuccessor(header); + pred->addSuccessor(preheader); + + if (DEBUG) { + std::cout << " Updated conditional branch from " << pred->getName() + << " to " << preheader->getName() << std::endl; + } + } + } + } +} + +std::string LoopNormalizationPass::generatePreheaderName(Loop* loop) { + std::ostringstream oss; + oss << loop->getName() << ".preheader"; + return oss.str(); +} + +bool LoopNormalizationPass::validateNormalization(Loop* loop) { + BasicBlock* header = loop->getHeader(); + if (!header) return false; + + // 检查循环是否现在有唯一的外部前驱 + std::vector externalPreds = getExternalPredecessors(loop); + if (externalPreds.size() != 1) { + if (DEBUG) + std::cout << " Validation failed: Loop " << loop->getName() + << " has " << externalPreds.size() << " external predecessors (expected 1)" << std::endl; + return false; + } + + // 检查外部前驱是否适合作为前置块 + if (!isSuitableAsPreheader(externalPreds[0], loop)) { + if (DEBUG) + std::cout << " Validation failed: External predecessor " << externalPreds[0]->getName() + << " is not suitable as preheader" << std::endl; + return false; + } + + if (DEBUG) + std::cout << " Validation passed for loop " << loop->getName() << std::endl; + + return true; +} + +std::vector LoopNormalizationPass::getExternalPredecessors(Loop* loop) { + std::vector externalPreds; + BasicBlock* header = loop->getHeader(); + if (!header) return externalPreds; + + for (BasicBlock* pred : header->getPredecessors()) { + if (!loop->contains(pred)) { + externalPreds.push_back(pred); + } + } + + return externalPreds; +} + +bool LoopNormalizationPass::isSuitableAsPreheader(BasicBlock* block, Loop* loop) { + if (!block) return false; + + // 检查该块是否只有一个后继,且后继是循环头部 + auto successors = block->getSuccessors(); + if (successors.size() != 1) { + return false; + } + + if (successors[0] != loop->getHeader()) { + return false; + } + + // 检查该块是否不包含复杂的控制流 + // 理想的前置块应该只包含简单的跳转指令 + size_t instCount = 0; + for (const auto& inst : block->getInstructions()) { + instCount++; + // 如果指令过多,可能不适合作为前置块 + if (instCount > 10) { // 阈值可调整 + return false; + } + } + + return true; +} + +void LoopNormalizationPass::updatePhiNodesForPreheader(BasicBlock* header, BasicBlock* preheader, + const std::vector& oldPreds) { + if (DEBUG) { + std::cout << " Updating PHI nodes in header " << header->getName() + << " for new preheader " << preheader->getName() << std::endl; + } + + for (auto& inst : header->getInstructions()) { + if (auto* phi = dynamic_cast(inst.get())) { + if (DEBUG) { + std::cout << " Processing PHI node: " << phi->getName() << std::endl; + } + + // 收集来自外部前驱的值 + std::vector> externalValues; + for (BasicBlock* oldPred : oldPreds) { + Value* value = phi->getvalfromBlk(oldPred); + if (value) { + externalValues.push_back({value, oldPred}); + } + } + + // 从PHI节点中移除旧的外部前驱 + for (BasicBlock* oldPred : oldPreds) { + phi->removeIncoming(oldPred); + } + + // 如果有多个来自外部的值,需要在前置块中创建新的PHI节点 + if (externalValues.size() > 1) { + // 在前置块中创建新的PHI节点来合并外部值 + builder->setPosition(preheader, preheader->getInstructions().begin()); + + std::vector values; + std::vector blocks; + for (auto& [value, block] : externalValues) { + values.push_back(value); + blocks.push_back(block); + } + + PhiInst* newPhi = builder->createPhiInst(phi->getType(), values, blocks, "preheader.phi"); + + // 将新PHI的结果作为来自前置块的值添加到原PHI中 + phi->addIncoming(newPhi, preheader); + } else if (externalValues.size() == 1) { + // 只有一个外部值,直接添加 + phi->addIncoming(externalValues[0].first, preheader); + } + } + } +} + +void LoopNormalizationPass::printStats(Function* F) { + std::cout << "\n--- Loop Normalization Statistics for Function: " << F->getName() << " ---" << std::endl; + std::cout << "Total loops analyzed: " << stats.totalLoops << std::endl; + std::cout << "Loops needing preheader: " << stats.loopsNeedingPreheader << std::endl; + std::cout << "Preheaders created: " << stats.preheadersCreated << std::endl; + std::cout << "Loops successfully normalized: " << stats.loopsNormalized << std::endl; + + if (stats.totalLoops > 0) { + double normalizationRate = (double)stats.loopsNormalized / stats.totalLoops * 100.0; + std::cout << "Normalization rate: " << normalizationRate << "%" << std::endl; + } + + std::cout << "---------------------------------------------------------------" << std::endl; +} + +void LoopNormalizationPass::getAnalysisUsage(std::set &analysisDependencies, + std::set &analysisInvalidations) const { + // LoopNormalization依赖的分析 + analysisDependencies.insert(&LoopAnalysisPass::ID); // 循环结构分析 + analysisDependencies.insert(&LoopCharacteristicsPass::ID); // 循环特征分析 + analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); // 支配树分析 + + // LoopNormalization会修改CFG结构,因此会使以下分析失效 + analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树需要重新计算 + // 注意:循环结构分析可能需要更新,但我们不让它失效,因为我们只是添加前置块 + // analysisInvalidations.insert(&LoopAnalysisPass::ID); // 通常不需要失效 + // analysisInvalidations.insert(&LoopCharacteristicsPass::ID); // 通常不需要失效 +} + +} // namespace sysy