From a3435e7c26cfea1d661a807011768849d1717b55 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Thu, 14 Aug 2025 17:27:53 +0800 Subject: [PATCH] =?UTF-8?q?[midend-Loop-IVE]=E5=BE=AA=E7=8E=AF=E5=BD=92?= =?UTF-8?q?=E7=BA=B3=E5=8F=98=E9=87=8F=E6=B6=88=E9=99=A4=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E9=87=8D=E6=9E=84=EF=BC=8C=E4=BF=AE=E6=94=B9=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E9=A1=BA=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Optimize/InductionVariableElimination.h | 101 +++- .../Optimize/InductionVariableElimination.cpp | 516 +++++++++++++++++- src/midend/Pass/Pass.cpp | 2 +- 3 files changed, 587 insertions(+), 32 deletions(-) diff --git a/src/include/midend/Pass/Optimize/InductionVariableElimination.h b/src/include/midend/Pass/Optimize/InductionVariableElimination.h index b65a3d8..db06a46 100644 --- a/src/include/midend/Pass/Optimize/InductionVariableElimination.h +++ b/src/include/midend/Pass/Optimize/InductionVariableElimination.h @@ -6,6 +6,7 @@ #include "Loop.h" #include "Dom.h" #include "SideEffectAnalysis.h" +#include "AliasAnalysis.h" #include #include #include @@ -53,6 +54,7 @@ private: LoopCharacteristicsResult* loopCharacteristics = nullptr; DominatorTree* dominatorTree = nullptr; SideEffectAnalysisResult* sideEffectAnalysis = nullptr; + AliasAnalysisResult* aliasAnalysis = nullptr; // 死归纳变量存储 std::vector> deadIVs; @@ -90,12 +92,105 @@ private: isDeadInductionVariable(const InductionVarInfo* iv, Loop* loop); /** - * 检查归纳变量是否只用于自身更新 + * 递归分析phi指令及其使用链是否都是死代码 * @param phiInst phi指令 * @param loop 所在循环 - * @return 是否只用于自身更新 + * @return phi指令是否可以安全删除 */ - bool isUsedOnlyForSelfUpdate(PhiInst* phiInst, Loop* loop); + bool isPhiInstructionDeadRecursively(PhiInst* phiInst, Loop* loop); + + /** + * 递归分析指令的使用链是否都是死代码 + * @param inst 要分析的指令 + * @param loop 所在循环 + * @param visited 已访问的指令集合(避免无限递归) + * @param currentPath 当前递归路径(检测循环依赖) + * @return 指令的使用链是否都是死代码 + */ + bool isInstructionUseChainDeadRecursively(Instruction* inst, Loop* loop, + std::set& visited, + std::set& currentPath); + + /** + * 检查循环是否有副作用 + * @param loop 要检查的循环 + * @return 循环是否有副作用 + */ + bool loopHasSideEffects(Loop* loop); + + /** + * 检查指令是否被用于循环退出条件 + * @param inst 要检查的指令 + * @param loop 所在循环 + * @return 是否被用于循环退出条件 + */ + bool isUsedInLoopExitCondition(Instruction* inst, Loop* loop); + + /** + * 检查指令的结果是否未被有效使用 + * @param inst 要检查的指令 + * @param loop 所在循环 + * @return 指令结果是否未被有效使用 + */ + bool isInstructionResultUnused(Instruction* inst, Loop* loop); + + /** + * 检查store指令是否存储到死地址(利用别名分析) + * @param store store指令 + * @param loop 所在循环 + * @return 是否存储到死地址 + */ + bool isStoreToDeadLocation(StoreInst* store, Loop* loop); + + /** + * 检查指令是否为死代码或只在循环内部使用 + * @param inst 要检查的指令 + * @param loop 所在循环 + * @return 是否为死代码或只在循环内部使用 + */ + bool isInstructionDeadOrInternalOnly(Instruction* inst, Loop* loop); + + /** + * 检查指令是否有效地为死代码(带递归深度限制) + * @param inst 要检查的指令 + * @param loop 所在循环 + * @param maxDepth 最大递归深度 + * @return 指令是否有效地为死代码 + */ + bool isInstructionEffectivelyDead(Instruction* inst, Loop* loop, int maxDepth); + + /** + * 检查store指令是否有后续的load操作 + * @param store store指令 + * @param loop 所在循环 + * @return 是否有后续的load操作 + */ + bool hasSubsequentLoad(StoreInst* store, Loop* loop); + + /** + * 检查指令是否在循环外有使用 + * @param inst 要检查的指令 + * @param loop 所在循环 + * @return 是否在循环外有使用 + */ + bool hasUsageOutsideLoop(Instruction* inst, Loop* loop); + + /** + * 检查store指令是否在循环外有后续的load操作 + * @param store store指令 + * @param loop 所在循环 + * @return 是否在循环外有后续的load操作 + */ + bool hasSubsequentLoadOutsideLoop(StoreInst* store, Loop* loop); + + /** + * 递归检查基本块子树中是否有对指定位置的load操作 + * @param bb 基本块 + * @param ptr 指针 + * @param visited 已访问的基本块集合 + * @return 是否有load操作 + */ + bool hasLoadInSubtree(BasicBlock* bb, Value* ptr, std::set& visited); /** * 收集与归纳变量相关的所有指令 diff --git a/src/midend/Pass/Optimize/InductionVariableElimination.cpp b/src/midend/Pass/Optimize/InductionVariableElimination.cpp index 09527f5..ef4b851 100644 --- a/src/midend/Pass/Optimize/InductionVariableElimination.cpp +++ b/src/midend/Pass/Optimize/InductionVariableElimination.cpp @@ -3,6 +3,7 @@ #include "Loop.h" #include "Dom.h" #include "SideEffectAnalysis.h" +#include "AliasAnalysis.h" #include "SysYIROptUtils.h" #include #include @@ -43,6 +44,7 @@ void InductionVariableElimination::getAnalysisUsage(std::set& analysisDep analysisDependencies.insert(&LoopCharacteristicsPass::ID); analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); analysisDependencies.insert(&SysYSideEffectAnalysisPass::ID); + analysisDependencies.insert(&SysYAliasAnalysisPass::ID); // 会使失效的分析(归纳变量消除会修改IR结构) analysisInvalidations.insert(&LoopCharacteristicsPass::ID); @@ -93,6 +95,18 @@ bool InductionVariableEliminationContext::run(Function* F, AnalysisManager& AM) } } + aliasAnalysis = AM.getAnalysisResult(F); + if (!aliasAnalysis) { + if (DEBUG) { + std::cout << " AliasAnalysis not available, using conservative approach" << std::endl; + } + // 可以继续执行,但会使用更保守的策略 + } else { + if (DEBUG) { + std::cout << " Using AliasAnalysis for memory safety checks" << std::endl; + } + } + // 执行三个阶段的优化 // 阶段1:识别死归纳变量 @@ -179,9 +193,9 @@ InductionVariableEliminationContext::isDeadInductionVariable(const InductionVarI return nullptr; // 不是 phi 指令 } - // 检查是否只用于自身更新 - if (!isUsedOnlyForSelfUpdate(phiInst, loop)) { - return nullptr; // 有其他用途 + // 新的逻辑:递归分析整个use-def链,判断是否有真实的使用 + if (!isPhiInstructionDeadRecursively(phiInst, loop)) { + return nullptr; // 有真实的使用,不能删除 } // 创建死归纳变量信息 @@ -191,9 +205,310 @@ InductionVariableEliminationContext::isDeadInductionVariable(const InductionVarI return deadIV; } -bool InductionVariableEliminationContext::isUsedOnlyForSelfUpdate(PhiInst* phiInst, Loop* loop) { - // 检查 phi 指令的所有使用 - for (auto use : phiInst->getUses()) { +// 递归分析phi指令及其使用链是否都是死代码 +bool InductionVariableEliminationContext::isPhiInstructionDeadRecursively(PhiInst* phiInst, Loop* loop) { + if (DEBUG) { + std::cout << " 递归分析归纳变量 " << phiInst->getName() << " 的完整使用链" << std::endl; + } + + // 使用访问集合避免无限递归 + std::set visitedInstructions; + std::set currentPath; // 用于检测循环依赖 + + // 核心逻辑:递归分析使用链,寻找任何"逃逸点" + return isInstructionUseChainDeadRecursively(phiInst, loop, visitedInstructions, currentPath); +} + +// 递归分析指令的使用链是否都是死代码 +bool InductionVariableEliminationContext::isInstructionUseChainDeadRecursively( + Instruction* inst, Loop* loop, + std::set& visited, + std::set& currentPath) { + + if (DEBUG && visited.size() < 10) { // 限制debug输出 + std::cout << " 分析指令 " << inst->getName() << " (" << inst->getKindString() << ")" << std::endl; + } + + // 避免无限递归 + if (currentPath.count(inst) > 0) { + // 发现循环依赖,这在归纳变量中是正常的,继续分析其他路径 + if (DEBUG && visited.size() < 10) { + std::cout << " 发现循环依赖,继续分析其他路径" << std::endl; + } + return true; // 循环依赖本身不是逃逸点 + } + + if (visited.count(inst) > 0) { + // 已经分析过这个指令 + return true; // 假设之前的分析是正确的 + } + + visited.insert(inst); + currentPath.insert(inst); + + // 1. 检查是否有副作用(逃逸点) + if (sideEffectAnalysis && sideEffectAnalysis->hasSideEffect(inst)) { + if (DEBUG && visited.size() < 10) { + std::cout << " 指令有副作用,是逃逸点" << std::endl; + } + currentPath.erase(inst); + return false; // 有副作用的指令是逃逸点 + } + + // 2. 检查指令的所有使用 + bool allUsesAreDead = true; + for (auto use : inst->getUses()) { + auto user = use->getUser(); + auto* userInst = dynamic_cast(user); + + if (!userInst) { + // 被非指令使用(如函数返回值),是逃逸点 + if (DEBUG && visited.size() < 10) { + std::cout << " 被非指令使用,是逃逸点" << std::endl; + } + allUsesAreDead = false; + break; + } + + // 检查使用是否在循环外(逃逸点) + if (!loop->contains(userInst->getParent())) { + if (DEBUG && visited.size() < 10) { + std::cout << " 在循环外被 " << userInst->getName() << " 使用,是逃逸点" << std::endl; + } + allUsesAreDead = false; + break; + } + + // 特殊检查:如果使用者是循环的退出条件,需要进一步分析 + // 只有当循环有副作用时,才将用于退出条件的归纳变量视为逃逸点 + 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 (!isInstructionUseChainDeadRecursively(userInst, loop, visited, currentPath)) { + allUsesAreDead = false; + break; // 找到逃逸点,不需要继续分析 + } + } + + currentPath.erase(inst); + + if (allUsesAreDead && DEBUG && visited.size() < 10) { + std::cout << " 指令 " << inst->getName() << " 的所有使用都是死代码" << std::endl; + } + + return allUsesAreDead; +} + +// 检查循环是否有副作用 +bool InductionVariableEliminationContext::loopHasSideEffects(Loop* loop) { + // 遍历循环中的所有指令,检查是否有副作用 + for (BasicBlock* bb : loop->getBlocks()) { + for (auto& inst : bb->getInstructions()) { + Instruction* instPtr = inst.get(); + + // 使用副作用分析(如果可用) + if (sideEffectAnalysis && sideEffectAnalysis->hasSideEffect(instPtr)) { + if (DEBUG) { + std::cout << " 循环中发现有副作用的指令: " << instPtr->getName() << std::endl; + } + return true; + } + + // 如果没有副作用分析,使用保守的判断 + if (!sideEffectAnalysis) { + auto kind = instPtr->getKind(); + // 这些指令通常有副作用 + if (kind == Instruction::Kind::kCall || + kind == Instruction::Kind::kStore || + kind == Instruction::Kind::kReturn) { + if (DEBUG) { + std::cout << " 循环中发现潜在有副作用的指令: " << instPtr->getName() << std::endl; + } + return true; + } + } + } + } + + if (DEBUG) { + std::cout << " 循环 " << loop->getName() << " 无副作用" << std::endl; + } + return false; // 循环无副作用 +} + +// 检查指令是否被用于循环退出条件 +bool InductionVariableEliminationContext::isUsedInLoopExitCondition(Instruction* inst, Loop* loop) { + // 检查指令是否被循环的退出条件使用 + for (BasicBlock* exitingBB : loop->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) == inst) { + if (DEBUG) { + std::cout << " 指令 " << inst->getName() << " 用于循环退出条件" << std::endl; + } + return true; + } + } + + // 对于条件分支,还需要检查条件指令的操作数 + if (terminator->getKind() == Instruction::Kind::kCondBr) { + auto* condBr = dynamic_cast(terminator); + if (condBr) { + Value* condition = condBr->getCondition(); + if (condition == inst) { + if (DEBUG) { + std::cout << " 指令 " << inst->getName() << " 是循环条件" << std::endl; + } + return true; + } + + // 递归检查条件指令的操作数(比如比较指令) + auto* condInst = dynamic_cast(condition); + if (condInst) { + for (size_t i = 0; i < condInst->getNumOperands(); ++i) { + if (condInst->getOperand(i) == inst) { + if (DEBUG) { + std::cout << " 指令 " << inst->getName() << " 用于循环条件的操作数" << std::endl; + } + return true; + } + } + } + } + } + } + } + } + + return false; +} + + +// 检查指令的结果是否未被有效使用 +bool InductionVariableEliminationContext::isInstructionResultUnused(Instruction* inst, Loop* loop) { + // 检查指令的所有使用 + if (inst->getUses().empty()) { + return true; // 没有使用,肯定是未使用 + } + + for (auto use : inst->getUses()) { + auto user = use->getUser(); + auto* userInst = dynamic_cast(user); + + if (!userInst) { + return false; // 被非指令使用,认为是有效使用 + } + + // 如果在循环外被使用,认为是有效使用 + if (!loop->contains(userInst->getParent())) { + return false; + } + + // 递归检查使用这个结果的指令是否也是死代码 + // 为了避免无限递归,限制递归深度 + if (!isInstructionEffectivelyDead(userInst, loop, 3)) { + return false; // 存在有效使用 + } + } + + return true; // 所有使用都是无效的 +} + +// 检查store指令是否存储到死地址(利用别名分析) +bool InductionVariableEliminationContext::isStoreToDeadLocation(StoreInst* store, Loop* loop) { + if (!aliasAnalysis) { + return false; // 没有别名分析,保守返回false + } + + Value* storePtr = store->getPointer(); + + // 检查是否存储到局部临时变量且该变量在循环外不被读取 + const MemoryLocation* memLoc = aliasAnalysis->getMemoryLocation(storePtr); + if (!memLoc) { + return false; // 无法确定内存位置 + } + + // 如果是局部数组且只在循环内被访问 + if (memLoc->isLocalArray) { + // 检查该内存位置是否在循环外被读取 + for (auto* accessInst : memLoc->accessInsts) { + if (accessInst->getKind() == Instruction::Kind::kLoad) { + if (!loop->contains(accessInst->getParent())) { + return false; // 在循环外被读取,不是死存储 + } + } + } + + if (DEBUG) { + std::cout << " 存储到局部数组且仅在循环内访问" << std::endl; + } + return true; // 存储到仅循环内访问的局部数组 + } + + return false; +} + +// 检查指令是否有效死代码(带递归深度限制) +bool InductionVariableEliminationContext::isInstructionEffectivelyDead(Instruction* inst, Loop* loop, int maxDepth) { + if (maxDepth <= 0) { + return false; // 达到递归深度限制,保守返回false + } + + // 利用副作用分析 + if (sideEffectAnalysis && sideEffectAnalysis->hasSideEffect(inst)) { + return false; // 有副作用的指令不是死代码 + } + + // 检查特殊指令类型 + switch (inst->getKind()) { + case Instruction::Kind::kStore: + // Store指令可能是死存储 + return isStoreToDeadLocation(dynamic_cast(inst), loop); + + case Instruction::Kind::kCall: + // 函数调用通常有副作用 + if (sideEffectAnalysis) { + return !sideEffectAnalysis->hasSideEffect(inst); + } + return false; // 保守地认为函数调用有效果 + + case Instruction::Kind::kReturn: + case Instruction::Kind::kBr: + case Instruction::Kind::kCondBr: + // 控制流指令不是死代码 + return false; + + default: + // 其他指令检查其使用是否有效 + break; + } + + // 检查指令的使用 + if (inst->getUses().empty()) { + return true; // 没有使用的纯指令是死代码 + } + + // 递归检查所有使用 + for (auto use : inst->getUses()) { auto user = use->getUser(); auto* userInst = dynamic_cast(user); @@ -201,35 +516,180 @@ bool InductionVariableEliminationContext::isUsedOnlyForSelfUpdate(PhiInst* phiIn 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; // 有非自更新的使用 + // 递归检查使用者 + if (!isInstructionEffectivelyDead(userInst, loop, maxDepth - 1)) { + return false; // 存在有效使用 } } - return true; // 只用于自身更新 + return true; // 所有使用都是死代码 +} + +// 原有的函数保持兼容,但现在使用增强的死代码分析 +bool InductionVariableEliminationContext::isInstructionDeadOrInternalOnly(Instruction* inst, Loop* loop) { + return isInstructionEffectivelyDead(inst, loop, 5); +} + +// 检查store指令是否有后续的load操作 +bool InductionVariableEliminationContext::hasSubsequentLoad(StoreInst* store, Loop* loop) { + if (!aliasAnalysis) { + // 没有别名分析,保守地假设有后续读取 + return true; + } + + Value* storePtr = store->getPointer(); + const MemoryLocation* storeLoc = aliasAnalysis->getMemoryLocation(storePtr); + + if (!storeLoc) { + // 无法确定内存位置,保守处理 + return true; + } + + // 在循环中和循环后查找对同一位置的load操作 + std::vector blocksToCheck; + + // 添加循环内的所有基本块 + for (auto* bb : loop->getBlocks()) { + blocksToCheck.push_back(bb); + } + + // 添加循环的退出块 + auto exitBlocks = loop->getExitBlocks(); + for (auto* exitBB : exitBlocks) { + blocksToCheck.push_back(exitBB); + } + + // 搜索load操作 + for (auto* bb : blocksToCheck) { + for (auto& inst : bb->getInstructions()) { + if (inst->getKind() == Instruction::Kind::kLoad) { + LoadInst* loadInst = static_cast(inst.get()); + Value* loadPtr = loadInst->getPointer(); + const MemoryLocation* loadLoc = aliasAnalysis->getMemoryLocation(loadPtr); + + if (loadLoc && aliasAnalysis->queryAlias(storePtr, loadPtr) != AliasType::NO_ALIAS) { + // 找到可能读取同一位置的load操作 + if (DEBUG) { + std::cout << " 找到后续load操作: " << loadInst->getName() << std::endl; + } + return true; + } + } + } + } + + // 检查是否通过函数调用间接访问 + for (auto* bb : blocksToCheck) { + for (auto& inst : bb->getInstructions()) { + if (inst->getKind() == Instruction::Kind::kCall) { + CallInst* callInst = static_cast(inst.get()); + if (callInst && sideEffectAnalysis && sideEffectAnalysis->hasSideEffect(callInst)) { + // 函数调用可能间接读取内存 + if (DEBUG) { + std::cout << " 函数调用可能读取内存: " << callInst->getName() << std::endl; + } + return true; + } + } + } + } + + if (DEBUG) { + std::cout << " 未找到后续load操作" << std::endl; + } + return false; // 没有找到后续读取 +} + +// 检查指令是否在循环外有使用 +bool InductionVariableEliminationContext::hasUsageOutsideLoop(Instruction* inst, Loop* loop) { + for (auto use : inst->getUses()) { + auto user = use->getUser(); + auto* userInst = dynamic_cast(user); + + if (!userInst) { + // 被非指令使用,可能在循环外 + return true; + } + + if (!loop->contains(userInst->getParent())) { + // 在循环外被使用 + if (DEBUG) { + std::cout << " 指令 " << inst->getName() << " 在循环外被 " + << userInst->getName() << " 使用" << std::endl; + } + return true; + } + } + + return false; // 没有循环外使用 +} + +// 检查store指令是否在循环外有后续的load操作 +bool InductionVariableEliminationContext::hasSubsequentLoadOutsideLoop(StoreInst* store, Loop* loop) { + if (!aliasAnalysis) { + // 没有别名分析,保守地假设有后续读取 + return true; + } + + Value* storePtr = store->getPointer(); + + // 检查循环的退出块及其后继 + auto exitBlocks = loop->getExitBlocks(); + std::set visitedBlocks; + + for (auto* exitBB : exitBlocks) { + if (hasLoadInSubtree(exitBB, storePtr, visitedBlocks)) { + if (DEBUG) { + std::cout << " 找到循环外的后续load操作" << std::endl; + } + return true; + } + } + + return false; // 没有找到循环外的后续读取 +} + +// 递归检查基本块子树中是否有对指定位置的load操作 +bool InductionVariableEliminationContext::hasLoadInSubtree(BasicBlock* bb, Value* ptr, std::set& visited) { + if (visited.count(bb) > 0) { + return false; // 已经访问过,避免无限循环 + } + visited.insert(bb); + + // 检查当前基本块中的指令 + for (auto& inst : bb->getInstructions()) { + if (inst->getKind() == Instruction::Kind::kLoad) { + LoadInst* loadInst = static_cast(inst.get()); + if (aliasAnalysis && aliasAnalysis->queryAlias(ptr, loadInst->getPointer()) != AliasType::NO_ALIAS) { + return true; // 找到了对相同或别名位置的load + } + } else if (inst->getKind() == Instruction::Kind::kCall) { + // 函数调用可能间接读取内存 + CallInst* callInst = static_cast(inst.get()); + if (sideEffectAnalysis && sideEffectAnalysis->hasSideEffect(callInst)) { + return true; // 保守地认为函数调用可能读取内存 + } + } + } + + // 递归检查后继基本块(限制深度以避免过度搜索) + static int searchDepth = 0; + if (searchDepth < 10) { // 限制搜索深度 + searchDepth++; + for (auto* succ : bb->getSuccessors()) { + if (hasLoadInSubtree(succ, ptr, visited)) { + searchDepth--; + return true; + } + } + searchDepth--; + } + + return false; } std::vector InductionVariableEliminationContext::collectRelatedInstructions( diff --git a/src/midend/Pass/Pass.cpp b/src/midend/Pass/Pass.cpp index 3686bd2..440ce0c 100644 --- a/src/midend/Pass/Pass.cpp +++ b/src/midend/Pass/Pass.cpp @@ -140,9 +140,9 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR this->clearPasses(); this->addPass(&LoopNormalizationPass::ID); + this->addPass(&InductionVariableElimination::ID); this->addPass(&LICM::ID); this->addPass(&LoopStrengthReduction::ID); - this->addPass(&InductionVariableElimination::ID); this->run(); if(DEBUG) {