diff --git a/src/include/midend/Pass/Analysis/AliasAnalysis.h b/src/include/midend/Pass/Analysis/AliasAnalysis.h index 0adc4c5..e8dc9ef 100644 --- a/src/include/midend/Pass/Analysis/AliasAnalysis.h +++ b/src/include/midend/Pass/Analysis/AliasAnalysis.h @@ -186,6 +186,7 @@ private: // ========== 别名关系推断 ========== AliasType analyzeAliasBetween(MemoryLocation* loc1, MemoryLocation* loc2); + AliasType compareIndices(MemoryLocation* loc1, MemoryLocation* loc2); AliasType compareLocalArrays(MemoryLocation* loc1, MemoryLocation* loc2); AliasType compareParameters(MemoryLocation* loc1, MemoryLocation* loc2); AliasType compareWithGlobal(MemoryLocation* loc1, MemoryLocation* loc2); diff --git a/src/include/midend/Pass/Optimize/DCE.h b/src/include/midend/Pass/Optimize/DCE.h index 41bc223..cfb0966 100644 --- a/src/include/midend/Pass/Optimize/DCE.h +++ b/src/include/midend/Pass/Optimize/DCE.h @@ -4,6 +4,8 @@ #include "IR.h" #include "SysYIROptUtils.h" #include "Dom.h" +#include "AliasAnalysis.h" +#include "SideEffectAnalysis.h" #include #include @@ -25,8 +27,12 @@ public: private: // 存储活跃指令的集合 std::unordered_set alive_insts; + // 别名分析结果 + AliasAnalysisResult* aliasAnalysis = nullptr; + // 副作用分析结果 + SideEffectAnalysisResult* sideEffectAnalysis = nullptr; - // 判断指令是否是“天然活跃”的(即总是保留的) + // 判断指令是否是"天然活跃"的(即总是保留的) // inst: 要检查的指令 // 返回值: 如果指令是天然活跃的,则为true,否则为false bool isAlive(Instruction* inst); @@ -34,6 +40,9 @@ private: // 递归地将活跃指令及其依赖加入到 alive_insts 集合中 // inst: 要标记为活跃的指令 void addAlive(Instruction* inst); + + // 检查Store指令是否可能有副作用(通过别名分析) + bool mayHaveSideEffect(StoreInst* store); }; // DCE 优化遍类,继承自 OptimizationPass diff --git a/src/include/midend/Pass/Optimize/SCCP.h b/src/include/midend/Pass/Optimize/SCCP.h index 667ee51..cd9e68f 100644 --- a/src/include/midend/Pass/Optimize/SCCP.h +++ b/src/include/midend/Pass/Optimize/SCCP.h @@ -3,6 +3,8 @@ #include "IR.h" #include "Pass.h" #include "SysYIROptUtils.h" +#include "AliasAnalysis.h" +#include "SideEffectAnalysis.h" #include #include #include @@ -63,6 +65,8 @@ struct SSAPValue { class SCCPContext { private: IRBuilder *builder; // IR 构建器,用于插入指令和创建常量 + AliasAnalysisResult *aliasAnalysis; // 别名分析结果 + SideEffectAnalysisResult *sideEffectAnalysis; // 副作用分析结果 // 工作列表 // 存储需要重新评估的指令 @@ -92,6 +96,14 @@ private: SSAPValue ComputeConstant(BinaryInst *binaryinst, SSAPValue lhsVal, SSAPValue rhsVal); // 辅助函数:对一元操作进行常量折叠 SSAPValue ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVal); + // 辅助函数:检查是否为已知的纯函数 + bool isKnownPureFunction(const std::string &funcName) const; + // 辅助函数:计算纯函数的常量结果 + SSAPValue computePureFunctionResult(CallInst *call, const std::vector &argValues); + // 辅助函数:查找存储到指定位置的常量值 + SSAPValue findStoredConstantValue(Value *ptr, BasicBlock *currentBB); + // 辅助函数:动态检查数组访问是否为常量索引(考虑SCCP状态) + bool hasRuntimeConstantAccess(Value *ptr); // 主要优化阶段 // 阶段1: 常量传播与折叠 @@ -117,7 +129,13 @@ private: void RemovePhiIncoming(BasicBlock *phiParentBB, BasicBlock *removedPred); public: - SCCPContext(IRBuilder *builder) : builder(builder) {} + SCCPContext(IRBuilder *builder) : builder(builder), aliasAnalysis(nullptr), sideEffectAnalysis(nullptr) {} + + // 设置别名分析结果 + void setAliasAnalysis(AliasAnalysisResult *aa) { aliasAnalysis = aa; } + + // 设置副作用分析结果 + void setSideEffectAnalysis(SideEffectAnalysisResult *sea) { sideEffectAnalysis = sea; } // 运行 SCCP 优化 void run(Function *func, AnalysisManager &AM); diff --git a/src/midend/Pass/Analysis/AliasAnalysis.cpp b/src/midend/Pass/Analysis/AliasAnalysis.cpp index ae363cf..062dee4 100644 --- a/src/midend/Pass/Analysis/AliasAnalysis.cpp +++ b/src/midend/Pass/Analysis/AliasAnalysis.cpp @@ -251,6 +251,9 @@ void SysYAliasAnalysisPass::analyzeMemoryType(MemoryLocation* location) { void SysYAliasAnalysisPass::analyzeIndexPattern(MemoryLocation* location) { // 分析GEP指令的索引模式 if (auto* gepInst = dynamic_cast(location->accessPointer)) { + // 初始化为true,如果发现非常量索引则设为false + location->hasConstantIndices = true; + // 收集所有索引 for (unsigned i = 0; i < gepInst->getNumIndices(); ++i) { Value* index = gepInst->getIndex(i); @@ -262,11 +265,6 @@ void SysYAliasAnalysisPass::analyzeIndexPattern(MemoryLocation* location) { } } - // 如果没有非常量索引,则为常量访问 - if (location->indices.empty()) { - location->hasConstantIndices = true; - } - // 检查是否包含循环变量 Function* containingFunc = nullptr; if (auto* inst = dynamic_cast(location->basePointer)) { @@ -289,9 +287,15 @@ void SysYAliasAnalysisPass::analyzeIndexPattern(MemoryLocation* location) { AliasType SysYAliasAnalysisPass::analyzeAliasBetween(MemoryLocation* loc1, MemoryLocation* loc2) { // 分析两个内存位置之间的别名关系 - // 1. 相同基指针的自别名 + // 1. 相同基指针的情况需要进一步分析索引 if (loc1->basePointer == loc2->basePointer) { - return AliasType::SELF_ALIAS; + // 如果是同一个访问指针,那就是完全相同的内存位置 + if (loc1->accessPointer == loc2->accessPointer) { + return AliasType::SELF_ALIAS; + } + + // 相同基指针但不同访问指针,需要比较索引 + return compareIndices(loc1, loc2); } // 2. 不同类型的内存位置 @@ -310,6 +314,46 @@ AliasType SysYAliasAnalysisPass::analyzeAliasBetween(MemoryLocation* loc1, Memor return compareMixedTypes(loc1, loc2); } +AliasType SysYAliasAnalysisPass::compareIndices(MemoryLocation* loc1, MemoryLocation* loc2) { + // 比较相同基指针下的不同索引访问 + + // 如果都有常量索引,可以精确比较 + if (loc1->hasConstantIndices && loc2->hasConstantIndices) { + // 比较索引数量 + if (loc1->indices.size() != loc2->indices.size()) { + return AliasType::NO_ALIAS; + } + + // 逐个比较索引值 + for (size_t i = 0; i < loc1->indices.size(); ++i) { + Value* idx1 = loc1->indices[i]; + Value* idx2 = loc2->indices[i]; + + // 都是常量,比较值 + auto* const1 = dynamic_cast(idx1); + auto* const2 = dynamic_cast(idx2); + + if (const1 && const2) { + int val1 = std::get(const1->getVal()); + int val2 = std::get(const2->getVal()); + + if (val1 != val2) { + return AliasType::NO_ALIAS; // 不同常量索引,确定无别名 + } + } else { + // 不是常量,无法确定 + return AliasType::POSSIBLE_ALIAS; + } + } + + // 所有索引都相同 + return AliasType::SELF_ALIAS; + } + + // 如果有非常量索引,保守估计 + return AliasType::POSSIBLE_ALIAS; +} + AliasType SysYAliasAnalysisPass::compareLocalArrays(MemoryLocation* loc1, MemoryLocation* loc2) { // 不同局部数组不别名 return AliasType::NO_ALIAS; diff --git a/src/midend/Pass/Optimize/DCE.cpp b/src/midend/Pass/Optimize/DCE.cpp index 2da1873..7f95b96 100644 --- a/src/midend/Pass/Optimize/DCE.cpp +++ b/src/midend/Pass/Optimize/DCE.cpp @@ -1,9 +1,9 @@ -#include "DCE.h" // 包含DCE遍的头文件 -#include "IR.h" // 包含IR相关的定义 -#include "SysYIROptUtils.h" // 包含SysY IR优化工具类的定义 -#include // 用于断言 -#include // 用于调试输出 -#include // 包含set,虽然DCEContext内部用unordered_set,但这里保留 +#include "DCE.h" +#include "SysYIROptUtils.h" +#include "SideEffectAnalysis.h" +#include +#include +#include namespace sysy { @@ -17,10 +17,26 @@ void *DCE::ID = (void *)&DCE::ID; // DCEContext 的 run 方法实现 void DCEContext::run(Function *func, AnalysisManager *AM, bool &changed) { + // 获取别名分析结果 + if (AM) { + aliasAnalysis = AM->getAnalysisResult(func); + // 获取副作用分析结果 + sideEffectAnalysis = AM->getAnalysisResult(func); + + if (DEBUG) { + if (aliasAnalysis) { + std::cout << "DCE: Using alias analysis results" << std::endl; + } + if (sideEffectAnalysis) { + std::cout << "DCE: Using side effect analysis results" << std::endl; + } + } + } + // 清空活跃指令集合,确保每次运行都是新的状态 alive_insts.clear(); - // 第一次遍历:扫描所有指令,识别“天然活跃”的指令并将其及其依赖标记为活跃 + // 第一次遍历:扫描所有指令,识别"天然活跃"的指令并将其及其依赖标记为活跃 // 使用 func->getBasicBlocks() 获取基本块列表,保留用户风格 auto basicBlocks = func->getBasicBlocks(); for (auto &basicBlock : basicBlocks) { @@ -51,7 +67,7 @@ void DCEContext::run(Function *func, AnalysisManager *AM, bool &changed) { // 如果指令不在活跃集合中,则删除它。 // 分支和返回指令由 isAlive 处理,并会被保留。 if (alive_insts.count(currentInst) == 0) { - instIter = SysYIROptUtils::usedelete(instIter); // 删除后返回下一个迭代器 + instIter = SysYIROptUtils::usedelete(instIter); // 删除后返回下一个迭代器 changed = true; // 标记 IR 已被修改 } else { ++instIter; // 指令活跃,移动到下一个 @@ -60,20 +76,58 @@ void DCEContext::run(Function *func, AnalysisManager *AM, bool &changed) { } } -// 判断指令是否是“天然活跃”的实现 +// 判断指令是否是"天然活跃"的实现 // 只有具有副作用的指令(如存储、函数调用、原子操作) // 和控制流指令(如分支、返回)是天然活跃的。 bool DCEContext::isAlive(Instruction *inst) { - // TODO: 后续程序并发考虑原子操作 - // 其结果不被其他指令使用的指令(例如 StoreInst, BranchInst, ReturnInst)。 - // dynamic_cast(inst) 检查是否是函数调用指令, - // 函数调用通常有副作用。 - // 终止指令 (BranchInst, ReturnInst) 必须是活跃的,因为它控制了程序的执行流程。 - // 保留用户提供的 isAlive 逻辑 - bool isBranchOrReturn = inst->isBranch() || inst->isReturn(); - bool isCall = inst->isCall(); - bool isStoreOrMemset = inst->isStore() || inst->isMemset(); - return isBranchOrReturn || isCall || isStoreOrMemset; + // 终止指令 (BranchInst, ReturnInst) 必须是活跃的,因为它控制了程序的执行流程 + if (inst->isBranch() || inst->isReturn()) { + return true; + } + + // 使用副作用分析来判断指令是否有副作用 + if (sideEffectAnalysis && sideEffectAnalysis->hasSideEffect(inst)) { + return true; + } + + // 特殊处理Store指令:使用别名分析进行更精确的判断 + if (inst->isStore()) { + auto* storeInst = static_cast(inst); + return mayHaveSideEffect(storeInst); + } + + // 特殊处理Memset指令:总是保留(因为它修改内存) + if (inst->isMemset()) { + return true; + } + + // 函数调用指令:总是保留(可能有未知副作用) + if (inst->isCall()) { + return true; + } + + // 其他指令(算术、逻辑、Load等):无副作用,可以删除 + return false; +} + +// 检查Store指令是否可能有副作用(通过别名分析) +bool DCEContext::mayHaveSideEffect(StoreInst* store) { + if (!aliasAnalysis) { + // 没有别名分析结果时,保守地认为所有store都有副作用 + return true; + } + + Value* storePtr = store->getPointer(); + + // 如果是对本地数组的存储且访问模式是常量,可能可以安全删除 + if (aliasAnalysis->isLocalArray(storePtr)) { + // 检查是否有其他指令可能读取这个位置 + // 这里需要更复杂的活性分析,暂时保守处理 + return true; // 保守地保留所有本地数组的存储 + } + + // 对全局变量、函数参数等的存储总是有副作用 + return true; } // 递归地将活跃指令及其依赖加入到 alive_insts 集合中 @@ -102,7 +156,6 @@ void DCEContext::addAlive(Instruction *inst) { // DCE 遍的 runOnFunction 方法实现 bool DCE::runOnFunction(Function *func, AnalysisManager &AM) { - DCEContext ctx; bool changed = false; ctx.run(func, &AM, changed); // 运行 DCE 优化 @@ -120,7 +173,11 @@ bool DCE::runOnFunction(Function *func, AnalysisManager &AM) { // 声明DCE遍的分析依赖和失效信息 void DCE::getAnalysisUsage(std::set &analysisDependencies, std::set &analysisInvalidations) const { - // DCE不依赖特定的分析结果,它通过遍历和副作用判断来工作。 + // DCE依赖别名分析来更精确地判断Store指令的副作用 + analysisDependencies.insert(&SysYAliasAnalysisPass::ID); + + // DCE依赖副作用分析来判断指令是否有副作用 + analysisDependencies.insert(&SysYSideEffectAnalysisPass::ID); // DCE会删除指令,这会影响许多分析结果。 // 至少,它会影响活跃性分析、支配树、控制流图(如果删除导致基本块为空并被合并)。 diff --git a/src/midend/Pass/Optimize/Mem2Reg.cpp b/src/midend/Pass/Optimize/Mem2Reg.cpp index 7570b30..f1c7d59 100644 --- a/src/midend/Pass/Optimize/Mem2Reg.cpp +++ b/src/midend/Pass/Optimize/Mem2Reg.cpp @@ -1,6 +1,8 @@ #include "Mem2Reg.h" // 包含 Mem2Reg 遍的头文件 #include "Dom.h" // 包含支配树分析的头文件 #include "Liveness.h" +#include "AliasAnalysis.h" // 包含别名分析 +#include "SideEffectAnalysis.h" // 包含副作用分析 #include "IR.h" // 包含 IR 相关的定义 #include "SysYIROptUtils.h" #include // 用于断言 @@ -420,8 +422,9 @@ void Mem2Reg::getAnalysisUsage(std::set &analysisDependencies, std::set< // 因此,它会使许多分析结果失效。 analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树可能受影响 analysisInvalidations.insert(&LivenessAnalysisPass::ID); // 活跃性分析肯定失效 + analysisInvalidations.insert(&SysYAliasAnalysisPass::ID); // 别名分析必须失效,因为Mem2Reg改变了内存访问模式 + analysisInvalidations.insert(&SysYSideEffectAnalysisPass::ID); // 副作用分析也可能失效 // analysisInvalidations.insert(&LoopInfoAnalysisPass::ID); // 循环信息可能失效 - // analysisInvalidations.insert(&SideEffectInfoAnalysisPass::ID); // 副作用分析可能失效 // 其他所有依赖于数据流或 IR 结构的分析都可能失效。 } diff --git a/src/midend/Pass/Optimize/SCCP.cpp b/src/midend/Pass/Optimize/SCCP.cpp index 33d716f..d88136d 100644 --- a/src/midend/Pass/Optimize/SCCP.cpp +++ b/src/midend/Pass/Optimize/SCCP.cpp @@ -1,10 +1,12 @@ #include "SCCP.h" #include "Dom.h" #include "Liveness.h" +#include "SideEffectAnalysis.h" #include #include #include // For std::fmod, std::fabs #include // For std::numeric_limits +#include // For std::set in isKnownPureFunction namespace sysy { @@ -263,6 +265,192 @@ SSAPValue SCCPContext::ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVa return SSAPValue(LatticeVal::Bottom); } +// 辅助函数:检查是否为已知的纯函数 +bool SCCPContext::isKnownPureFunction(const std::string &funcName) const { + // SysY中一些已知的纯函数(不修改全局状态,结果只依赖参数) + static const std::set knownPureFunctions = { + // 数学函数(如果有的话) + // "abs", "fabs", "sqrt", "sin", "cos" + // SysY标准中基本没有纯函数,大多数都有I/O副作用 + }; + + return knownPureFunctions.find(funcName) != knownPureFunctions.end(); +} + +// 辅助函数:计算纯函数的常量结果 +SSAPValue SCCPContext::computePureFunctionResult(CallInst *call, const std::vector &argValues) { + Function *calledFunc = call->getCallee(); + if (!calledFunc) { + return SSAPValue(LatticeVal::Bottom); + } + + std::string funcName = calledFunc->getName(); + + // 目前SysY中没有标准的纯函数,这里预留扩展空间 + // 未来可以添加数学函数的常量折叠 + /* + if (funcName == "abs" && argValues.size() == 1) { + if (argValues[0].constant_type == ValueType::Integer) { + int val = std::get(argValues[0].constantVal); + return SSAPValue(std::abs(val)); + } + } + */ + + return SSAPValue(LatticeVal::Bottom); +} + +// 辅助函数:查找存储到指定位置的常量值 +SSAPValue SCCPContext::findStoredConstantValue(Value *ptr, BasicBlock *currentBB) { + if (!aliasAnalysis) { + if (DEBUG) { + std::cout << "SCCP: No alias analysis available" << std::endl; + } + return SSAPValue(LatticeVal::Bottom); + } + + if (DEBUG) { + std::cout << "SCCP: Searching for stored constant value for ptr" << std::endl; + } + + // 从当前块的指令列表末尾向前查找最近的Store + std::vector instructions; + for (auto it = currentBB->begin(); it != currentBB->end(); ++it) { + instructions.push_back(it->get()); + } + + for (int i = instructions.size() - 1; i >= 0; --i) { + Instruction *prevInst = instructions[i]; + + if (prevInst->isStore()) { + StoreInst *storeInst = static_cast(prevInst); + Value *storePtr = storeInst->getPointer(); + + if (DEBUG) { + std::cout << "SCCP: Checking store instruction" << std::endl; + } + + // 使用别名分析检查Store是否针对相同的内存位置 + auto aliasResult = aliasAnalysis->queryAlias(ptr, storePtr); + + if (DEBUG) { + std::cout << "SCCP: Alias result: " << (int)aliasResult << std::endl; + } + + if (aliasResult == AliasType::SELF_ALIAS) { + // 找到了对相同位置的Store,获取存储的值 + Value *storedValue = storeInst->getValue(); + + if (DEBUG) { + std::cout << "SCCP: Found matching store, checking value type" << std::endl; + } + + // 检查存储的值是否为常量 + if (auto constInt = dynamic_cast(storedValue)) { + int val = std::get(constInt->getVal()); + if (DEBUG) { + std::cout << "SCCP: Found constant integer value: " << val << std::endl; + } + return SSAPValue(val); + } else if (auto constFloat = dynamic_cast(storedValue)) { + float val = std::get(constFloat->getVal()); + if (DEBUG) { + std::cout << "SCCP: Found constant float value: " << val << std::endl; + } + return SSAPValue(val); + } else { + // 存储的值不是常量,检查其SCCP状态 + SSAPValue storedState = GetValueState(storedValue); + if (storedState.state == LatticeVal::Constant) { + if (DEBUG) { + std::cout << "SCCP: Found SCCP constant value" << std::endl; + } + return storedState; + } else { + if (DEBUG) { + std::cout << "SCCP: Stored value is not constant" << std::endl; + } + } + } + + // 找到了最近的Store但不是常量,停止查找 + if (DEBUG) { + std::cout << "SCCP: Found non-constant store, stopping search" << std::endl; + } + break; + } + } + } + + if (DEBUG) { + std::cout << "SCCP: No constant value found" << std::endl; + } + return SSAPValue(LatticeVal::Bottom); +} + +// 辅助函数:动态检查数组访问是否为常量索引(考虑SCCP状态) +bool SCCPContext::hasRuntimeConstantAccess(Value *ptr) { + if (auto gep = dynamic_cast(ptr)) { + if (DEBUG) { + std::cout << "SCCP: Checking runtime constant access for GEP instruction" << std::endl; + } + + // 检查所有索引是否为常量或SCCP传播的常量 + bool allConstantIndices = true; + for (auto indexUse : gep->getIndices()) { + Value* index = indexUse->getValue(); + + // 首先检查是否为编译时常量 + if (auto constInt = dynamic_cast(index)) { + if (DEBUG) { + std::cout << "SCCP: Index is compile-time constant integer: " << std::get(constInt->getVal()) << std::endl; + } + continue; + } + if (auto constFloat = dynamic_cast(index)) { + if (DEBUG) { + std::cout << "SCCP: Index is compile-time constant float: " << std::get(constFloat->getVal()) << std::endl; + } + continue; + } + + // 检查是否为SCCP传播的常量 + SSAPValue indexState = GetValueState(index); + if (indexState.state == LatticeVal::Constant) { + if (DEBUG) { + std::cout << "SCCP: Index is SCCP constant: "; + if (indexState.constant_type == ValueType::Integer) { + std::cout << std::get(indexState.constantVal); + } else { + std::cout << std::get(indexState.constantVal); + } + std::cout << std::endl; + } + continue; + } + + // 如果任何一个索引不是常量,返回false + if (DEBUG) { + std::cout << "SCCP: Index is not constant, access is not constant" << std::endl; + } + allConstantIndices = false; + break; + } + + if (DEBUG) { + std::cout << "SCCP: hasRuntimeConstantAccess result: " << (allConstantIndices ? "true" : "false") << std::endl; + } + return allConstantIndices; + } + + // 对于非GEP指令,回退到别名分析的静态结果 + if (aliasAnalysis) { + return aliasAnalysis->hasConstantAccess(ptr); + } + + return false; +} + // 辅助函数:处理单条指令 void SCCPContext::ProcessInstruction(Instruction *inst) { SSAPValue oldState = GetValueState(inst); @@ -380,27 +568,237 @@ void SCCPContext::ProcessInstruction(Instruction *inst) { break; } case Instruction::kLoad: { - // 对于 Load 指令,除非我们有特殊的别名分析,否则假定为 Bottom - // 或者如果它加载的是一个已知常量地址的全局常量 + // 使用别名分析和副作用分析改进Load指令的处理 Value *ptr = inst->getOperand(0); + + // 首先检查是否是全局常量 if (auto globalVal = dynamic_cast(ptr)) { // 如果 GlobalValue 有初始化器,并且它是常量,我们可以传播 - // 这需要额外的逻辑来检查 globalVal 的初始化器 - // 暂时保守地设置为 Bottom + // TODO: 检查全局变量的初始化器进行常量传播 newState = SSAPValue(LatticeVal::Bottom); + } else if (aliasAnalysis && sideEffectAnalysis) { + // 使用别名分析和副作用分析进行更精确的Load分析 + if (aliasAnalysis->isLocalArray(ptr) && (aliasAnalysis->hasConstantAccess(ptr) || hasRuntimeConstantAccess(ptr))) { + // 对于局部数组的常量索引访问,检查是否有影响该位置的Store + bool mayBeModified = false; + + if (DEBUG) { + std::cout << "SCCP: Analyzing local array with constant access for modification" << std::endl; + } + + // 遍历指令所在块之前的所有指令,查找可能修改该内存位置的Store + BasicBlock *currentBB = inst->getParent(); + auto instPos = currentBB->findInstIterator(inst); + + SSAPValue foundConstantValue = SSAPValue(LatticeVal::Bottom); + bool hasFoundDefinitiveStore = false; + + for (auto it = currentBB->begin(); it != instPos; ++it) { + Instruction *prevInst = it->get(); + + if (prevInst->isStore()) { + StoreInst *storeInst = static_cast(prevInst); + Value *storePtr = storeInst->getPointer(); + + // 使用别名分析判断Store是否可能影响当前Load + auto aliasResult = aliasAnalysis->queryAlias(ptr, storePtr); + if (DEBUG) { + std::cout << "SCCP: Checking store with alias result: " << (int)aliasResult << std::endl; + } + + if (aliasResult == AliasType::SELF_ALIAS) { + // 找到对相同位置的精确Store + Value *storedValue = storeInst->getValue(); + + if (DEBUG) { + std::cout << "SCCP: Found exact store to same location, checking value" << std::endl; + } + + // 检查存储的值是否为常量 + if (auto constInt = dynamic_cast(storedValue)) { + int val = std::get(constInt->getVal()); + if (DEBUG) { + std::cout << "SCCP: Store contains constant integer: " << val << std::endl; + } + foundConstantValue = SSAPValue(val); + hasFoundDefinitiveStore = true; + // 继续遍历,查找是否有更后面的Store覆盖这个值 + } else if (auto constFloat = dynamic_cast(storedValue)) { + float val = std::get(constFloat->getVal()); + if (DEBUG) { + std::cout << "SCCP: Store contains constant float: " << val << std::endl; + } + foundConstantValue = SSAPValue(val); + hasFoundDefinitiveStore = true; + } else { + // 存储的值不是编译时常量,检查其SCCP状态 + SSAPValue storedState = GetValueState(storedValue); + if (storedState.state == LatticeVal::Constant) { + if (DEBUG) { + std::cout << "SCCP: Store contains SCCP constant" << std::endl; + } + foundConstantValue = storedState; + hasFoundDefinitiveStore = true; + } else { + if (DEBUG) { + std::cout << "SCCP: Store contains non-constant value" << std::endl; + } + // 非常量Store覆盖了之前的常量,无法传播 + foundConstantValue = SSAPValue(LatticeVal::Bottom); + hasFoundDefinitiveStore = true; + } + } + } else if (aliasResult != AliasType::NO_ALIAS) { + // 可能有别名,但不确定 + if (DEBUG) { + std::cout << "SCCP: Found store with uncertain alias, stopping propagation" << std::endl; + } + mayBeModified = true; + break; + } + } else if (prevInst->isCall()) { + // 检查函数调用是否可能修改该内存位置 + if (sideEffectAnalysis->mayModifyMemory(prevInst)) { + // 进一步检查是否可能影响局部数组 + if (!aliasAnalysis->isLocalArray(ptr) || + sideEffectAnalysis->mayModifyGlobal(prevInst)) { + mayBeModified = true; + break; + } + } + } else if (prevInst->isMemset()) { + // Memset指令可能影响内存,但只有在它在相关Store之前时才阻止常量传播 + MemsetInst *memsetInst = static_cast(prevInst); + Value *memsetPtr = memsetInst->getOperand(0); + + auto aliasResult = aliasAnalysis->queryAlias(ptr, memsetPtr); + if (aliasResult != AliasType::NO_ALIAS) { + // Memset可能影响这个位置,但我们继续查找是否有Store覆盖了memset + // 不立即设置mayBeModified = true,让后续的Store有机会覆盖 + if (DEBUG) { + std::cout << "SCCP: Found memset that may affect location, but continuing to check for overwriting stores" << std::endl; + } + } + } + } + + if (DEBUG) { + std::cout << "SCCP: mayBeModified = " << (mayBeModified ? "true" : "false") << std::endl; + std::cout << "SCCP: hasFoundDefinitiveStore = " << (hasFoundDefinitiveStore ? "true" : "false") << std::endl; + } + + if (!mayBeModified) { + if (hasFoundDefinitiveStore && foundConstantValue.state == LatticeVal::Constant) { + // 直接使用找到的常量值 + if (DEBUG) { + std::cout << "SCCP: Using found constant value from store analysis: "; + if (foundConstantValue.constant_type == ValueType::Integer) { + std::cout << std::get(foundConstantValue.constantVal); + } else { + std::cout << std::get(foundConstantValue.constantVal); + } + std::cout << std::endl; + } + newState = foundConstantValue; + } else { + // 如果没有发现修改该位置的指令,尝试用旧方法找到对应的Store值 + SSAPValue constantValue = findStoredConstantValue(ptr, inst->getParent()); + if (constantValue.state == LatticeVal::Constant) { + if (DEBUG) { + std::cout << "SCCP: Found constant value for array load using fallback method: "; + if (constantValue.constant_type == ValueType::Integer) { + std::cout << std::get(constantValue.constantVal); + } else { + std::cout << std::get(constantValue.constantVal); + } + std::cout << std::endl; + } + newState = constantValue; + } else { + newState = SSAPValue(LatticeVal::Bottom); + } + } + } else { + newState = SSAPValue(LatticeVal::Bottom); + } + } else { + // 非局部数组或非常量访问,保守处理 + newState = SSAPValue(LatticeVal::Bottom); + } } else { + // 没有分析信息时保守处理 newState = SSAPValue(LatticeVal::Bottom); } + + if (DEBUG && aliasAnalysis && sideEffectAnalysis) { + std::cout << "SCCP: Load instruction analysis - " + << (aliasAnalysis->isLocalArray(ptr) ? "local array" : "other") + << ", static constant access: " + << (aliasAnalysis->hasConstantAccess(ptr) ? "yes" : "no") + << ", runtime constant access: " + << (hasRuntimeConstantAccess(ptr) ? "yes" : "no") << std::endl; + } break; } case Instruction::kStore: // Store 指令不产生值,其 SSAPValue 不重要 newState = SSAPValue(); // 保持 Top break; - case Instruction::kCall: - // 大多数 Call 指令都假定为 Bottom,除非是纯函数且所有参数都是常量 - newState = SSAPValue(LatticeVal::Bottom); + case Instruction::kCall: { + // 使用副作用分析改进Call指令处理 + CallInst *callInst = static_cast(inst); + + if (sideEffectAnalysis) { + const auto &sideEffect = sideEffectAnalysis->getInstructionSideEffect(callInst); + + // 检查是否为纯函数且所有参数都是常量 + if (sideEffect.isPure && sideEffect.type == SideEffectType::NO_SIDE_EFFECT) { + // 对于纯函数,检查所有参数是否都是常量 + bool allArgsConstant = true; + std::vector argValues; + + for (unsigned i = 0; i < callInst->getNumOperands() - 1; ++i) { // 减1排除函数本身 + SSAPValue argVal = GetValueState(callInst->getOperand(i)); + argValues.push_back(argVal); + if (argVal.state != LatticeVal::Constant) { + allArgsConstant = false; + break; + } + } + + if (allArgsConstant) { + // 对于参数全为常量的纯函数,可以尝试常量折叠 + // 但由于实际执行函数比较复杂,这里先标记为可优化 + // TODO: 实现具体的纯函数常量折叠 + Function *calledFunc = callInst->getCallee(); + if (calledFunc && isKnownPureFunction(calledFunc->getName())) { + // 对已知的纯函数进行常量计算 + newState = computePureFunctionResult(callInst, argValues); + } else { + newState = SSAPValue(LatticeVal::Bottom); + } + } else { + // 参数不全是常量,但函数无副作用 + newState = SSAPValue(LatticeVal::Bottom); + } + + if (DEBUG) { + std::cout << "SCCP: Pure function call with " + << (allArgsConstant ? "constant" : "non-constant") << " arguments" << std::endl; + } + } else { + // 有副作用的函数调用,保守处理 + newState = SSAPValue(LatticeVal::Bottom); + if (DEBUG) { + std::cout << "SCCP: Function call with side effects" << std::endl; + } + } + } else { + // 没有副作用分析时,保守处理所有Call + newState = SSAPValue(LatticeVal::Bottom); + } break; + } case Instruction::kGetElementPtr: { // GEP 指令计算地址,通常其结果值(地址指向的内容)是 Bottom // 除非所有索引和基指针都是常量,指向一个确定常量值的内存位置 @@ -866,12 +1264,34 @@ bool SCCP::runOnFunction(Function *F, AnalysisManager &AM) { if (DEBUG) { std::cout << "Running SCCP on function: " << F->getName() << std::endl; } + SCCPContext context(builder); + + // 获取别名分析结果 + if (auto *aliasResult = AM.getAnalysisResult(F)) { + context.setAliasAnalysis(aliasResult); + if (DEBUG) { + std::cout << "SCCP: Using alias analysis results" << std::endl; + } + } + + // 获取副作用分析结果 + if (auto *sideEffectResult = AM.getAnalysisResult(F)) { + context.setSideEffectAnalysis(sideEffectResult); + if (DEBUG) { + std::cout << "SCCP: Using side effect analysis results" << std::endl; + } + } + context.run(F, AM); return true; } void SCCP::getAnalysisUsage(std::set &analysisDependencies, std::set &analysisInvalidations) const { + // 声明依赖别名分析和副作用分析 + analysisDependencies.insert(&SysYAliasAnalysisPass::ID); + analysisDependencies.insert(&SysYSideEffectAnalysisPass::ID); + // analysisInvalidations.insert(nullptr); // 表示使所有默认分析失效 analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树可能受影响 analysisInvalidations.insert(&LivenessAnalysisPass::ID); // 活跃性分析很可能失效