From fa33bf513497814bcf632e6240c622d25bfdb9f1 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Fri, 15 Aug 2025 01:19:45 +0800 Subject: [PATCH] =?UTF-8?q?[midend-Loop-IVE]=E4=BF=AE=E5=A4=8D=E5=BE=AA?= =?UTF-8?q?=E7=8E=AF=E7=9A=84=E6=AD=BBIV=E6=B6=88=E9=99=A4=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Pass_ID_List.md | 18 ++++++- .../Optimize/InductionVariableElimination.cpp | 51 ++++++++++++++----- 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/Pass_ID_List.md b/Pass_ID_List.md index 7481855..86393c7 100644 --- a/Pass_ID_List.md +++ b/Pass_ID_List.md @@ -396,9 +396,25 @@ check_initial_overflow() 智能回退:使用已验证的标准值保证正确性 保持通用性:对于没有预设值的除数仍然可以工作 +## 死归纳变量消除 + +整体架构和工作流程 +当前的归纳变量消除优化分为三个清晰的阶段: + +识别阶段:找出所有潜在的死归纳变量 +安全性分析阶段:验证每个变量消除的安全性 +消除执行阶段:实际删除安全的死归纳变量 + + +逃逸点检测 (已修复的关键安全机制) +数组索引检测:GEP指令被正确识别为逃逸点 +循环退出条件:用于比较和条件分支的归纳变量不会被消除 +控制流指令:condBr、br、return等被特殊处理为逃逸点 +内存操作:store/load指令经过别名分析检查 + # 后续优化可能涉及的改动 -## 1)将所有的alloca集中到entryblock中 +## 1)将所有的alloca集中到entryblock中(已实现) 好处:优化友好性,方便mem2reg提升 目前没有实现这个机制,如果想要实现首先解决同一函数不同域的同名变量命名区分 diff --git a/src/midend/Pass/Optimize/InductionVariableElimination.cpp b/src/midend/Pass/Optimize/InductionVariableElimination.cpp index ef4b851..8055efa 100644 --- a/src/midend/Pass/Optimize/InductionVariableElimination.cpp +++ b/src/midend/Pass/Optimize/InductionVariableElimination.cpp @@ -255,6 +255,18 @@ bool InductionVariableEliminationContext::isInstructionUseChainDeadRecursively( return false; // 有副作用的指令是逃逸点 } + // 1.5. 特殊检查:控制流指令永远不是死代码 + auto instKind = inst->getKind(); + if (instKind == Instruction::Kind::kCondBr || + instKind == Instruction::Kind::kBr || + instKind == Instruction::Kind::kReturn) { + if (DEBUG && visited.size() < 10) { + std::cout << " 控制流指令,是逃逸点" << std::endl; + } + currentPath.erase(inst); + return false; // 控制流指令是逃逸点 + } + // 2. 检查指令的所有使用 bool allUsesAreDead = true; for (auto use : inst->getUses()) { @@ -280,22 +292,15 @@ bool InductionVariableEliminationContext::isInstructionUseChainDeadRecursively( } // 特殊检查:如果使用者是循环的退出条件,需要进一步分析 - // 只有当循环有副作用时,才将用于退出条件的归纳变量视为逃逸点 + // 对于用于退出条件的归纳变量,需要更谨慎的处理 if (isUsedInLoopExitCondition(userInst, loop)) { - // 检查循环是否有副作用 - if (loopHasSideEffects(loop)) { - if (DEBUG && visited.size() < 10) { - std::cout << " 被用于循环退出条件且循环有副作用,是逃逸点" << std::endl; - } - allUsesAreDead = false; - break; - } else { - if (DEBUG && visited.size() < 10) { - std::cout << " 被用于循环退出条件但循环无副作用,继续分析" << std::endl; - } - // 对于纯循环,即使用于退出条件也不是逃逸点,继续分析其他使用 - continue; + // 修复逻辑:用于循环退出条件的归纳变量通常不应该被消除 + // 除非整个循环都可以被证明是完全无用的(这需要更复杂的分析) + if (DEBUG && visited.size() < 10) { + std::cout << " 被用于循环退出条件,是逃逸点(避免破坏循环语义)" << std::endl; } + allUsesAreDead = false; + break; } // 递归分析使用者的使用链 @@ -345,6 +350,24 @@ bool InductionVariableEliminationContext::loopHasSideEffects(Loop* loop) { } } + // 重要修复:检查是否为嵌套循环的外层循环 + // 如果当前循环包含其他循环,那么它有潜在的副作用 + for (const auto& loop_ptr : loopAnalysis->getAllLoops()) { + Loop* otherLoop = loop_ptr.get(); + if(loopAnalysis->getLowestCommonAncestor(otherLoop, loop) == loop) { + if (DEBUG) { + std::cout << " 循环 " << loop->getName() << " 是其他循环的外层循环,视为有副作用" << std::endl; + } + return true; // 外层循环被视为有副作用 + } + // if (otherLoop != loop && loop->contains(otherLoop->getHeader())) { + // if (DEBUG) { + // std::cout << " 循环 " << loop->getName() << " 包含子循环 " << otherLoop->getName() << ",视为有副作用" << std::endl; + // } + // return true; // 包含子循环的外层循环被视为有副作用 + // } + } + if (DEBUG) { std::cout << " 循环 " << loop->getName() << " 无副作用" << std::endl; }