From 48865fa805be42cf5633d07a31ed036dc709d8ef Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Wed, 13 Aug 2025 17:42:34 +0800 Subject: [PATCH] =?UTF-8?q?[midend-IVE]=E5=A2=9E=E5=8A=A0=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E5=BD=92=E7=BA=B3=E5=8F=98=E9=87=8F=E6=B6=88=E9=99=A4?= =?UTF-8?q?=E9=81=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Optimize/InductionVariableElimination.h | 157 +++++++ src/midend/CMakeLists.txt | 1 + .../Optimize/InductionVariableElimination.cpp | 433 ++++++++++++++++++ src/midend/Pass/Pass.cpp | 3 + 4 files changed, 594 insertions(+) create mode 100644 src/include/midend/Pass/Optimize/InductionVariableElimination.h create mode 100644 src/midend/Pass/Optimize/InductionVariableElimination.cpp diff --git a/src/include/midend/Pass/Optimize/InductionVariableElimination.h b/src/include/midend/Pass/Optimize/InductionVariableElimination.h new file mode 100644 index 0000000..b65a3d8 --- /dev/null +++ b/src/include/midend/Pass/Optimize/InductionVariableElimination.h @@ -0,0 +1,157 @@ +#pragma once + +#include "Pass.h" +#include "IR.h" +#include "LoopCharacteristics.h" +#include "Loop.h" +#include "Dom.h" +#include "SideEffectAnalysis.h" +#include +#include +#include +#include + +namespace sysy { + +// 前向声明 +class LoopCharacteristicsResult; +class LoopAnalysisResult; + +/** + * @brief 死归纳变量信息 + * 记录一个可以被消除的归纳变量 + */ +struct DeadInductionVariable { + PhiInst* phiInst; // phi 指令 + std::vector relatedInsts; // 相关的递增/递减指令 + Loop* containingLoop; // 所在循环 + bool canEliminate; // 是否可以安全消除 + + DeadInductionVariable(PhiInst* phi, Loop* loop) + : phiInst(phi), containingLoop(loop), canEliminate(false) {} +}; + +/** + * @brief 归纳变量消除上下文类 + * 封装归纳变量消除优化的核心逻辑和状态 + */ +class InductionVariableEliminationContext { +public: + InductionVariableEliminationContext() {} + + /** + * 运行归纳变量消除优化 + * @param F 目标函数 + * @param AM 分析管理器 + * @return 是否修改了IR + */ + bool run(Function* F, AnalysisManager& AM); + +private: + // 分析结果缓存 + LoopAnalysisResult* loopAnalysis = nullptr; + LoopCharacteristicsResult* loopCharacteristics = nullptr; + DominatorTree* dominatorTree = nullptr; + SideEffectAnalysisResult* sideEffectAnalysis = nullptr; + + // 死归纳变量存储 + std::vector> deadIVs; + std::unordered_map> loopToDeadIVs; + + // ========== 核心分析和优化阶段 ========== + + /** + * 阶段1:识别死归纳变量 + * 找出没有被有效使用的归纳变量 + */ + void identifyDeadInductionVariables(Function* F); + + /** + * 阶段2:分析消除的安全性 + * 确保消除操作不会破坏程序语义 + */ + void analyzeSafetyForElimination(); + + /** + * 阶段3:执行归纳变量消除 + * 删除死归纳变量及其相关指令 + */ + bool performInductionVariableElimination(); + + // ========== 辅助方法 ========== + + /** + * 检查归纳变量是否为死归纳变量 + * @param iv 归纳变量信息 + * @param loop 所在循环 + * @return 如果是死归纳变量返回相关信息,否则返回nullptr + */ + std::unique_ptr + isDeadInductionVariable(const InductionVarInfo* iv, Loop* loop); + + /** + * 检查归纳变量是否只用于自身更新 + * @param phiInst phi指令 + * @param loop 所在循环 + * @return 是否只用于自身更新 + */ + bool isUsedOnlyForSelfUpdate(PhiInst* phiInst, Loop* loop); + + /** + * 收集与归纳变量相关的所有指令 + * @param phiInst phi指令 + * @param loop 所在循环 + * @return 相关指令列表 + */ + std::vector collectRelatedInstructions(PhiInst* phiInst, Loop* loop); + + /** + * 检查消除归纳变量的安全性 + * @param deadIV 死归纳变量 + * @return 是否可以安全消除 + */ + bool isSafeToEliminate(const DeadInductionVariable* deadIV); + + /** + * 消除单个死归纳变量 + * @param deadIV 死归纳变量 + * @return 是否成功消除 + */ + bool eliminateDeadInductionVariable(DeadInductionVariable* deadIV); + + /** + * 打印调试信息 + */ + void printDebugInfo(); +}; + +/** + * @brief 归纳变量消除优化遍 + * 消除循环中无用的归纳变量,减少寄存器压力 + */ +class InductionVariableElimination : public OptimizationPass { +public: + // 唯一的 Pass ID + static void *ID; + + InductionVariableElimination() + : OptimizationPass("InductionVariableElimination", Granularity::Function) {} + + /** + * 在函数上运行归纳变量消除优化 + * @param F 目标函数 + * @param AM 分析管理器 + * @return 是否修改了IR + */ + bool runOnFunction(Function* F, AnalysisManager& AM) override; + + /** + * 声明分析依赖和失效信息 + */ + void getAnalysisUsage(std::set& analysisDependencies, + std::set& analysisInvalidations) const override; + + void* getPassID() const override { return &ID; } +}; + +} // namespace sysy diff --git a/src/midend/CMakeLists.txt b/src/midend/CMakeLists.txt index 93d1468..b3b86cc 100644 --- a/src/midend/CMakeLists.txt +++ b/src/midend/CMakeLists.txt @@ -20,6 +20,7 @@ add_library(midend_lib STATIC Pass/Optimize/LoopNormalization.cpp Pass/Optimize/LICM.cpp Pass/Optimize/LoopStrengthReduction.cpp + Pass/Optimize/InductionVariableElimination.cpp Pass/Optimize/BuildCFG.cpp Pass/Optimize/LargeArrayToGlobal.cpp ) diff --git a/src/midend/Pass/Optimize/InductionVariableElimination.cpp b/src/midend/Pass/Optimize/InductionVariableElimination.cpp new file mode 100644 index 0000000..09527f5 --- /dev/null +++ b/src/midend/Pass/Optimize/InductionVariableElimination.cpp @@ -0,0 +1,433 @@ +#include "InductionVariableElimination.h" +#include "LoopCharacteristics.h" +#include "Loop.h" +#include "Dom.h" +#include "SideEffectAnalysis.h" +#include "SysYIROptUtils.h" +#include +#include + +// 使用全局调试开关 +extern int DEBUG; + +namespace sysy { + +// 定义 Pass 的唯一 ID +void *InductionVariableElimination::ID = (void *)&InductionVariableElimination::ID; + +bool InductionVariableElimination::runOnFunction(Function* F, AnalysisManager& AM) { + if (F->getBasicBlocks().empty()) { + return false; // 空函数 + } + + if (DEBUG) { + std::cout << "Running InductionVariableElimination on function: " << F->getName() << std::endl; + } + + // 创建优化上下文并运行 + InductionVariableEliminationContext context; + bool modified = context.run(F, AM); + + if (DEBUG) { + std::cout << "InductionVariableElimination " << (modified ? "modified" : "did not modify") + << " function: " << F->getName() << std::endl; + } + + return modified; +} + +void InductionVariableElimination::getAnalysisUsage(std::set& analysisDependencies, + std::set& analysisInvalidations) const { + // 依赖的分析 + analysisDependencies.insert(&LoopAnalysisPass::ID); + analysisDependencies.insert(&LoopCharacteristicsPass::ID); + analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); + analysisDependencies.insert(&SysYSideEffectAnalysisPass::ID); + + // 会使失效的分析(归纳变量消除会修改IR结构) + analysisInvalidations.insert(&LoopCharacteristicsPass::ID); + // 注意:支配树分析通常不会因为归纳变量消除而失效,因为我们不改变控制流 +} + +// ========== InductionVariableEliminationContext 实现 ========== + +bool InductionVariableEliminationContext::run(Function* F, AnalysisManager& AM) { + if (DEBUG) { + std::cout << " Starting induction variable elimination analysis..." << std::endl; + } + + // 获取必要的分析结果 + loopAnalysis = AM.getAnalysisResult(F); + if (!loopAnalysis || !loopAnalysis->hasLoops()) { + if (DEBUG) { + std::cout << " No loops found, skipping induction variable elimination" << std::endl; + } + return false; + } + + loopCharacteristics = AM.getAnalysisResult(F); + if (!loopCharacteristics) { + if (DEBUG) { + std::cout << " LoopCharacteristics analysis not available" << std::endl; + } + return false; + } + + dominatorTree = AM.getAnalysisResult(F); + if (!dominatorTree) { + if (DEBUG) { + std::cout << " DominatorTree analysis not available" << std::endl; + } + return false; + } + + sideEffectAnalysis = AM.getAnalysisResult(); + if (!sideEffectAnalysis) { + if (DEBUG) { + std::cout << " SideEffectAnalysis not available, using conservative approach" << std::endl; + } + // 可以继续执行,但会使用更保守的策略 + } else { + if (DEBUG) { + std::cout << " Using SideEffectAnalysis for safety checks" << std::endl; + } + } + + // 执行三个阶段的优化 + + // 阶段1:识别死归纳变量 + identifyDeadInductionVariables(F); + + if (deadIVs.empty()) { + if (DEBUG) { + std::cout << " No dead induction variables found" << std::endl; + } + return false; + } + + if (DEBUG) { + std::cout << " Found " << deadIVs.size() << " potentially dead induction variables" << std::endl; + } + + // 阶段2:分析安全性 + analyzeSafetyForElimination(); + + // 阶段3:执行消除 + bool modified = performInductionVariableElimination(); + + if (DEBUG) { + printDebugInfo(); + } + + return modified; +} + +void InductionVariableEliminationContext::identifyDeadInductionVariables(Function* F) { + if (DEBUG) { + std::cout << " === Phase 1: Identifying Dead Induction Variables ===" << std::endl; + } + + // 遍历所有循环 + for (const auto& loop_ptr : loopAnalysis->getAllLoops()) { + Loop* loop = loop_ptr.get(); + + if (DEBUG) { + std::cout << " Analyzing loop: " << loop->getName() << std::endl; + } + + // 获取循环特征 + const LoopCharacteristics* characteristics = loopCharacteristics->getCharacteristics(loop); + if (!characteristics) { + if (DEBUG) { + std::cout << " No characteristics available for loop" << std::endl; + } + continue; + } + + if (characteristics->InductionVars.empty()) { + if (DEBUG) { + std::cout << " No induction variables found in loop" << std::endl; + } + continue; + } + + // 检查每个归纳变量是否为死归纳变量 + for (const auto& iv : characteristics->InductionVars) { + auto deadIV = isDeadInductionVariable(iv.get(), loop); + if (deadIV) { + if (DEBUG) { + std::cout << " Found potential dead IV: %" << deadIV->phiInst->getName() << std::endl; + } + + // 添加到候选项列表 + loopToDeadIVs[loop].push_back(deadIV.get()); + deadIVs.push_back(std::move(deadIV)); + } + } + } + + if (DEBUG) { + std::cout << " === End Phase 1: Found " << deadIVs.size() << " candidates ===" << std::endl; + } +} + +std::unique_ptr +InductionVariableEliminationContext::isDeadInductionVariable(const InductionVarInfo* iv, Loop* loop) { + // 获取 phi 指令 + auto* phiInst = dynamic_cast(iv->div); + if (!phiInst) { + return nullptr; // 不是 phi 指令 + } + + // 检查是否只用于自身更新 + if (!isUsedOnlyForSelfUpdate(phiInst, loop)) { + return nullptr; // 有其他用途 + } + + // 创建死归纳变量信息 + auto deadIV = std::make_unique(phiInst, loop); + deadIV->relatedInsts = collectRelatedInstructions(phiInst, loop); + + return deadIV; +} + +bool InductionVariableEliminationContext::isUsedOnlyForSelfUpdate(PhiInst* phiInst, Loop* loop) { + // 检查 phi 指令的所有使用 + for (auto use : phiInst->getUses()) { + auto user = use->getUser(); + auto* userInst = dynamic_cast(user); + + if (!userInst) { + return false; // 被非指令使用 + } + + // 检查使用是否在循环内 + if (!loop->contains(userInst->getParent())) { + return false; // 在循环外被使用 + } + + // 检查是否为自身的更新指令 + bool isSelfUpdate = false; + + // 检查是否为加法/减法指令(常见的归纳变量更新模式) + if (userInst->getKind() == Instruction::Kind::kAdd || + userInst->getKind() == Instruction::Kind::kSub) { + auto* binInst = dynamic_cast(userInst); + if (binInst && (binInst->getOperand(0) == phiInst || binInst->getOperand(1) == phiInst)) { + // 检查这个指令的结果是否流回到 phi + for (auto& [incomingBB, incomingVal] : phiInst->getIncomingValues()) { + if (loop->contains(incomingBB) && incomingVal == binInst) { + isSelfUpdate = true; + break; + } + } + } + } + + if (!isSelfUpdate) { + return false; // 有非自更新的使用 + } + } + + return true; // 只用于自身更新 +} + +std::vector InductionVariableEliminationContext::collectRelatedInstructions( + PhiInst* phiInst, Loop* loop) { + std::vector relatedInsts; + + // 收集所有与该归纳变量相关的指令 + for (auto use : phiInst->getUses()) { + auto user = use->getUser(); + auto* userInst = dynamic_cast(user); + + if (userInst && loop->contains(userInst->getParent())) { + relatedInsts.push_back(userInst); + } + } + + return relatedInsts; +} + +void InductionVariableEliminationContext::analyzeSafetyForElimination() { + if (DEBUG) { + std::cout << " === Phase 2: Analyzing Safety for Elimination ===" << std::endl; + } + + // 为每个死归纳变量检查消除的安全性 + for (auto& deadIV : deadIVs) { + bool isSafe = isSafeToEliminate(deadIV.get()); + deadIV->canEliminate = isSafe; + + if (DEBUG) { + std::cout << " Dead IV " << deadIV->phiInst->getName() + << ": " << (isSafe ? "SAFE" : "UNSAFE") << " to eliminate" << std::endl; + } + } + + if (DEBUG) { + size_t safeCount = 0; + for (const auto& deadIV : deadIVs) { + if (deadIV->canEliminate) safeCount++; + } + std::cout << " === End Phase 2: " << safeCount << " of " << deadIVs.size() + << " variables are safe to eliminate ===" << std::endl; + } +} + +bool InductionVariableEliminationContext::isSafeToEliminate(const DeadInductionVariable* deadIV) { + // 1. 确保归纳变量在循环头 + if (deadIV->phiInst->getParent() != deadIV->containingLoop->getHeader()) { + if (DEBUG) { + std::cout << " Unsafe: phi not in loop header" << std::endl; + } + return false; + } + + // 2. 确保相关指令都在循环内 + for (auto* inst : deadIV->relatedInsts) { + if (!deadIV->containingLoop->contains(inst->getParent())) { + if (DEBUG) { + std::cout << " Unsafe: related instruction outside loop" << std::endl; + } + return false; + } + } + + // 3. 确保没有副作用 + for (auto* inst : deadIV->relatedInsts) { + if (sideEffectAnalysis) { + // 使用副作用分析进行精确检查 + if (sideEffectAnalysis->hasSideEffect(inst)) { + if (DEBUG) { + std::cout << " Unsafe: related instruction " << inst->getName() + << " has side effects" << std::endl; + } + return false; + } + } else { + // 没有副作用分析时使用保守策略:只允许基本算术运算 + auto kind = inst->getKind(); + if (kind != Instruction::Kind::kAdd && + kind != Instruction::Kind::kSub && + kind != Instruction::Kind::kMul) { + if (DEBUG) { + std::cout << " Unsafe: related instruction may have side effects (conservative)" << std::endl; + } + return false; + } + } + } + + // 4. 确保不影响循环的退出条件 + for (BasicBlock* exitingBB : deadIV->containingLoop->getExitingBlocks()) { + auto terminatorIt = exitingBB->terminator(); + if (terminatorIt != exitingBB->end()) { + Instruction* terminator = terminatorIt->get(); + if (terminator) { + for (size_t i = 0; i < terminator->getNumOperands(); ++i) { + if (terminator->getOperand(i) == deadIV->phiInst) { + if (DEBUG) { + std::cout << " Unsafe: phi used in loop exit condition" << std::endl; + } + return false; + } + } + } + } + } + + return true; +} + +bool InductionVariableEliminationContext::performInductionVariableElimination() { + if (DEBUG) { + std::cout << " === Phase 3: Performing Induction Variable Elimination ===" << std::endl; + } + + bool modified = false; + + for (auto& deadIV : deadIVs) { + if (!deadIV->canEliminate) { + continue; + } + + if (DEBUG) { + std::cout << " Eliminating dead IV: " << deadIV->phiInst->getName() << std::endl; + } + + if (eliminateDeadInductionVariable(deadIV.get())) { + if (DEBUG) { + std::cout << " Successfully eliminated: " << deadIV->phiInst->getName() << std::endl; + } + modified = true; + } else { + if (DEBUG) { + std::cout << " Failed to eliminate: " << deadIV->phiInst->getName() << std::endl; + } + } + } + + if (DEBUG) { + std::cout << " === End Phase 3: " << (modified ? "Eliminations performed" : "No eliminations") << " ===" << std::endl; + } + + return modified; +} + +bool InductionVariableEliminationContext::eliminateDeadInductionVariable(DeadInductionVariable* deadIV) { + // 1. 删除所有相关指令 + for (auto* inst : deadIV->relatedInsts) { + auto* bb = inst->getParent(); + auto it = bb->findInstIterator(inst); + if (it != bb->end()) { + SysYIROptUtils::usedelete(it); + // bb->getInstructions().erase(it); + if (DEBUG) { + std::cout << " Removed related instruction: " << inst->getName() << std::endl; + } + } + } + + // 2. 删除 phi 指令 + auto* bb = deadIV->phiInst->getParent(); + auto it = bb->findInstIterator(deadIV->phiInst); + if (it != bb->end()) { + SysYIROptUtils::usedelete(it); + // bb->getInstructions().erase(it); + if (DEBUG) { + std::cout << " Removed phi instruction: " << deadIV->phiInst->getName() << std::endl; + } + return true; + } + + return false; +} + +void InductionVariableEliminationContext::printDebugInfo() { + if (!DEBUG) return; + + std::cout << "\n=== Induction Variable Elimination Summary ===" << std::endl; + std::cout << "Total dead IVs found: " << deadIVs.size() << std::endl; + + size_t eliminatedCount = 0; + for (auto& [loop, loopDeadIVs] : loopToDeadIVs) { + size_t loopEliminatedCount = 0; + for (auto* deadIV : loopDeadIVs) { + if (deadIV->canEliminate) { + loopEliminatedCount++; + eliminatedCount++; + } + } + + if (loopEliminatedCount > 0) { + std::cout << "Loop " << loop->getName() << ": " << loopEliminatedCount + << " of " << loopDeadIVs.size() << " IVs eliminated" << std::endl; + } + } + + std::cout << "Total eliminated: " << eliminatedCount << " of " << deadIVs.size() << std::endl; + std::cout << "=============================================" << std::endl; +} + +} // namespace sysy diff --git a/src/midend/Pass/Pass.cpp b/src/midend/Pass/Pass.cpp index 5b9db22..3686bd2 100644 --- a/src/midend/Pass/Pass.cpp +++ b/src/midend/Pass/Pass.cpp @@ -16,6 +16,7 @@ #include "LoopNormalization.h" #include "LICM.h" #include "LoopStrengthReduction.h" +#include "InductionVariableElimination.h" #include "Pass.h" #include #include @@ -72,6 +73,7 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR registerOptimizationPass(builderIR); registerOptimizationPass(builderIR); registerOptimizationPass(builderIR); + registerOptimizationPass(); registerOptimizationPass(builderIR); registerOptimizationPass(builderIR); @@ -140,6 +142,7 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR this->addPass(&LoopNormalizationPass::ID); this->addPass(&LICM::ID); this->addPass(&LoopStrengthReduction::ID); + this->addPass(&InductionVariableElimination::ID); this->run(); if(DEBUG) {