[midend-Loop]初步构建循环规范遍
This commit is contained in:
155
src/include/midend/Pass/Optimize/LoopNormalization.h
Normal file
155
src/include/midend/Pass/Optimize/LoopNormalization.h
Normal 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
|
||||||
@@ -17,6 +17,7 @@ add_library(midend_lib STATIC
|
|||||||
Pass/Optimize/Reg2Mem.cpp
|
Pass/Optimize/Reg2Mem.cpp
|
||||||
Pass/Optimize/SysYIRCFGOpt.cpp
|
Pass/Optimize/SysYIRCFGOpt.cpp
|
||||||
Pass/Optimize/SCCP.cpp
|
Pass/Optimize/SCCP.cpp
|
||||||
|
Pass/Optimize/LoopNormalization.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# 包含中端模块所需的头文件路径
|
# 包含中端模块所需的头文件路径
|
||||||
|
|||||||
432
src/midend/Pass/Optimize/LoopNormalization.cpp
Normal file
432
src/midend/Pass/Optimize/LoopNormalization.cpp
Normal 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
|
||||||
Reference in New Issue
Block a user