[midend-LICM]将能够外提的循环不变量进行Kanh拓扑排序保证外提后的计算顺序正确。
This commit is contained in:
@@ -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<Instruction *> workSet(chars->invariantInsts.begin(), chars->invariantInsts.end());
|
||||
|
||||
// 2. 计算每个指令被依赖的次数(入度)
|
||||
std::unordered_map<Instruction *, int> 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<Instruction *>(inst->getOperand(i))) {
|
||||
if (workSet.count(dep)) {
|
||||
indegree[inst]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Kahn拓扑排序
|
||||
std::vector<Instruction *> sorted;
|
||||
std::queue<Instruction *> 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<Instruction *>(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);
|
||||
|
||||
Reference in New Issue
Block a user