[midend-Loop-IVE]循环归纳变量消除逻辑重构,修改运行顺序
This commit is contained in:
@ -6,6 +6,7 @@
|
||||
#include "Loop.h"
|
||||
#include "Dom.h"
|
||||
#include "SideEffectAnalysis.h"
|
||||
#include "AliasAnalysis.h"
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
@ -53,6 +54,7 @@ private:
|
||||
LoopCharacteristicsResult* loopCharacteristics = nullptr;
|
||||
DominatorTree* dominatorTree = nullptr;
|
||||
SideEffectAnalysisResult* sideEffectAnalysis = nullptr;
|
||||
AliasAnalysisResult* aliasAnalysis = nullptr;
|
||||
|
||||
// 死归纳变量存储
|
||||
std::vector<std::unique_ptr<DeadInductionVariable>> 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<Instruction*>& visited,
|
||||
std::set<Instruction*>& 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<BasicBlock*>& visited);
|
||||
|
||||
/**
|
||||
* 收集与归纳变量相关的所有指令
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include "Loop.h"
|
||||
#include "Dom.h"
|
||||
#include "SideEffectAnalysis.h"
|
||||
#include "AliasAnalysis.h"
|
||||
#include "SysYIROptUtils.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
@ -43,6 +44,7 @@ void InductionVariableElimination::getAnalysisUsage(std::set<void*>& 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<AliasAnalysisResult, SysYAliasAnalysisPass>(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<Instruction*> visitedInstructions;
|
||||
std::set<Instruction*> currentPath; // 用于检测循环依赖
|
||||
|
||||
// 核心逻辑:递归分析使用链,寻找任何"逃逸点"
|
||||
return isInstructionUseChainDeadRecursively(phiInst, loop, visitedInstructions, currentPath);
|
||||
}
|
||||
|
||||
// 递归分析指令的使用链是否都是死代码
|
||||
bool InductionVariableEliminationContext::isInstructionUseChainDeadRecursively(
|
||||
Instruction* inst, Loop* loop,
|
||||
std::set<Instruction*>& visited,
|
||||
std::set<Instruction*>& 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<Instruction*>(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<CondBrInst*>(terminator);
|
||||
if (condBr) {
|
||||
Value* condition = condBr->getCondition();
|
||||
if (condition == inst) {
|
||||
if (DEBUG) {
|
||||
std::cout << " 指令 " << inst->getName() << " 是循环条件" << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 递归检查条件指令的操作数(比如比较指令)
|
||||
auto* condInst = dynamic_cast<Instruction*>(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<Instruction*>(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<StoreInst*>(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<Instruction*>(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<BinaryInst*>(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<BasicBlock*> 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<LoadInst*>(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<CallInst*>(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<Instruction*>(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<BasicBlock*> 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<BasicBlock*>& 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<LoadInst*>(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<CallInst*>(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<Instruction*> InductionVariableEliminationContext::collectRelatedInstructions(
|
||||
|
||||
@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user