diff --git a/src/midend/Pass/Optimize/LICM.cpp b/src/midend/Pass/Optimize/LICM.cpp index da9b432..b583066 100644 --- a/src/midend/Pass/Optimize/LICM.cpp +++ b/src/midend/Pass/Optimize/LICM.cpp @@ -12,33 +12,62 @@ bool LICMContext::run() { return hoistInstructions(); } bool LICMContext::hoistInstructions() { bool changed = false; BasicBlock *preheader = loop->getPreHeader(); - if (!preheader || !chars){ - if(DEBUG) { - std::cerr << "LICM: No preheader or loop characteristics found, skipping hoisting." << std::endl; + if (!preheader || !chars) + return false; + + // 1. 先收集所有可外提指令 + std::unordered_set workSet(chars->invariantInsts.begin(), chars->invariantInsts.end()); + + // 2. 计算每个指令被依赖的次数(入度) + std::unordered_map indegree; + for (auto *inst : workSet) { + indegree[inst] = 0; + } + for (auto *inst : workSet) { + for (size_t i = 0; i < inst->getNumOperands(); ++i) { + if (auto *dep = dynamic_cast(inst->getOperand(i))) { + if (workSet.count(dep)) { + indegree[inst]++; + } + } } + } + + // 3. Kahn拓扑排序 + std::vector sorted; + std::queue q; + for (auto &[inst, deg] : indegree) { + if (deg == 0) + q.push(inst); + } + while (!q.empty()) { + auto *inst = q.front(); + q.pop(); + sorted.push_back(inst); + for (size_t i = 0; i < inst->getNumOperands(); ++i) { + if (auto *dep = dynamic_cast(inst->getOperand(i))) { + if (workSet.count(dep)) { + indegree[dep]--; + if (indegree[dep] == 0) + q.push(dep); + } + } + } + } + + // 检查是否全部排序,若未全部排序,说明有环(理论上不会) + if (sorted.size() != workSet.size()) { + if (DEBUG) + std::cerr << "LICM: Topological sort failed, possible dependency cycle." << std::endl; return false; } - - for (auto *inst : chars->invariantInsts) { - if (!inst) { - if(DEBUG) { - std::cerr << "LICM: Invalid instruction found, skipping." << std::endl; - } - continue; // 跳过无效指令 - } - else{ - if(DEBUG) { - std::cout << "LICM: Processing instruction " << inst->getName() << " for hoisting." << std::endl; - } - } + + // 4. 按拓扑序外提 + for (auto *inst : sorted) { + if (!inst) + continue; BasicBlock *parent = inst->getParent(); - // 只外提当前还在循环体内的指令 if (parent && loop->contains(parent)) { - // 获取源和槽的迭代器并移动指令到前置块 - if(DEBUG) { - std::cout << "LICM: Hoisting instruction " << inst->getName() << " from " - << parent->getName() << " to preheader " << preheader->getName() << std::endl; - } auto sourcePos = parent->findInstIterator(inst); auto targetPos = preheader->terminator(); parent->moveInst(sourcePos, targetPos, preheader); @@ -47,7 +76,6 @@ bool LICMContext::hoistInstructions() { } return changed; } - // ---- LICM Pass Implementation ---- bool LICM::runOnFunction(Function *F, AnalysisManager &AM) { @@ -60,7 +88,7 @@ bool LICM::runOnFunction(Function *F, AnalysisManager &AM) { // 对每个函数内的所有循环做处理 for (const auto &loop_ptr : loopAnalysis->getAllLoops()) { Loop *loop = loop_ptr.get(); - if(DEBUG){ + if (DEBUG) { std::cout << "LICM: Processing loop in function " << F->getName() << ": " << loop->getName() << std::endl; } const LoopCharacteristics *chars = loopCharsResult->getCharacteristics(loop);