diff --git a/src/include/midend/Pass/Analysis/SideEffectAnalysis.h b/src/include/midend/Pass/Analysis/SideEffectAnalysis.h index d19a59a..d75d329 100644 --- a/src/include/midend/Pass/Analysis/SideEffectAnalysis.h +++ b/src/include/midend/Pass/Analysis/SideEffectAnalysis.h @@ -3,6 +3,7 @@ #include "Pass.h" #include "IR.h" #include "AliasAnalysis.h" +#include "CallGraphAnalysis.h" #include #include @@ -86,16 +87,16 @@ public: private: }; -// 副作用分析遍类 +// 副作用分析遍类 - Module级别分析 class SysYSideEffectAnalysisPass : public AnalysisPass { public: // 静态成员,作为该遍的唯一ID static void* ID; - SysYSideEffectAnalysisPass() : AnalysisPass("SysYSideEffectAnalysis", Granularity::Function) {} + SysYSideEffectAnalysisPass() : AnalysisPass("SysYSideEffectAnalysis", Granularity::Module) {} - // 在函数上运行分析 - bool runOnFunction(Function* F, AnalysisManager& AM) override; + // 在模块上运行分析 + bool runOnModule(Module* M, AnalysisManager& AM) override; // 获取分析结果 std::unique_ptr getResult() override; @@ -107,20 +108,30 @@ private: // 分析结果 std::unique_ptr result; - // 别名分析结果(在整个函数分析过程中重复使用) - AliasAnalysisResult* aliasAnalysis = nullptr; + // 调用图分析结果 + CallGraphAnalysisResult* callGraphAnalysis = nullptr; + + // 分析单个函数的副作用(Module级别的内部方法) + SideEffectInfo analyzeFunction(Function* func, AnalysisManager& AM); // 分析单个指令的副作用 - SideEffectInfo analyzeInstruction(Instruction* inst, AnalysisManager& AM); + SideEffectInfo analyzeInstruction(Instruction* inst, Function* currentFunc, AnalysisManager& AM); - // 分析函数调用指令的副作用 - SideEffectInfo analyzeCallInstruction(CallInst* call, AnalysisManager& AM); + // 分析函数调用指令的副作用(利用调用图) + SideEffectInfo analyzeCallInstruction(CallInst* call, Function* currentFunc, AnalysisManager& AM); // 分析存储指令的副作用 - SideEffectInfo analyzeStoreInstruction(StoreInst* store, AnalysisManager& AM); + SideEffectInfo analyzeStoreInstruction(StoreInst* store, Function* currentFunc, AnalysisManager& AM); // 分析内存设置指令的副作用 - SideEffectInfo analyzeMemsetInstruction(MemsetInst* memset, AnalysisManager& AM); + SideEffectInfo analyzeMemsetInstruction(MemsetInst* memset, Function* currentFunc, AnalysisManager& AM); + + // 使用不动点算法分析递归函数群 + void analyzeStronglyConnectedComponent(const std::vector& scc, AnalysisManager& AM); + + // 检查函数间副作用传播的收敛性 + bool hasConverged(const std::unordered_map& oldEffects, + const std::unordered_map& newEffects) const; }; } // namespace sysy diff --git a/src/midend/CMakeLists.txt b/src/midend/CMakeLists.txt index d61ea91..b326585 100644 --- a/src/midend/CMakeLists.txt +++ b/src/midend/CMakeLists.txt @@ -10,6 +10,7 @@ add_library(midend_lib STATIC Pass/Analysis/LoopCharacteristics.cpp Pass/Analysis/AliasAnalysis.cpp Pass/Analysis/SideEffectAnalysis.cpp + Pass/Analysis/CallGraphAnalysis.cpp Pass/Optimize/DCE.cpp Pass/Optimize/Mem2Reg.cpp Pass/Optimize/Reg2Mem.cpp diff --git a/src/midend/Pass/Analysis/SideEffectAnalysis.cpp b/src/midend/Pass/Analysis/SideEffectAnalysis.cpp index 34a6034..060055c 100644 --- a/src/midend/Pass/Analysis/SideEffectAnalysis.cpp +++ b/src/midend/Pass/Analysis/SideEffectAnalysis.cpp @@ -1,5 +1,6 @@ #include "SideEffectAnalysis.h" #include "AliasAnalysis.h" +#include "CallGraphAnalysis.h" #include "SysYIRPrinter.h" #include @@ -110,78 +111,71 @@ const SideEffectInfo* SideEffectAnalysisResult::getKnownFunctionSideEffect(const // SysYSideEffectAnalysisPass 类的实现 // ====================================================================== -bool SysYSideEffectAnalysisPass::runOnFunction(Function* F, AnalysisManager& AM) { +bool SysYSideEffectAnalysisPass::runOnModule(Module* M, AnalysisManager& AM) { if (DEBUG) { - std::cout << "Running SideEffect analysis on function: " << F->getName() << std::endl; + std::cout << "Running SideEffect analysis on module" << std::endl; } // 创建分析结果(构造函数中已经调用了initializeKnownFunctions) result = std::make_unique(); - // 获取别名分析结果,在整个函数分析过程中重复使用 - aliasAnalysis = AM.getAnalysisResult(F); + // 获取调用图分析结果 + callGraphAnalysis = AM.getAnalysisResult(); + if (!callGraphAnalysis) { + std::cerr << "Warning: CallGraphAnalysis not available, falling back to conservative analysis" << std::endl; + } - // TODO: 重构为Module级别的分析,利用独立的调用图分析 - // - // 建议的架构: - // 1. SysYCallGraphAnalysisPass - 独立的调用图分析(Module级别) - // - 构建完整的函数调用关系 - // - 提供拓扑排序和强连通分量 - // - 识别递归调用模式 - // - // 2. SysYSideEffectAnalysisPass - 重构为Module级别 - // - 依赖调用图分析结果 - // - 按拓扑序分析函数,确保依赖函数先分析 - // - 使用不动点算法处理递归函数群 - // - // 优势: - // - 调用图可被多个Pass复用(内联、DCE等) - // - 准确的函数间副作用传播 - // - 正确处理递归调用 - // - 避免保守的"未分析函数"假设 - - // 分析函数中的每条指令 - SideEffectInfo functionSideEffect; - - for (auto& BB : F->getBasicBlocks()) { - for (auto& I : BB->getInstructions_Range()) { - Instruction* inst = I.get(); - SideEffectInfo instEffect = analyzeInstruction(inst, AM); - - // 记录指令的副作用信息 - result->setInstructionSideEffect(inst, instEffect); - - // 合并到函数级别的副作用信息中 - functionSideEffect = functionSideEffect.merge(instEffect); + // 按拓扑序分析函数,确保被调用函数先于调用者分析 + if (callGraphAnalysis) { + // 使用调用图的拓扑排序结果 + const auto& topOrder = callGraphAnalysis->getTopologicalOrder(); + + // 处理强连通分量(递归函数群) + const auto& sccs = callGraphAnalysis->getStronglyConnectedComponents(); + for (const auto& scc : sccs) { + if (scc.size() > 1) { + // 多个函数的强连通分量,使用不动点算法 + analyzeStronglyConnectedComponent(scc, AM); + } else { + // 单个函数,检查是否自递归 + Function* func = scc[0]; + if (callGraphAnalysis->isSelfRecursive(func)) { + // 自递归函数也需要不动点算法 + analyzeStronglyConnectedComponent(scc, AM); + } else { + // 非递归函数,直接分析 + SideEffectInfo funcEffect = analyzeFunction(func, AM); + result->setFunctionSideEffect(func, funcEffect); + } + } + } + } else { + // 没有调用图,保守地分析每个函数 + for (auto& pair : M->getFunctions()) { + Function* func = pair.second.get(); + SideEffectInfo funcEffect = analyzeFunction(func, AM); + result->setFunctionSideEffect(func, funcEffect); } } - // 记录函数级别的副作用信息 - result->setFunctionSideEffect(F, functionSideEffect); - if (DEBUG) { - std::cout << "---- Side Effect Analysis Results for Function: " << F->getName() << " ----\n"; - - for (auto& BB : F->getBasicBlocks()) { - for (auto& I : BB->getInstructions_Range()) { - Instruction* inst = I.get(); - const auto& info = result->getInstructionSideEffect(inst); - - SysYPrinter::printInst(inst); - std::cout << " -> Side Effect: "; - switch (info.type) { - case SideEffectType::NO_SIDE_EFFECT: std::cout << "None"; break; - case SideEffectType::MEMORY_WRITE: std::cout << "Memory Write"; break; - case SideEffectType::FUNCTION_CALL: std::cout << "Function Call"; break; - case SideEffectType::IO_OPERATION: std::cout << "I/O Operation"; break; - case SideEffectType::UNKNOWN: std::cout << "Unknown"; break; - } - std::cout << " (Modifies Global: " << (info.mayModifyGlobal ? "Yes" : "No") - << ", Modifies Memory: " << (info.mayModifyMemory ? "Yes" : "No") - << ", Is Pure: " << (info.isPure ? "Yes" : "No") << ")\n"; + std::cout << "---- Side Effect Analysis Results for Module ----\n"; + for (auto& pair : M->getFunctions()) { + Function* func = pair.second.get(); + const auto& funcInfo = result->getFunctionSideEffect(func); + + std::cout << "Function " << func->getName() << ": "; + switch (funcInfo.type) { + case SideEffectType::NO_SIDE_EFFECT: std::cout << "No Side Effect"; break; + case SideEffectType::MEMORY_WRITE: std::cout << "Memory Write"; break; + case SideEffectType::FUNCTION_CALL: std::cout << "Function Call"; break; + case SideEffectType::IO_OPERATION: std::cout << "I/O Operation"; break; + case SideEffectType::UNKNOWN: std::cout << "Unknown"; break; } + std::cout << " (Pure: " << (funcInfo.isPure ? "Yes" : "No") + << ", Modifies Global: " << (funcInfo.mayModifyGlobal ? "Yes" : "No") << ")\n"; } - std::cout << "------------------------------------------------------------------\n"; + std::cout << "--------------------------------------------------\n"; } return false; // Analysis passes return false since they don't modify the IR @@ -191,16 +185,100 @@ std::unique_ptr SysYSideEffectAnalysisPass::getResult() { return std::move(result); } -SideEffectInfo SysYSideEffectAnalysisPass::analyzeInstruction(Instruction* inst, AnalysisManager& AM) { +SideEffectInfo SysYSideEffectAnalysisPass::analyzeFunction(Function* func, AnalysisManager& AM) { + SideEffectInfo functionSideEffect; + + // 为每个指令分析副作用 + for (auto& BB : func->getBasicBlocks()) { + for (auto& I : BB->getInstructions_Range()) { + Instruction* inst = I.get(); + SideEffectInfo instEffect = analyzeInstruction(inst, func, AM); + + // 记录指令的副作用信息 + result->setInstructionSideEffect(inst, instEffect); + + // 合并到函数级别的副作用信息中 + functionSideEffect = functionSideEffect.merge(instEffect); + } + } + + return functionSideEffect; +} + +void SysYSideEffectAnalysisPass::analyzeStronglyConnectedComponent(const std::vector& scc, AnalysisManager& AM) { + // 使用不动点算法处理递归函数群 + std::unordered_map currentEffects; + std::unordered_map previousEffects; + + // 初始化:所有函数都假设为纯函数 + for (Function* func : scc) { + SideEffectInfo initialEffect; + initialEffect.isPure = true; + currentEffects[func] = initialEffect; + result->setFunctionSideEffect(func, initialEffect); + } + + bool converged = false; + int iterations = 0; + const int maxIterations = 10; // 防止无限循环 + + while (!converged && iterations < maxIterations) { + previousEffects = currentEffects; + + // 重新分析每个函数 + for (Function* func : scc) { + SideEffectInfo newEffect = analyzeFunction(func, AM); + currentEffects[func] = newEffect; + result->setFunctionSideEffect(func, newEffect); + } + + // 检查是否收敛 + converged = hasConverged(previousEffects, currentEffects); + iterations++; + } + + if (iterations >= maxIterations) { + std::cerr << "Warning: SideEffect analysis did not converge for SCC after " + << maxIterations << " iterations" << std::endl; + } +} + +bool SysYSideEffectAnalysisPass::hasConverged(const std::unordered_map& oldEffects, + const std::unordered_map& newEffects) const { + for (const auto& pair : oldEffects) { + Function* func = pair.first; + const SideEffectInfo& oldEffect = pair.second; + + auto it = newEffects.find(func); + if (it == newEffects.end()) { + return false; // 函数不存在于新结果中 + } + + const SideEffectInfo& newEffect = it->second; + + // 比较关键属性是否相同 + if (oldEffect.type != newEffect.type || + oldEffect.mayModifyGlobal != newEffect.mayModifyGlobal || + oldEffect.mayModifyMemory != newEffect.mayModifyMemory || + oldEffect.mayCallFunction != newEffect.mayCallFunction || + oldEffect.isPure != newEffect.isPure) { + return false; + } + } + + return true; +} + +SideEffectInfo SysYSideEffectAnalysisPass::analyzeInstruction(Instruction* inst, Function* currentFunc, AnalysisManager& AM) { SideEffectInfo info; // 根据指令类型进行分析 if (inst->isCall()) { - return analyzeCallInstruction(static_cast(inst), AM); + return analyzeCallInstruction(static_cast(inst), currentFunc, AM); } else if (inst->isStore()) { - return analyzeStoreInstruction(static_cast(inst), AM); + return analyzeStoreInstruction(static_cast(inst), currentFunc, AM); } else if (inst->isMemset()) { - return analyzeMemsetInstruction(static_cast(inst), AM); + return analyzeMemsetInstruction(static_cast(inst), currentFunc, AM); } else if (inst->isBranch() || inst->isReturn()) { // 控制流指令无副作用,但必须保留 info.type = SideEffectType::NO_SIDE_EFFECT; @@ -214,7 +292,7 @@ SideEffectInfo SysYSideEffectAnalysisPass::analyzeInstruction(Instruction* inst, return info; } -SideEffectInfo SysYSideEffectAnalysisPass::analyzeCallInstruction(CallInst* call, AnalysisManager& AM) { +SideEffectInfo SysYSideEffectAnalysisPass::analyzeCallInstruction(CallInst* call, Function* currentFunc, AnalysisManager& AM) { SideEffectInfo info; // 获取被调用的函数 @@ -237,10 +315,24 @@ SideEffectInfo SysYSideEffectAnalysisPass::analyzeCallInstruction(CallInst* call return *knownInfo; } - // 对于用户定义的函数,检查是否已经分析过 - const SideEffectInfo& funcEffect = result->getFunctionSideEffect(calledFunc); - if (funcEffect.type != SideEffectType::NO_SIDE_EFFECT || !funcEffect.isPure) { - return funcEffect; + // 利用调用图分析结果进行精确分析 + if (callGraphAnalysis) { + // 检查被调用函数是否已分析过 + const SideEffectInfo& funcEffect = result->getFunctionSideEffect(calledFunc); + if (funcEffect.type != SideEffectType::NO_SIDE_EFFECT || !funcEffect.isPure) { + return funcEffect; + } + + // 检查递归调用 + if (callGraphAnalysis->isRecursive(calledFunc)) { + // 递归函数保守处理(在不动点算法中会精确分析) + info.type = SideEffectType::FUNCTION_CALL; + info.mayModifyGlobal = true; + info.mayModifyMemory = true; + info.mayCallFunction = true; + info.isPure = false; + return info; + } } // 对于未分析的用户函数,保守处理 @@ -253,13 +345,14 @@ SideEffectInfo SysYSideEffectAnalysisPass::analyzeCallInstruction(CallInst* call return info; } -SideEffectInfo SysYSideEffectAnalysisPass::analyzeStoreInstruction(StoreInst* store, AnalysisManager& AM) { +SideEffectInfo SysYSideEffectAnalysisPass::analyzeStoreInstruction(StoreInst* store, Function* currentFunc, AnalysisManager& AM) { SideEffectInfo info; info.type = SideEffectType::MEMORY_WRITE; info.mayModifyMemory = true; info.isPure = false; - // 使用缓存的别名分析结果 + // 获取函数的别名分析结果 + AliasAnalysisResult* aliasAnalysis = AM.getAnalysisResult(currentFunc); if (aliasAnalysis) { Value* storePtr = store->getPointer(); @@ -275,13 +368,14 @@ SideEffectInfo SysYSideEffectAnalysisPass::analyzeStoreInstruction(StoreInst* st return info; } -SideEffectInfo SysYSideEffectAnalysisPass::analyzeMemsetInstruction(MemsetInst* memset, AnalysisManager& AM) { +SideEffectInfo SysYSideEffectAnalysisPass::analyzeMemsetInstruction(MemsetInst* memset, Function* currentFunc, AnalysisManager& AM) { SideEffectInfo info; info.type = SideEffectType::MEMORY_WRITE; info.mayModifyMemory = true; info.isPure = false; - // 使用缓存的别名分析结果 + // 获取函数的别名分析结果 + AliasAnalysisResult* aliasAnalysis = AM.getAnalysisResult(currentFunc); if (aliasAnalysis) { Value* memsetPtr = memset->getPointer(); diff --git a/src/midend/Pass/Optimize/DCE.cpp b/src/midend/Pass/Optimize/DCE.cpp index 7f95b96..06a4822 100644 --- a/src/midend/Pass/Optimize/DCE.cpp +++ b/src/midend/Pass/Optimize/DCE.cpp @@ -20,8 +20,8 @@ void DCEContext::run(Function *func, AnalysisManager *AM, bool &changed) { // 获取别名分析结果 if (AM) { aliasAnalysis = AM->getAnalysisResult(func); - // 获取副作用分析结果 - sideEffectAnalysis = AM->getAnalysisResult(func); + // 获取副作用分析结果(Module级别) + sideEffectAnalysis = AM->getAnalysisResult(); if (DEBUG) { if (aliasAnalysis) { diff --git a/src/midend/Pass/Optimize/SCCP.cpp b/src/midend/Pass/Optimize/SCCP.cpp index d88136d..f344c60 100644 --- a/src/midend/Pass/Optimize/SCCP.cpp +++ b/src/midend/Pass/Optimize/SCCP.cpp @@ -1275,8 +1275,8 @@ bool SCCP::runOnFunction(Function *F, AnalysisManager &AM) { } } - // 获取副作用分析结果 - if (auto *sideEffectResult = AM.getAnalysisResult(F)) { + // 获取副作用分析结果(Module级别) + if (auto *sideEffectResult = AM.getAnalysisResult()) { context.setSideEffectAnalysis(sideEffectResult); if (DEBUG) { std::cout << "SCCP: Using side effect analysis results" << std::endl; diff --git a/src/midend/Pass/Pass.cpp b/src/midend/Pass/Pass.cpp index 6649f65..a5d76a7 100644 --- a/src/midend/Pass/Pass.cpp +++ b/src/midend/Pass/Pass.cpp @@ -3,6 +3,7 @@ #include "Loop.h" #include "LoopCharacteristics.h" #include "AliasAnalysis.h" +#include "CallGraphAnalysis.h" #include "SideEffectAnalysis.h" #include "SysYIRCFGOpt.h" #include "SysYIRPrinter.h" @@ -42,7 +43,8 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR registerAnalysisPass(); registerAnalysisPass(); registerAnalysisPass(); // 别名分析 (优先级高) - registerAnalysisPass(); // 副作用分析 (依赖别名分析) + registerAnalysisPass(); // 调用图分析 (Module级别,独立分析) + registerAnalysisPass(); // 副作用分析 (依赖别名分析和调用图) registerAnalysisPass(); registerAnalysisPass(); // 循环特征分析依赖别名分析