diff --git a/src/SysYIRAnalyser.cpp b/src/SysYIRAnalyser.cpp index f7c685d..9b78fb4 100644 --- a/src/SysYIRAnalyser.cpp +++ b/src/SysYIRAnalyser.cpp @@ -254,6 +254,267 @@ void ControlFlowAnalysis::computeDomFrontierAllBlk() { } } +// ========================== +// dataflow analysis utils +// ========================== + +// 先引用学长的代码 +// TODO: Worklist 增加逆后序遍历机制 +void DataFlowAnalysisUtils::forwardAnalyze(Module *pModule){ + std::map workAnalysis; + for (auto &dataflow : forwardAnalysisList) { + dataflow->init(pModule); + } + + for (const auto &function : pModule->getFunctions()) { + for (auto &dataflow : forwardAnalysisList) { + workAnalysis.emplace(dataflow, false); + } + while (!workAnalysis.empty()) { + for (const auto &block : function.second->getBasicBlocks()) { + for (auto &elem : workAnalysis) { + if (elem.first->analyze(pModule, block.get())) { + elem.second = true; + } + } + } + std::map tmp; + std::remove_copy_if(workAnalysis.begin(), workAnalysis.end(), std::inserter(tmp, tmp.end()), + [](const std::pair &elem) -> bool { return !elem.second; }); + workAnalysis.swap(tmp); + + for (auto &elem : workAnalysis) { + elem.second = false; + } + } + } +} + +void DataFlowAnalysisUtils::backwardAnalyze(Module *pModule) { + std::map workAnalysis; + for (auto &dataflow : backwardAnalysisList) { + dataflow->init(pModule); + } + + for (const auto &function : pModule->getFunctions()) { + for (auto &dataflow : backwardAnalysisList) { + workAnalysis.emplace(dataflow, false); + } + while (!workAnalysis.empty()) { + for (const auto &block : function.second->getBasicBlocks()) { + for (auto &elem : workAnalysis) { + if (elem.first->analyze(pModule, block.get())) { + elem.second = true; + } + } + } + std::map tmp; + std::remove_copy_if(workAnalysis.begin(), workAnalysis.end(), std::inserter(tmp, tmp.end()), + [](const std::pair &elem) -> bool { return !elem.second; }); + workAnalysis.swap(tmp); + + for (auto &elem : workAnalysis) { + elem.second = false; + } + } + } +} + + +std::set ActiveVarAnalysis::getUsedSet(Instruction *inst) { + using Kind = Instruction::Kind; + std::vector operands; + for (const auto &operand : inst->getOperands()) { + operands.emplace_back(dynamic_cast(operand->getValue())); + } + std::set result; + switch (inst->getKind()) { + // phi op + case Kind::kPhi: + case Kind::kCall: + result.insert(std::next(operands.begin()), operands.end()); + break; + case Kind::kCondBr: + result.insert(operands[0]); + break; + case Kind::kBr: + case Kind::kAlloca: + break; + // mem op + case Kind::kStore: + // StoreInst 的第一个操作数是被存储的值,第二个操作数是存储的变量 + // 后续的是可能的数组维度 + result.insert(operands[0]); + result.insert(operands.begin() + 2, operands.end()); + break; + case Kind::kLoad: + case Kind::kLa: { + auto variable = dynamic_cast(operands[0]); + auto global = dynamic_cast(operands[0]); + auto constArray = dynamic_cast(operands[0]); + if ((variable != nullptr && variable->getNumDims() == 0) || (global != nullptr && global->getNumDims() == 0) || + (constArray != nullptr && constArray->getNumDims() == 0)) { + result.insert(operands[0]); + } + result.insert(std::next(operands.begin()), operands.end()); + break; + } + case Kind::kGetSubArray: { + for (unsigned i = 2; i < operands.size(); i++) { + // 数组的维度信息 + result.insert(operands[i]); + } + break; + } + case Kind::kMemset: { + result.insert(std::next(operands.begin()), operands.end()); + break; + } + case Kind::kInvalid: + // Binary + case Kind::kAdd: + case Kind::kSub: + case Kind::kMul: + case Kind::kDiv: + case Kind::kRem: + case Kind::kICmpEQ: + case Kind::kICmpNE: + case Kind::kICmpLT: + case Kind::kICmpLE: + case Kind::kICmpGT: + case Kind::kICmpGE: + case Kind::kFAdd: + case Kind::kFSub: + case Kind::kFMul: + case Kind::kFDiv: + case Kind::kFCmpEQ: + case Kind::kFCmpNE: + case Kind::kFCmpLT: + case Kind::kFCmpLE: + case Kind::kFCmpGT: + case Kind::kFCmpGE: + case Kind::kAnd: + case Kind::kOr: + // Unary + case Kind::kNeg: + case Kind::kNot: + case Kind::kFNot: + case Kind::kFNeg: + case Kind::kFtoI: + case Kind::kItoF: + // terminator + case Kind::kReturn: + result.insert(operands.begin(), operands.end()); + break; + default: + assert(false); + break; + } + result.erase(nullptr); + return result; +} + +User * ActiveVarAnalysis::getDefine(Instruction *inst) { + User *result = nullptr; + if (inst->isStore()) { + StoreInst* store = dynamic_cast(inst); + auto operand = store->getPointer(); + AllocaInst* variable = dynamic_cast(operand); + GlobalValue* global = dynamic_cast(operand); + if ((variable != nullptr && variable->getNumDims() != 0) || (global != nullptr && global->getNumDims() != 0)) { + // 如果是数组变量或者全局变量,则不返回定义 + // TODO:兼容数组变量 + result = nullptr; + } else { + result = dynamic_cast(operand); + } + } else if (inst->isPhi()) { + result = dynamic_cast(inst->getOperand(0)); + } else if (inst->isBinary() || inst->isUnary() || inst->isCall() || + inst->isLoad() || inst->isLa()) { + result = dynamic_cast(inst); + } + return result; +} + +void ActiveVarAnalysis::init(Module *pModule) { + for (const auto &function : pModule->getFunctions()) { + for (const auto &block : function.second->getBasicBlocks()) { + activeTable.emplace(block.get(), std::vector>{}); + for (unsigned i = 0; i < block->getNumInstructions() + 1; i++) + activeTable.at(block.get()).emplace_back(); + } + } +} + +// 活跃变量分析公式 每个块内的分析动作供分析器调用 +bool ActiveVarAnalysis::analyze(Module *pModule, BasicBlock *block) { + bool changed = false; // 标记数据流结果是否有变化 + std::set activeSet{}; // 当前计算的活跃变量集合 + + // 步骤1: 计算基本块出口的活跃变量集 (OUT[B]) + // 公式: OUT[B] = ∪_{S ∈ succ(B)} IN[S] + for (const auto &succ : block->getSuccessors()) { + // 获取后继块入口的活跃变量集 (IN[S]) + auto succActiveSet = activeTable.at(succ).front(); + // 合并所有后继块的入口活跃变量 + activeSet.insert(succActiveSet.begin(), succActiveSet.end()); + } + + // 步骤2: 处理基本块出口处的活跃变量集 + const auto &instructions = block->getInstructions(); + const auto numInstructions = instructions.size(); + + // 获取旧的出口活跃变量集 (block出口对应索引numInstructions) + const auto &oldEndActiveSet = activeTable.at(block)[numInstructions]; + + // 检查出口活跃变量集是否有变化 + if (!std::equal(activeSet.begin(), activeSet.end(), + oldEndActiveSet.begin(), oldEndActiveSet.end())) + { + changed = true; // 标记变化 + activeTable.at(block)[numInstructions] = activeSet; // 更新出口活跃变量集 + } + + // 步骤3: 逆序遍历基本块中的指令 + // 从最后一条指令开始向前计算每个程序点的活跃变量 + auto instructionIter = instructions.end(); + instructionIter--; // 指向最后一条指令 + + // 从出口向入口遍历 (索引从numInstructions递减到1) + for (unsigned i = numInstructions; i > 0; i--) { + auto inst = instructionIter->get(); // 当前指令 + + auto used = getUsedSet(inst); + User *defined = getDefine(inst); + + // 步骤3.3: 计算指令入口的活跃变量 (IN[i]) + // 公式: IN[i] = use_i ∪ (OUT[i] - def_i) + activeSet.erase(defined); // 移除被定义的变量 (OUT[i] - def_i) + activeSet.insert(used.begin(), used.end()); // 添加使用的变量 + + // 获取旧的入口活跃变量集 (位置i-1对应当前指令的入口) + const auto &oldActiveSet = activeTable.at(block)[i - 1]; + + // 检查活跃变量集是否有变化 + if (!std::equal(activeSet.begin(), activeSet.end(), + oldActiveSet.begin(), oldActiveSet.end())) + { + changed = true; // 标记变化 + activeTable.at(block)[i - 1] = activeSet; // 更新入口活跃变量集 + } + + instructionIter--; // 移动到前一条指令 + } + + return changed; // 返回数据流结果是否变化 +} + + +auto ActiveVarAnalysis::getActiveTable() const -> const std::map>> & { + return activeTable; +} + } // namespace sysy diff --git a/src/include/SysYIRAnalyser.h b/src/include/SysYIRAnalyser.h index 2cb3f1f..7a13491 100644 --- a/src/include/SysYIRAnalyser.h +++ b/src/include/SysYIRAnalyser.h @@ -252,6 +252,7 @@ public: bool isParallelable() const { return parallelable; } }; +// 控制流分析类 class ControlFlowAnalysis { private: Module *pModule; ///< 模块 @@ -287,8 +288,111 @@ private: BasicBlock* findCommonDominator(BasicBlock *a, BasicBlock *b); // 查找两个基本块的共同支配结点 }; +// 数据流分析类 +// 该类为抽象类,具体的数据流分析器需要继承此类 +// 因为每个数据流分析器的分析动作都不一样,所以需要继承并实现analyze方法 +class DataFlowAnalysis { + public: + virtual ~DataFlowAnalysis() = default; -// 分析管理器(整合版) + public: + virtual void init(Module *pModule) {} ///< 分析器初始化 + virtual auto analyze(Module *pModule, BasicBlock *block) -> bool { return true; } ///< 分析动作,若完成则返回true; + virtual void clear() {} ///< 清空 +}; + +// 数据流分析工具类 +// 该类用于管理多个数据流分析器,提供统一的前向与后向分析接口 +class DataFlowAnalysisUtils { +private: + std::vector forwardAnalysisList; ///< 前向分析器列表 + std::vector backwardAnalysisList; ///< 后向分析器列表 + +public: + DataFlowAnalysisUtils() = default; + + // 统一构造 + DataFlowAnalysisUtils( + std::vector forwardList = {}, + std::vector backwardList = {}) + : forwardAnalysisList(std::move(forwardList)), + backwardAnalysisList(std::move(backwardList)) {} + + // 统一添加接口 + void addAnalyzers( + std::vector forwardList, + std::vector backwardList = {}) + { + forwardAnalysisList.insert( + forwardAnalysisList.end(), + forwardList.begin(), + forwardList.end()); + + backwardAnalysisList.insert( + backwardAnalysisList.end(), + backwardList.begin(), + backwardList.end()); + } + + // 单独添加接口 + void addForwardAnalyzer(DataFlowAnalysis *analyzer) { + forwardAnalysisList.push_back(analyzer); + } + + void addBackwardAnalyzer(DataFlowAnalysis *analyzer) { + backwardAnalysisList.push_back(analyzer); + } + + // 设置分析器列表 + void setAnalyzers( + std::vector forwardList, + std::vector backwardList) + { + forwardAnalysisList = std::move(forwardList); + backwardAnalysisList = std::move(backwardList); + } + + // 清空列表 + void clear() { + forwardAnalysisList.clear(); + backwardAnalysisList.clear(); + } + + // 访问器 + const auto& getForwardAnalyzers() const { return forwardAnalysisList; } + const auto& getBackwardAnalyzers() const { return backwardAnalysisList; } + +public: + void forwardAnalyze(Module *pModule); ///< 执行前向分析 + void backwardAnalyze(Module *pModule); ///< 执行后向分析 +}; + +// 活跃变量分析类 +// 提供def - use分析 +// 未兼容数组变量但是考虑了维度的use信息 +class ActiveVarAnalysis : public DataFlowAnalysis { + private: + std::map>> activeTable; ///< 活跃信息表,存储每个基本块内的的活跃变量信息 + + public: + ActiveVarAnalysis() = default; + ~ActiveVarAnalysis() override = default; + + public: + static std::set getUsedSet(Instruction *inst); + static User* getDefine(Instruction *inst); + + public: + void init(Module *pModule) override; + bool analyze(Module *pModule, BasicBlock *block) override; + // 外部活跃信息表访问器 + const std::map>> &getActiveTable() const; + void clear() override { + activeTable.clear(); // 清空活跃信息表 + } +}; + +// 分析管理器 class AnalysisManager { };