[midend-Loop]初步构建循环规范遍

This commit is contained in:
rain2133
2025-08-09 17:53:41 +08:00
parent be9ac89584
commit 6a7355ed28
3 changed files with 588 additions and 0 deletions

View File

@@ -0,0 +1,155 @@
#pragma once
#include "Loop.h" // 循环分析依赖
#include "LoopCharacteristics.h" // 循环特征分析依赖
#include "Dom.h" // 支配树分析依赖
#include "IR.h" // IR定义
#include "IRBuilder.h" // IR构建器
#include "Pass.h" // Pass框架
#include <memory>
#include <set>
#include <vector>
namespace sysy {
/**
* @brief 循环规范化转换Pass
*
* 该Pass在循环不变量提升等优化前运行主要负责
* 1. 为没有前置块(preheader)的循环创建前置块
* 2. 确保循环结构符合后续优化的要求
* 3. 规范化循环的控制流结构
*
* 前置块的作用:
* - 为循环不变量提升提供插入位置
* - 简化循环分析和优化
* - 确保循环有唯一的入口点
*/
class LoopNormalizationPass : public OptimizationPass {
public:
// 唯一的 Pass ID
static void *ID;
LoopNormalizationPass(IRBuilder* builder) : OptimizationPass("LoopNormalization", Pass::Granularity::Function), builder(builder) {}
// 实现 getPassID
void *getPassID() const override { return &ID; }
// 核心运行方法
bool runOnFunction(Function *F, AnalysisManager &AM) override;
// 声明分析依赖和失效信息
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
private:
// ========== IR构建器 ==========
IRBuilder* builder; // IR构建器
// ========== 缓存的分析结果 ==========
LoopAnalysisResult* loopAnalysis; // 循环结构分析结果
LoopCharacteristicsResult* loopCharacteristics; // 循环特征分析结果
DominatorTree* domTree; // 支配树分析结果
// ========== 规范化统计 ==========
struct NormalizationStats {
size_t totalLoops; // 总循环数
size_t loopsNeedingPreheader; // 需要前置块的循环数
size_t preheadersCreated; // 创建的前置块数
size_t loopsNormalized; // 规范化的循环数
NormalizationStats() : totalLoops(0), loopsNeedingPreheader(0),
preheadersCreated(0), loopsNormalized(0) {}
} stats;
// ========== 核心规范化方法 ==========
/**
* 规范化单个循环
* @param loop 要规范化的循环
* @return 是否进行了修改
*/
bool normalizeLoop(Loop* loop);
/**
* 为循环创建前置块
* @param loop 需要前置块的循环
* @return 创建的前置块如果失败则返回nullptr
*/
BasicBlock* createPreheaderForLoop(Loop* loop);
/**
* 检查循环是否需要前置块
* @param loop 要检查的循环
* @return true如果需要前置块
*/
bool needsPreheader(Loop* loop);
/**
* 检查循环是否已有合适的前置块
* @param loop 要检查的循环
* @return 现有的前置块如果没有则返回nullptr
*/
BasicBlock* getExistingPreheader(Loop* loop);
/**
* 更新支配树关系(在创建新块后)
* @param newBlock 新创建的基本块
* @param loop 相关的循环
*/
void updateDominatorRelations(BasicBlock* newBlock, Loop* loop);
/**
* 重定向循环外的前驱块到新的前置块
* @param loop 目标循环
* @param preheader 新创建的前置块
* @param header 循环头部
*/
void redirectExternalPredecessors(Loop* loop, BasicBlock* preheader, BasicBlock* header);
/**
* 为前置块生成合适的名称
* @param loop 相关的循环
* @return 生成的前置块名称
*/
std::string generatePreheaderName(Loop* loop);
/**
* 验证规范化结果的正确性
* @param loop 规范化后的循环
* @return true如果规范化正确
*/
bool validateNormalization(Loop* loop);
// ========== 辅助方法 ==========
/**
* 获取循环的外部前驱块(不在循环内的前驱)
* @param loop 目标循环
* @return 外部前驱块列表
*/
std::vector<BasicBlock*> getExternalPredecessors(Loop* loop);
/**
* 检查基本块是否适合作为前置块
* @param block 候选基本块
* @param loop 目标循环
* @return true如果适合作为前置块
*/
bool isSuitableAsPreheader(BasicBlock* block, Loop* loop);
/**
* 更新PHI节点以适应新的前置块
* @param header 循环头部
* @param preheader 新的前置块
* @param oldPreds 原来的外部前驱
*/
void updatePhiNodesForPreheader(BasicBlock* header, BasicBlock* preheader,
const std::vector<BasicBlock*>& oldPreds);
/**
* 打印规范化统计信息
*/
void printStats(Function* F);
};
} // namespace sysy

View File

@@ -17,6 +17,7 @@ add_library(midend_lib STATIC
Pass/Optimize/Reg2Mem.cpp
Pass/Optimize/SysYIRCFGOpt.cpp
Pass/Optimize/SCCP.cpp
Pass/Optimize/LoopNormalization.cpp
)
# 包含中端模块所需的头文件路径

View File

@@ -0,0 +1,432 @@
#include "LoopNormalization.h"
#include "Dom.h"
#include "Loop.h"
#include "LoopCharacteristics.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; // 没有循环需要规范化
}
loopCharacteristics = AM.getAnalysisResult<LoopCharacteristicsResult, LoopCharacteristicsPass>(F);
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);
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);
// 重定向外部前驱到新的前置块
redirectExternalPredecessors(loop, preheader, header);
// 更新PHI节点
updatePhiNodesForPreheader(header, preheader, externalPreds);
// 更新支配树关系
updateDominatorRelations(preheader, loop);
return preheader;
}
bool LoopNormalizationPass::needsPreheader(Loop* loop) {
// 检查是否已有合适的前置块
if (getExistingPreheader(loop) != nullptr) {
return false;
}
// 检查是否有外部前驱(如果没有外部前驱,不需要前置块)
std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
if (externalPreds.empty()) {
return false;
}
// 如果有多个外部前驱,或者单个外部前驱不适合作为前置块,则需要创建前置块
if (externalPreds.size() > 1) {
return true;
}
// 检查唯一的外部前驱是否适合作为前置块
return !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) {
// 这里需要更新支配树关系
// 新的前置块应该支配循环头部,并且被循环外的前驱支配
if (DEBUG) {
std::cout << " Updating dominator relations for new preheader " << newBlock->getName() << std::endl;
}
// 实际的支配树更新逻辑在这里实现
// 由于支配树分析通常在Pass运行后重新计算这里主要是标记需要更新
}
void LoopNormalizationPass::redirectExternalPredecessors(Loop* loop, BasicBlock* preheader, BasicBlock* header) {
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) {
// 需要更新操作数
br->setOperand(0, preheader);
// 更新CFG关系
header->removePredecessor(pred);
preheader->addPredecessor(pred);
pred->removeSuccessor(header);
pred->addSuccessor(preheader);
if (DEBUG)
std::cout << " Updated unconditional branch from " << pred->getName()
<< " to " << preheader->getName() << std::endl;
}
} 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;
}
// 检查外部前驱是否适合作为前置块
if (!isSuitableAsPreheader(externalPreds[0], loop)) {
if (DEBUG)
std::cout << " Validation failed: External predecessor " << externalPreds[0]->getName()
<< " is not suitable as preheader" << 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;
}
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::vector<std::pair<Value*, BasicBlock*>> externalValues;
for (BasicBlock* oldPred : oldPreds) {
Value* value = phi->getvalfromBlk(oldPred);
if (value) {
externalValues.push_back({value, oldPred});
}
}
// 从PHI节点中移除旧的外部前驱
for (BasicBlock* oldPred : oldPreds) {
phi->removeIncoming(oldPred);
}
// 如果有多个来自外部的值需要在前置块中创建新的PHI节点
if (externalValues.size() > 1) {
// 在前置块中创建新的PHI节点来合并外部值
builder->setPosition(preheader, preheader->getInstructions().begin());
std::vector<Value*> values;
std::vector<BasicBlock*> blocks;
for (auto& [value, block] : externalValues) {
values.push_back(value);
blocks.push_back(block);
}
PhiInst* newPhi = builder->createPhiInst(phi->getType(), values, blocks, "preheader.phi");
// 将新PHI的结果作为来自前置块的值添加到原PHI中
phi->addIncoming(newPhi, preheader);
} else if (externalValues.size() == 1) {
// 只有一个外部值,直接添加
phi->addIncoming(externalValues[0].first, preheader);
}
}
}
}
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;
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(&LoopCharacteristicsPass::ID); // 循环特征分析
analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); // 支配树分析
// LoopNormalization会修改CFG结构因此会使以下分析失效
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树需要重新计算
// 注意:循环结构分析可能需要更新,但我们不让它失效,因为我们只是添加前置块
// analysisInvalidations.insert(&LoopAnalysisPass::ID); // 通常不需要失效
// analysisInvalidations.insert(&LoopCharacteristicsPass::ID); // 通常不需要失效
}
} // namespace sysy