918 lines
30 KiB
C++
918 lines
30 KiB
C++
#include "InductionVariableElimination.h"
|
||
#include "LoopCharacteristics.h"
|
||
#include "Loop.h"
|
||
#include "Dom.h"
|
||
#include "SideEffectAnalysis.h"
|
||
#include "AliasAnalysis.h"
|
||
#include "SysYIROptUtils.h"
|
||
#include <iostream>
|
||
#include <algorithm>
|
||
|
||
// 使用全局调试开关
|
||
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<void*>& analysisDependencies,
|
||
std::set<void*>& analysisInvalidations) const {
|
||
// 依赖的分析
|
||
analysisDependencies.insert(&LoopAnalysisPass::ID);
|
||
analysisDependencies.insert(&LoopCharacteristicsPass::ID);
|
||
analysisDependencies.insert(&DominatorTreeAnalysisPass::ID);
|
||
analysisDependencies.insert(&SysYSideEffectAnalysisPass::ID);
|
||
analysisDependencies.insert(&SysYAliasAnalysisPass::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<LoopAnalysisResult, LoopAnalysisPass>(F);
|
||
if (!loopAnalysis || !loopAnalysis->hasLoops()) {
|
||
if (DEBUG) {
|
||
std::cout << " No loops found, skipping induction variable elimination" << std::endl;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
loopCharacteristics = AM.getAnalysisResult<LoopCharacteristicsResult, LoopCharacteristicsPass>(F);
|
||
if (!loopCharacteristics) {
|
||
if (DEBUG) {
|
||
std::cout << " LoopCharacteristics analysis not available" << std::endl;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
dominatorTree = AM.getAnalysisResult<DominatorTree, DominatorTreeAnalysisPass>(F);
|
||
if (!dominatorTree) {
|
||
if (DEBUG) {
|
||
std::cout << " DominatorTree analysis not available" << std::endl;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
sideEffectAnalysis = AM.getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>();
|
||
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;
|
||
}
|
||
}
|
||
|
||
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:识别死归纳变量
|
||
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();
|
||
}
|
||
|
||
modified |= SysYIROptUtils::eliminateRedundantPhisInFunction(F);
|
||
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<DeadInductionVariable>
|
||
InductionVariableEliminationContext::isDeadInductionVariable(const InductionVarInfo* iv, Loop* loop) {
|
||
// 获取 phi 指令
|
||
auto* phiInst = dynamic_cast<PhiInst*>(iv->div);
|
||
if (!phiInst) {
|
||
return nullptr; // 不是 phi 指令
|
||
}
|
||
|
||
// 新的逻辑:递归分析整个use-def链,判断是否有真实的使用
|
||
if (!isPhiInstructionDeadRecursively(phiInst, loop)) {
|
||
return nullptr; // 有真实的使用,不能删除
|
||
}
|
||
|
||
// 创建死归纳变量信息
|
||
auto deadIV = std::make_unique<DeadInductionVariable>(phiInst, loop);
|
||
deadIV->relatedInsts = collectRelatedInstructions(phiInst, loop);
|
||
|
||
return deadIV;
|
||
}
|
||
|
||
// 递归分析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; // 有副作用的指令是逃逸点
|
||
}
|
||
|
||
// 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()) {
|
||
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 (DEBUG && visited.size() < 10) {
|
||
std::cout << " 被用于循环退出条件,是逃逸点(避免破坏循环语义)" << std::endl;
|
||
}
|
||
allUsesAreDead = false;
|
||
break;
|
||
}
|
||
|
||
// 递归分析使用者的使用链
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 重要修复:检查是否为嵌套循环的外层循环
|
||
// 如果当前循环包含其他循环,那么它有潜在的副作用
|
||
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;
|
||
}
|
||
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);
|
||
|
||
if (!userInst) {
|
||
return false; // 被非指令使用
|
||
}
|
||
|
||
if (!loop->contains(userInst->getParent())) {
|
||
return false; // 在循环外被使用
|
||
}
|
||
|
||
// 递归检查使用者
|
||
if (!isInstructionEffectivelyDead(userInst, loop, maxDepth - 1)) {
|
||
return false; // 存在有效使用
|
||
}
|
||
}
|
||
|
||
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(
|
||
PhiInst* phiInst, Loop* loop) {
|
||
std::vector<Instruction*> relatedInsts;
|
||
|
||
// 收集所有与该归纳变量相关的指令
|
||
for (auto use : phiInst->getUses()) {
|
||
auto user = use->getUser();
|
||
auto* userInst = dynamic_cast<Instruction*>(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
|