529 lines
18 KiB
C++
529 lines
18 KiB
C++
#include "LoopNormalization.h"
|
||
#include "Dom.h"
|
||
#include "Loop.h"
|
||
#include "SysYIROptUtils.h"
|
||
#include <iostream>
|
||
#include <algorithm>
|
||
#include <sstream>
|
||
|
||
// 使用全局调试开关
|
||
extern int DEBUG;
|
||
|
||
namespace sysy {
|
||
|
||
// 定义 Pass 的唯一 ID
|
||
void *LoopNormalizationPass::ID = (void *)&LoopNormalizationPass::ID;
|
||
|
||
bool LoopNormalizationPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||
if (F->getBasicBlocks().empty()) {
|
||
return false; // 空函数
|
||
}
|
||
|
||
if (DEBUG)
|
||
std::cout << "Running LoopNormalizationPass on function: " << F->getName() << std::endl;
|
||
|
||
// 获取并缓存所有需要的分析结果
|
||
loopAnalysis = AM.getAnalysisResult<LoopAnalysisResult, LoopAnalysisPass>(F);
|
||
if (!loopAnalysis || !loopAnalysis->hasLoops()) {
|
||
if (DEBUG)
|
||
std::cout << "No loops found in function " << F->getName() << ", skipping normalization" << std::endl;
|
||
return false; // 没有循环需要规范化
|
||
}
|
||
|
||
domTree = AM.getAnalysisResult<DominatorTree, DominatorTreeAnalysisPass>(F);
|
||
|
||
if (!domTree) {
|
||
std::cerr << "Error: DominatorTree not available for function " << F->getName() << std::endl;
|
||
return false;
|
||
}
|
||
|
||
// 重置统计信息
|
||
stats = NormalizationStats();
|
||
|
||
bool modified = false;
|
||
const auto& allLoops = loopAnalysis->getAllLoops();
|
||
stats.totalLoops = allLoops.size();
|
||
|
||
if (DEBUG) {
|
||
std::cout << "Found " << stats.totalLoops << " loops to analyze for normalization" << std::endl;
|
||
}
|
||
|
||
// 按循环深度从外到内处理,确保外层循环先规范化
|
||
std::vector<Loop*> sortedLoops;
|
||
for (const auto& loop_ptr : allLoops) {
|
||
sortedLoops.push_back(loop_ptr.get());
|
||
}
|
||
|
||
std::sort(sortedLoops.begin(), sortedLoops.end(), [](Loop* a, Loop* b) {
|
||
return a->getLoopDepth() < b->getLoopDepth(); // 按深度升序排列
|
||
});
|
||
|
||
// 逐个规范化循环
|
||
for (Loop* loop : sortedLoops) {
|
||
if (needsPreheader(loop)) {
|
||
stats.loopsNeedingPreheader++;
|
||
|
||
if (DEBUG) {
|
||
std::cout << " Loop " << loop->getName() << " needs preheader (depth="
|
||
<< loop->getLoopDepth() << ")" << std::endl;
|
||
}
|
||
|
||
if (normalizeLoop(loop)) {
|
||
modified = true;
|
||
stats.loopsNormalized++;
|
||
|
||
// 验证规范化结果
|
||
if (!validateNormalization(loop)) {
|
||
std::cerr << "Warning: Loop normalization validation failed for loop "
|
||
<< loop->getName() << std::endl;
|
||
}
|
||
}
|
||
} else {
|
||
if (DEBUG) {
|
||
auto* preheader = getExistingPreheader(loop);
|
||
if (preheader) {
|
||
std::cout << " Loop " << loop->getName() << " already has preheader: "
|
||
<< preheader->getName() << std::endl;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (DEBUG && modified) {
|
||
printStats(F);
|
||
}
|
||
|
||
return modified;
|
||
}
|
||
|
||
bool LoopNormalizationPass::normalizeLoop(Loop* loop) {
|
||
if (DEBUG)
|
||
std::cout << " Normalizing loop: " << loop->getName() << std::endl;
|
||
|
||
// 创建前置块
|
||
BasicBlock* preheader = createPreheaderForLoop(loop);
|
||
if (!preheader) {
|
||
if (DEBUG)
|
||
std::cout << " Failed to create preheader for loop " << loop->getName() << std::endl;
|
||
return false;
|
||
}
|
||
|
||
stats.preheadersCreated++;
|
||
|
||
if (DEBUG) {
|
||
std::cout << " Successfully created preheader " << preheader->getName()
|
||
<< " for loop " << loop->getName() << std::endl;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
BasicBlock* LoopNormalizationPass::createPreheaderForLoop(Loop* loop) {
|
||
BasicBlock* header = loop->getHeader();
|
||
if (!header) {
|
||
if (DEBUG)
|
||
std::cerr << " Error: Loop has no header block" << std::endl;
|
||
return nullptr;
|
||
}
|
||
|
||
// 获取循环外的前驱块
|
||
std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
|
||
if (externalPreds.empty()) {
|
||
if (DEBUG)
|
||
std::cout << " Loop " << loop->getName() << " has no external predecessors" << std::endl;
|
||
return nullptr;
|
||
}
|
||
|
||
if (DEBUG) {
|
||
std::cout << " Found " << externalPreds.size() << " external predecessors for loop "
|
||
<< loop->getName() << std::endl;
|
||
for (auto* pred : externalPreds) {
|
||
std::cout << " External pred: " << pred->getName() << std::endl;
|
||
}
|
||
}
|
||
|
||
// 生成前置块名称
|
||
std::string preheaderName = generatePreheaderName(loop);
|
||
|
||
// 创建新的前置块
|
||
Function* parentFunction = header->getParent();
|
||
BasicBlock* preheader = parentFunction->addBasicBlock(preheaderName, header);
|
||
|
||
if (!preheader) {
|
||
if (DEBUG)
|
||
std::cerr << " Error: Failed to create basic block " << preheaderName << std::endl;
|
||
return nullptr;
|
||
}
|
||
|
||
// 在前置块中创建跳转指令到循环头部
|
||
builder->setPosition(preheader, preheader->end());
|
||
UncondBrInst* br = builder->createUncondBrInst(header);
|
||
|
||
// 更新preheader的CFG关系
|
||
preheader->addSuccessor(header);
|
||
header->addPredecessor(preheader);
|
||
|
||
if(DEBUG) {
|
||
std::cout << " Created preheader " << preheader->getName()
|
||
<< " with unconditional branch to " << header->getName() << std::endl;
|
||
}
|
||
// 重定向外部前驱到新的前置块
|
||
redirectExternalPredecessors(loop, preheader, header, externalPreds);
|
||
|
||
// 更新PHI节点
|
||
updatePhiNodesForPreheader(header, preheader, externalPreds);
|
||
|
||
// 更新支配树关系
|
||
updateDominatorRelations(preheader, loop);
|
||
|
||
// 重要:更新循环对象的前置块信息
|
||
// 这样后续的优化遍可以通过 loop->getPreHeader() 获取到新创建的前置块
|
||
loop->setPreHeader(preheader);
|
||
|
||
if (DEBUG) {
|
||
std::cout << " Updated loop object: preheader set to " << preheader->getName() << std::endl;
|
||
}
|
||
|
||
return preheader;
|
||
}
|
||
|
||
bool LoopNormalizationPass::needsPreheader(Loop* loop) {
|
||
// 检查是否已有合适的前置块
|
||
if (getExistingPreheader(loop) != nullptr) {
|
||
return false;
|
||
}
|
||
|
||
// 检查是否有外部前驱(如果没有外部前驱,不需要前置块)
|
||
std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
|
||
if (externalPreds.empty()) {
|
||
return false;
|
||
}
|
||
|
||
// 基于结构性需求判断:
|
||
// 1. 如果有多个外部前驱,必须创建前置块来合并它们
|
||
// 2. 如果单个外部前驱不适合作为前置块,需要创建新的前置块
|
||
return (externalPreds.size() > 1) || !isSuitableAsPreheader(externalPreds[0], loop);
|
||
}
|
||
|
||
BasicBlock* LoopNormalizationPass::getExistingPreheader(Loop* loop) {
|
||
BasicBlock* header = loop->getHeader();
|
||
if (!header) return nullptr;
|
||
|
||
std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
|
||
|
||
// 如果只有一个外部前驱,且适合作为前置块,则返回它
|
||
if (externalPreds.size() == 1 && isSuitableAsPreheader(externalPreds[0], loop)) {
|
||
return externalPreds[0];
|
||
}
|
||
|
||
return nullptr;
|
||
}
|
||
|
||
void LoopNormalizationPass::updateDominatorRelations(BasicBlock* newBlock, Loop* loop) {
|
||
// 由于在getAnalysisUsage中声明了DominatorTree会失效,
|
||
// PassManager会在本遍运行后自动将支配树结果标记为失效,
|
||
// 后续需要支配树的Pass会触发重新计算,所以这里无需手动更新
|
||
|
||
if (DEBUG) {
|
||
BasicBlock* header = loop->getHeader();
|
||
std::cout << " DominatorTree marked for invalidation - new preheader "
|
||
<< newBlock->getName() << " will dominate " << header->getName()
|
||
<< " after recomputation by PassManager" << std::endl;
|
||
}
|
||
}
|
||
|
||
void LoopNormalizationPass::redirectExternalPredecessors(Loop* loop, BasicBlock* preheader, BasicBlock* header,
|
||
const std::vector<BasicBlock*>& externalPreds) {
|
||
// std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
|
||
|
||
if (DEBUG) {
|
||
std::cout << " Redirecting " << externalPreds.size() << " external predecessors" << std::endl;
|
||
}
|
||
|
||
for (BasicBlock* pred : externalPreds) {
|
||
// 获取前驱块的终止指令
|
||
auto termIt = pred->terminator();
|
||
if (termIt == pred->end()) continue;
|
||
|
||
Instruction* terminator = termIt->get();
|
||
if (!terminator) continue;
|
||
|
||
// 更新跳转目标
|
||
if (auto* br = dynamic_cast<UncondBrInst*>(terminator)) {
|
||
// 无条件跳转
|
||
if (br->getBlock() == header) {
|
||
if(DEBUG){
|
||
std::cout << " Updating unconditional branch from " << br->getBlock()->getName()
|
||
<< " to " << preheader->getName() << std::endl;
|
||
}
|
||
// 需要更新操作数
|
||
br->setOperand(0, preheader);
|
||
// 更新CFG关系
|
||
header->removePredecessor(pred);
|
||
preheader->addPredecessor(pred);
|
||
pred->removeSuccessor(header);
|
||
pred->addSuccessor(preheader);
|
||
|
||
}
|
||
} else if (auto* condBr = dynamic_cast<CondBrInst*>(terminator)) {
|
||
// 条件跳转
|
||
bool updated = false;
|
||
if (condBr->getThenBlock() == header) {
|
||
condBr->setOperand(1, preheader); // 第1个操作数是then分支
|
||
updated = true;
|
||
}
|
||
if (condBr->getElseBlock() == header) {
|
||
condBr->setOperand(2, preheader); // 第2个操作数是else分支
|
||
updated = true;
|
||
}
|
||
if (updated) {
|
||
// 更新CFG关系
|
||
header->removePredecessor(pred);
|
||
preheader->addPredecessor(pred);
|
||
pred->removeSuccessor(header);
|
||
pred->addSuccessor(preheader);
|
||
|
||
if (DEBUG) {
|
||
std::cout << " Updated conditional branch from " << pred->getName()
|
||
<< " to " << preheader->getName() << std::endl;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
std::string LoopNormalizationPass::generatePreheaderName(Loop* loop) {
|
||
std::ostringstream oss;
|
||
oss << loop->getName() << "_preheader";
|
||
return oss.str();
|
||
}
|
||
|
||
bool LoopNormalizationPass::validateNormalization(Loop* loop) {
|
||
BasicBlock* header = loop->getHeader();
|
||
if (!header) return false;
|
||
|
||
// 检查循环是否现在有唯一的外部前驱
|
||
std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
|
||
if (externalPreds.size() != 1) {
|
||
if (DEBUG)
|
||
std::cout << " Validation failed: Loop " << loop->getName()
|
||
<< " has " << externalPreds.size() << " external predecessors (expected 1)" << std::endl;
|
||
return false;
|
||
}
|
||
|
||
// 检查外部前驱是否适合作为前置块
|
||
BasicBlock* preheader = externalPreds[0];
|
||
if (!isSuitableAsPreheader(preheader, loop)) {
|
||
if (DEBUG)
|
||
std::cout << " Validation failed: External predecessor " << preheader->getName()
|
||
<< " is not suitable as preheader" << std::endl;
|
||
return false;
|
||
}
|
||
|
||
// 额外验证:检查CFG连接性
|
||
if (!preheader->hasSuccessor(header)) {
|
||
if (DEBUG)
|
||
std::cout << " Validation failed: Preheader " << preheader->getName()
|
||
<< " is not connected to header " << header->getName() << std::endl;
|
||
return false;
|
||
}
|
||
|
||
if (!header->hasPredecessor(preheader)) {
|
||
if (DEBUG)
|
||
std::cout << " Validation failed: Header " << header->getName()
|
||
<< " does not have preheader " << preheader->getName() << " as predecessor" << std::endl;
|
||
return false;
|
||
}
|
||
|
||
if (DEBUG)
|
||
std::cout << " Validation passed for loop " << loop->getName() << std::endl;
|
||
|
||
return true;
|
||
}
|
||
|
||
std::vector<BasicBlock*> LoopNormalizationPass::getExternalPredecessors(Loop* loop) {
|
||
std::vector<BasicBlock*> externalPreds;
|
||
BasicBlock* header = loop->getHeader();
|
||
if (!header) return externalPreds;
|
||
|
||
for (BasicBlock* pred : header->getPredecessors()) {
|
||
if (!loop->contains(pred)) {
|
||
externalPreds.push_back(pred);
|
||
}
|
||
}
|
||
|
||
return externalPreds;
|
||
}
|
||
|
||
bool LoopNormalizationPass::isSuitableAsPreheader(BasicBlock* block, Loop* loop) {
|
||
if (!block) return false;
|
||
|
||
// 检查该块是否只有一个后继,且后继是循环头部
|
||
auto successors = block->getSuccessors();
|
||
if (successors.size() != 1) {
|
||
return false;
|
||
}
|
||
|
||
if (successors[0] != loop->getHeader()) {
|
||
return false;
|
||
}
|
||
|
||
// 检查该块是否不包含复杂的控制流
|
||
// 理想的前置块应该只包含简单的跳转指令
|
||
size_t instCount = 0;
|
||
for (const auto& inst : block->getInstructions()) {
|
||
instCount++;
|
||
// 如果指令过多,可能不适合作为前置块
|
||
if (instCount > 10) { // 阈值可调整
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
void LoopNormalizationPass::updatePhiNodesForPreheader(BasicBlock* header, BasicBlock* preheader,
|
||
const std::vector<BasicBlock*>& oldPreds) {
|
||
if (DEBUG) {
|
||
std::cout << " Updating PHI nodes in header " << header->getName()
|
||
<< " for new preheader " << preheader->getName() << std::endl;
|
||
}
|
||
|
||
std::vector<PhiInst*> phisToRemove; // 需要删除的PHI节点
|
||
|
||
for (auto& inst : header->getInstructions()) {
|
||
if (auto* phi = dynamic_cast<PhiInst*>(inst.get())) {
|
||
if (DEBUG) {
|
||
std::cout << " Processing PHI node: " << phi->getName() << std::endl;
|
||
}
|
||
|
||
// 收集来自外部前驱的值 - 需要保持原始的映射关系
|
||
std::map<BasicBlock*, Value*> externalValues;
|
||
for (BasicBlock* oldPred : oldPreds) {
|
||
Value* value = phi->getValfromBlk(oldPred);
|
||
if (value) {
|
||
externalValues[oldPred] = value;
|
||
}
|
||
}
|
||
|
||
// 处理PHI节点的更新
|
||
if (externalValues.size() > 1) {
|
||
// 多个外部前驱:在前置块中创建新的PHI节点
|
||
builder->setPosition(preheader, preheader->getInstructions().begin());
|
||
|
||
std::vector<Value*> values;
|
||
std::vector<BasicBlock*> blocks;
|
||
for (auto& [block, value] : externalValues) {
|
||
values.push_back(value);
|
||
blocks.push_back(block);
|
||
}
|
||
|
||
PhiInst* newPhi = builder->createPhiInst(phi->getType(), values, blocks);
|
||
|
||
// 移除所有外部前驱的条目
|
||
for (BasicBlock* oldPred : oldPreds) {
|
||
phi->removeIncomingBlock(oldPred);
|
||
}
|
||
|
||
// 添加来自新前置块的条目
|
||
phi->addIncoming(newPhi, preheader);
|
||
|
||
} else if (externalValues.size() == 1) {
|
||
// 单个外部前驱:直接重新映射
|
||
Value* value = externalValues.begin()->second;
|
||
|
||
// 移除旧的外部前驱条目
|
||
for (BasicBlock* oldPred : oldPreds) {
|
||
phi->removeIncomingBlock(oldPred);
|
||
}
|
||
|
||
// 添加来自新前置块的条目
|
||
phi->addIncoming(value, preheader);
|
||
|
||
// 检查PHI节点是否只剩下一个条目(只来自前置块)
|
||
if (phi->getNumIncomingValues() == 1) {
|
||
if (DEBUG) {
|
||
std::cout << " PHI node " << phi->getName()
|
||
<< " now has only one incoming value, scheduling for removal" << std::endl;
|
||
}
|
||
// 用单一值替换所有使用
|
||
Value* singleValue = phi->getIncomingValue(0u);
|
||
phi->replaceAllUsesWith(singleValue);
|
||
phisToRemove.push_back(phi);
|
||
}
|
||
} else {
|
||
// 没有外部值的PHI节点:检查是否需要更新
|
||
// 这种PHI节点只有循环内的边,通常不需要修改
|
||
// 但我们仍然需要检查是否只有一个条目
|
||
if (phi->getNumIncomingValues() == 1) {
|
||
if (DEBUG) {
|
||
std::cout << " PHI node " << phi->getName()
|
||
<< " has only one incoming value (no external), scheduling for removal" << std::endl;
|
||
}
|
||
// 用单一值替换所有使用
|
||
Value* singleValue = phi->getIncomingValue(0u);
|
||
phi->replaceAllUsesWith(singleValue);
|
||
phisToRemove.push_back(phi);
|
||
}
|
||
}
|
||
|
||
if (DEBUG && std::find(phisToRemove.begin(), phisToRemove.end(), phi) == phisToRemove.end()) {
|
||
std::cout << " Updated PHI node with " << externalValues.size()
|
||
<< " external values, total incoming: " << phi->getNumIncomingValues() << std::endl;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 删除标记为移除的PHI节点
|
||
for (PhiInst* phi : phisToRemove) {
|
||
if (DEBUG) {
|
||
std::cout << " Removing redundant PHI node: " << phi->getName() << std::endl;
|
||
}
|
||
SysYIROptUtils::usedelete(phi);
|
||
}
|
||
|
||
// 更新统计信息
|
||
stats.redundantPhisRemoved += phisToRemove.size();
|
||
|
||
if (DEBUG && !phisToRemove.empty()) {
|
||
std::cout << " Removed " << phisToRemove.size() << " redundant PHI nodes" << std::endl;
|
||
}
|
||
}
|
||
|
||
void LoopNormalizationPass::printStats(Function* F) {
|
||
std::cout << "\n--- Loop Normalization Statistics for Function: " << F->getName() << " ---" << std::endl;
|
||
std::cout << "Total loops analyzed: " << stats.totalLoops << std::endl;
|
||
std::cout << "Loops needing preheader: " << stats.loopsNeedingPreheader << std::endl;
|
||
std::cout << "Preheaders created: " << stats.preheadersCreated << std::endl;
|
||
std::cout << "Loops successfully normalized: " << stats.loopsNormalized << std::endl;
|
||
std::cout << "Redundant PHI nodes removed: " << stats.redundantPhisRemoved << std::endl;
|
||
|
||
if (stats.totalLoops > 0) {
|
||
double normalizationRate = (double)stats.loopsNormalized / stats.totalLoops * 100.0;
|
||
std::cout << "Normalization rate: " << normalizationRate << "%" << std::endl;
|
||
}
|
||
|
||
std::cout << "---------------------------------------------------------------" << std::endl;
|
||
}
|
||
|
||
void LoopNormalizationPass::getAnalysisUsage(std::set<void *> &analysisDependencies,
|
||
std::set<void *> &analysisInvalidations) const {
|
||
// LoopNormalization依赖的分析
|
||
analysisDependencies.insert(&LoopAnalysisPass::ID); // 循环结构分析
|
||
analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); // 支配树分析
|
||
|
||
// LoopNormalization会修改CFG结构,因此会使以下分析失效
|
||
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树需要重新计算
|
||
|
||
// 注意:我们不让循环结构分析失效,原因如下:
|
||
// 1. 循环规范化只添加前置块,不改变循环的核心结构(头部、体、回边)
|
||
// 2. 我们会手动更新Loop对象的前置块信息(通过loop->setPreHeader())
|
||
// 3. 让循环分析失效并重新计算的成本较高且不必要
|
||
// 4. 后续优化遍可以正确获取到更新后的前置块信息
|
||
//
|
||
// 如果未来有更复杂的循环结构修改,可能需要考虑让循环分析失效:
|
||
// analysisInvalidations.insert(&LoopAnalysisPass::ID);
|
||
}
|
||
|
||
} // namespace sysy
|