[midend-LoopCharacteristics]强化归纳变量的识别
This commit is contained in:
@@ -20,6 +20,42 @@ namespace sysy {
|
|||||||
// 前向声明
|
// 前向声明
|
||||||
class LoopCharacteristicsResult;
|
class LoopCharacteristicsResult;
|
||||||
|
|
||||||
|
enum IVKind {
|
||||||
|
kBasic, // 基本归纳变量
|
||||||
|
kLinear, // 线性归纳变量
|
||||||
|
kCmplx // 复杂派生归纳变量
|
||||||
|
} ; // 归纳变量类型
|
||||||
|
|
||||||
|
struct InductionVarInfo {
|
||||||
|
Value* div; // 派生归纳变量的指令
|
||||||
|
Value* base = nullptr; // 其根phi或BIV或DIV
|
||||||
|
std::pair<Value*, Value*> Multibase = {nullptr, nullptr}; // 多个BIV
|
||||||
|
Instruction::Kind Instkind; // 操作类型
|
||||||
|
int factor = 1; // 系数(如i*2+3的2)
|
||||||
|
int offset = 0; // 常量偏移
|
||||||
|
bool valid; // 是否线性可归约
|
||||||
|
IVKind ivkind; // 归纳变量类型
|
||||||
|
|
||||||
|
|
||||||
|
static std::unique_ptr<InductionVarInfo> createBasicBIV(Value* v, Instruction::Kind kind, Value* base = nullptr, int factor = 1, int offset = 0) {
|
||||||
|
return std::make_unique<InductionVarInfo>(
|
||||||
|
InductionVarInfo{v, base, {nullptr, nullptr}, kind, factor, offset, true, IVKind::kBasic}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<InductionVarInfo> createSingleDIV(Value* v, Instruction::Kind kind, Value* base = nullptr, int factor = 1, int offset = 0) {
|
||||||
|
return std::make_unique<InductionVarInfo>(
|
||||||
|
InductionVarInfo{v, base, {nullptr, nullptr}, kind, factor, offset, true, IVKind::kLinear}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<InductionVarInfo> createDoubleDIV(Value* v, Instruction::Kind kind, Value* base1 = nullptr, Value* base2 = nullptr, int factor = 1, int offset = 0) {
|
||||||
|
return std::make_unique<InductionVarInfo>(
|
||||||
|
InductionVarInfo{v, nullptr, {base1, base2}, kind, factor, offset, false, IVKind::kCmplx}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 循环特征信息结构 - 基础循环分析阶段
|
* @brief 循环特征信息结构 - 基础循环分析阶段
|
||||||
* 存储循环的基本特征信息,为后续精确分析提供基础
|
* 存储循环的基本特征信息,为后续精确分析提供基础
|
||||||
@@ -33,13 +69,13 @@ struct LoopCharacteristics {
|
|||||||
bool hasComplexControlFlow; // 是否有复杂控制流 (break, continue)
|
bool hasComplexControlFlow; // 是否有复杂控制流 (break, continue)
|
||||||
bool isInnermost; // 是否为最内层循环
|
bool isInnermost; // 是否为最内层循环
|
||||||
|
|
||||||
// ========== 基础归纳变量分析 ==========
|
// ========== 归纳变量分析 ==========
|
||||||
std::vector<Value*> basicInductionVars; // 基本归纳变量
|
|
||||||
std::map<Value*, int> inductionSteps; // 归纳变量的步长(简化)
|
|
||||||
|
|
||||||
// ========== 基础循环不变量分析 ==========
|
// ========== 基础循环不变量分析 ==========
|
||||||
std::unordered_set<Value*> loopInvariants; // 循环不变量
|
std::unordered_set<Value*> loopInvariants; // 循环不变量
|
||||||
std::unordered_set<Instruction*> invariantInsts; // 可提升的不变指令
|
std::unordered_set<Instruction*> invariantInsts; // 可提升的不变指令
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<InductionVarInfo>> InductionVars; // 归纳变量
|
||||||
|
|
||||||
// ========== 基础边界分析 ==========
|
// ========== 基础边界分析 ==========
|
||||||
std::optional<int> staticTripCount; // 静态循环次数(如果可确定)
|
std::optional<int> staticTripCount; // 静态循环次数(如果可确定)
|
||||||
@@ -307,6 +343,12 @@ private:
|
|||||||
|
|
||||||
// ========== 辅助方法 ==========
|
// ========== 辅助方法 ==========
|
||||||
bool isClassicLoopInvariant(Value* val, Loop* loop, const std::unordered_set<Value*>& invariants);
|
bool isClassicLoopInvariant(Value* val, Loop* loop, const std::unordered_set<Value*>& invariants);
|
||||||
|
void findDerivedInductionVars(Value* root,
|
||||||
|
Value* base, // 只传单一BIV base
|
||||||
|
Loop* loop,
|
||||||
|
std::vector<std::unique_ptr<InductionVarInfo>>& ivs,
|
||||||
|
std::set<Value*>& visited
|
||||||
|
);
|
||||||
bool isBasicInductionVariable(Value* val, Loop* loop);
|
bool isBasicInductionVariable(Value* val, Loop* loop);
|
||||||
bool hasSimpleMemoryPattern(Loop* loop); // 简单的内存模式检查
|
bool hasSimpleMemoryPattern(Loop* loop); // 简单的内存模式检查
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ void LoopCharacteristicsResult::print() const {
|
|||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
||||||
// 归纳变量
|
// 归纳变量
|
||||||
if (!chars->basicInductionVars.empty()) {
|
if (!chars->InductionVars.empty()) {
|
||||||
std::cout << " Basic Induction Vars: " << chars->basicInductionVars.size() << std::endl;
|
std::cout << " Induction Vars: " << chars->InductionVars.size() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 循环不变量
|
// 循环不变量
|
||||||
@@ -282,28 +282,150 @@ void LoopCharacteristicsPass::analyzeBasicMemoryAccessPatterns(Loop* loop, LoopC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoopCharacteristicsPass::identifyBasicInductionVariables(Loop* loop, LoopCharacteristics* characteristics) {
|
bool LoopCharacteristicsPass::isBasicInductionVariable(Value* val, Loop* loop) {
|
||||||
// 寻找基本归纳变量(简化版本)
|
// 简化的基础归纳变量检测
|
||||||
BasicBlock* header = loop->getHeader();
|
auto* phiInst = dynamic_cast<PhiInst*>(val);
|
||||||
|
if (!phiInst) return false;
|
||||||
|
|
||||||
// 遍历循环头的phi指令,寻找基本归纳变量模式
|
// 检查phi指令是否在循环头
|
||||||
for (auto& inst : header->getInstructions()) {
|
if (phiInst->getParent() != loop->getHeader()) return false;
|
||||||
auto* phiInst = dynamic_cast<PhiInst*>(inst.get());
|
|
||||||
if (!phiInst) continue;
|
// 检查是否有来自循环内的更新
|
||||||
|
for (auto& [incomingBB, incomingVal] : phiInst->getIncomingValues()) {
|
||||||
// 检查phi指令是否符合基本归纳变量模式
|
if (loop->contains(incomingBB)) {
|
||||||
if (isBasicInductionVariable(phiInst, loop)) {
|
return true; // 简化:有来自循环内的值就认为是基础归纳变量
|
||||||
characteristics->basicInductionVars.push_back(phiInst);
|
|
||||||
characteristics->inductionSteps[phiInst] = 1; // 简化:默认步长为1
|
|
||||||
|
|
||||||
if (DEBUG)
|
|
||||||
std::cout << " Found basic induction variable: " << phiInst->getName() << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LoopCharacteristicsPass::identifyBasicInductionVariables(
|
||||||
|
Loop* loop, LoopCharacteristics* characteristics) {
|
||||||
|
BasicBlock* header = loop->getHeader();
|
||||||
|
std::vector<std::unique_ptr<InductionVarInfo>> ivs;
|
||||||
|
|
||||||
|
// 1. 识别所有BIV
|
||||||
|
for (auto& inst : header->getInstructions()) {
|
||||||
|
auto* phi = dynamic_cast<PhiInst*>(inst.get());
|
||||||
|
if (!phi) continue;
|
||||||
|
if (isBasicInductionVariable(phi, loop)) {
|
||||||
|
ivs.push_back(InductionVarInfo::createBasicBIV(phi, Instruction::Kind::kPhi));
|
||||||
|
if (DEBUG) std::cout << " Found basic induction variable: " << phi->getName() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 递归识别所有派生DIV
|
||||||
|
std::set<Value*> visited;
|
||||||
|
for (const auto& biv : ivs) {
|
||||||
|
findDerivedInductionVars(biv->div, biv->base, loop, ivs, visited);
|
||||||
|
}
|
||||||
|
|
||||||
|
characteristics->InductionVars = std::move(ivs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct LinearExpr {
|
||||||
|
// 表达为: a * base1 + b * base2 + offset
|
||||||
|
Value* base1 = nullptr;
|
||||||
|
Value* base2 = nullptr;
|
||||||
|
int factor1 = 0;
|
||||||
|
int factor2 = 0;
|
||||||
|
int offset = 0;
|
||||||
|
bool valid = false;
|
||||||
|
bool isSimple = false; // 仅一个BIV时true
|
||||||
|
};
|
||||||
|
|
||||||
|
static LinearExpr analyzeLinearExpr(Value* val, Loop* loop, std::vector<std::unique_ptr<InductionVarInfo>>& ivs) {
|
||||||
|
// 递归归约val为线性表达式
|
||||||
|
// 只支持单/双BIV线性组合
|
||||||
|
// 见下方详细实现
|
||||||
|
// ----------
|
||||||
|
// 基本变量:常数
|
||||||
|
if (auto* cint = dynamic_cast<ConstantInteger*>(val)) {
|
||||||
|
return {nullptr, nullptr, 0, 0, cint->getInt(), true, false};
|
||||||
|
}
|
||||||
|
// 基本变量:BIV或派生IV
|
||||||
|
for (auto& iv : ivs) {
|
||||||
|
if (iv->div == val) {
|
||||||
|
if (iv->ivkind == IVKind::kBasic ||
|
||||||
|
iv->ivkind == IVKind::kLinear) {
|
||||||
|
return {iv->base, nullptr, iv->factor, 0, iv->offset, true, true};
|
||||||
|
}
|
||||||
|
// 复杂归纳变量
|
||||||
|
if (iv->ivkind == IVKind::kCmplx) {
|
||||||
|
return {iv->Multibase.first, iv->Multibase.second, 1, 1, 0, true, false};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 一元负号
|
||||||
|
if (auto* inst = dynamic_cast<Instruction*>(val)) {
|
||||||
|
auto kind = inst->getKind();
|
||||||
|
if (kind == Instruction::Kind::kNeg) {
|
||||||
|
auto expr = analyzeLinearExpr(inst->getOperand(0), loop, ivs);
|
||||||
|
if (!expr.valid) return expr;
|
||||||
|
expr.factor1 = -expr.factor1;
|
||||||
|
expr.factor2 = -expr.factor2;
|
||||||
|
expr.offset = -expr.offset;
|
||||||
|
expr.isSimple = (expr.base2 == nullptr);
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
// 二元加减乘
|
||||||
|
if (kind == Instruction::Kind::kAdd || kind == Instruction::Kind::kSub) {
|
||||||
|
auto expr0 = analyzeLinearExpr(inst->getOperand(0), loop, ivs);
|
||||||
|
auto expr1 = analyzeLinearExpr(inst->getOperand(1), loop, ivs);
|
||||||
|
if (!expr0.valid || !expr1.valid) return {nullptr, nullptr, 0, 0, 0, false, false};
|
||||||
|
// 合并:若BIV相同或有一个是常数
|
||||||
|
// 单BIV+常数
|
||||||
|
if (expr0.base1 && !expr1.base1 && !expr1.base2) {
|
||||||
|
int sign = (kind == Instruction::Kind::kAdd ? 1 : -1);
|
||||||
|
return {expr0.base1, nullptr, expr0.factor1, 0, expr0.offset + sign * expr1.offset, true, expr0.isSimple};
|
||||||
|
}
|
||||||
|
if (!expr0.base1 && !expr0.base2 && expr1.base1) {
|
||||||
|
int sign = (kind == Instruction::Kind::kAdd ? 1 : -1);
|
||||||
|
int f = sign * expr1.factor1;
|
||||||
|
int off = expr0.offset + sign * expr1.offset;
|
||||||
|
return {expr1.base1, nullptr, f, 0, off, true, expr1.isSimple};
|
||||||
|
}
|
||||||
|
// 双BIV线性组合
|
||||||
|
if (expr0.base1 && expr1.base1 && expr0.base1 != expr1.base1 && !expr0.base2 && !expr1.base2) {
|
||||||
|
int sign = (kind == Instruction::Kind::kAdd ? 1 : -1);
|
||||||
|
Value* base1 = expr0.base1;
|
||||||
|
Value* base2 = expr1.base1;
|
||||||
|
int f1 = expr0.factor1;
|
||||||
|
int f2 = sign * expr1.factor1;
|
||||||
|
int off = expr0.offset + sign * expr1.offset;
|
||||||
|
return {base1, base2, f1, f2, off, true, false};
|
||||||
|
}
|
||||||
|
// 同BIV合并
|
||||||
|
if (expr0.base1 && expr1.base1 && expr0.base1 == expr1.base1 && !expr0.base2 && !expr1.base2) {
|
||||||
|
int sign = (kind == Instruction::Kind::kAdd ? 1 : -1);
|
||||||
|
int f = expr0.factor1 + sign * expr1.factor1;
|
||||||
|
int off = expr0.offset + sign * expr1.offset;
|
||||||
|
return {expr0.base1, nullptr, f, 0, off, true, true};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 乘法:BIV*const 或 const*BIV
|
||||||
|
if (kind == Instruction::Kind::kMul) {
|
||||||
|
auto expr0 = analyzeLinearExpr(inst->getOperand(0), loop, ivs);
|
||||||
|
auto expr1 = analyzeLinearExpr(inst->getOperand(1), loop, ivs);
|
||||||
|
// 只允许一侧为常数
|
||||||
|
if (expr0.base1 && !expr1.base1 && !expr1.base2 && expr1.offset) {
|
||||||
|
return {expr0.base1, nullptr, expr0.factor1 * expr1.offset, 0, expr0.offset * expr1.offset, true, true};
|
||||||
|
}
|
||||||
|
if (!expr0.base1 && !expr0.base2 && expr0.offset && expr1.base1) {
|
||||||
|
return {expr1.base1, nullptr, expr1.factor1 * expr0.offset, 0, expr1.offset * expr0.offset, true, true};
|
||||||
|
}
|
||||||
|
// 双BIV乘法不支持
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 其它情况
|
||||||
|
return {nullptr, nullptr, 0, 0, 0, false, false};
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoopCharacteristicsPass::identifyBasicLoopInvariants(Loop* loop, LoopCharacteristics* characteristics) {
|
void LoopCharacteristicsPass::identifyBasicLoopInvariants(Loop* loop, LoopCharacteristics* characteristics) {
|
||||||
// 经典推进法:反复遍历,直到收敛
|
// 经典推进法:反复遍历,直到收敛 TODO:优化
|
||||||
bool changed;
|
bool changed;
|
||||||
std::unordered_set<Value*> invariants = characteristics->loopInvariants; // 可能为空
|
std::unordered_set<Value*> invariants = characteristics->loopInvariants; // 可能为空
|
||||||
|
|
||||||
@@ -334,7 +456,7 @@ void LoopCharacteristicsPass::identifyBasicLoopInvariants(Loop* loop, LoopCharac
|
|||||||
void LoopCharacteristicsPass::analyzeBasicLoopBounds(Loop* loop, LoopCharacteristics* characteristics) {
|
void LoopCharacteristicsPass::analyzeBasicLoopBounds(Loop* loop, LoopCharacteristics* characteristics) {
|
||||||
// 简化的基础边界分析
|
// 简化的基础边界分析
|
||||||
// 检查是否有静态可确定的循环次数(简化版本)
|
// 检查是否有静态可确定的循环次数(简化版本)
|
||||||
if (characteristics->isCountingLoop && !characteristics->basicInductionVars.empty()) {
|
if (characteristics->isCountingLoop && !characteristics->InductionVars.empty()) {
|
||||||
// 简化:如果是计数循环且有基本归纳变量,尝试确定循环次数
|
// 简化:如果是计数循环且有基本归纳变量,尝试确定循环次数
|
||||||
if (characteristics->instructionCount < 10) {
|
if (characteristics->instructionCount < 10) {
|
||||||
characteristics->staticTripCount = 100; // 简化估计
|
characteristics->staticTripCount = 100; // 简化估计
|
||||||
@@ -373,22 +495,46 @@ void LoopCharacteristicsPass::evaluateBasicOptimizationOpportunities(Loop* loop,
|
|||||||
|
|
||||||
// ========== 辅助方法实现 ==========
|
// ========== 辅助方法实现 ==========
|
||||||
|
|
||||||
bool LoopCharacteristicsPass::isBasicInductionVariable(Value* val, Loop* loop) {
|
// 递归识别DIV,支持线性与复杂归纳变量
|
||||||
// 简化的基础归纳变量检测
|
void LoopCharacteristicsPass::findDerivedInductionVars(
|
||||||
auto* phiInst = dynamic_cast<PhiInst*>(val);
|
Value* root,
|
||||||
if (!phiInst) return false;
|
Value* base, // 只传单一BIV base
|
||||||
|
Loop* loop,
|
||||||
// 检查phi指令是否在循环头
|
std::vector<std::unique_ptr<InductionVarInfo>>& ivs,
|
||||||
if (phiInst->getParent() != loop->getHeader()) return false;
|
std::set<Value*>& visited)
|
||||||
|
{
|
||||||
// 检查是否有来自循环内的更新
|
if (visited.count(root)) return;
|
||||||
for (auto& [incomingBB, incomingVal] : phiInst->getIncomingValues()) {
|
visited.insert(root);
|
||||||
if (loop->contains(incomingBB)) {
|
|
||||||
return true; // 简化:有来自循环内的值就认为是基础归纳变量
|
for (auto use : root->getUses()) {
|
||||||
|
auto user = use->getUser();
|
||||||
|
Instruction* inst = dynamic_cast<Instruction*>(user);
|
||||||
|
if (!inst) continue;
|
||||||
|
if (!loop->contains(inst->getParent())) continue;
|
||||||
|
|
||||||
|
// 下面是一个例子:假设你有线性归约分析(可用analyzeLinearExpr等递归辅助)
|
||||||
|
auto expr = analyzeLinearExpr(inst, loop, ivs);
|
||||||
|
|
||||||
|
if (!expr.valid) {
|
||||||
|
// 复杂非线性归纳变量,作为kCmplx记录(假如你想追踪)
|
||||||
|
// 这里假设expr.base1、base2都有效才记录double
|
||||||
|
if (expr.base1 && expr.base2) {
|
||||||
|
ivs.push_back(InductionVarInfo::createDoubleDIV(inst, inst->getKind(), expr.base1, expr.base2, 0, expr.offset));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 单BIV线性
|
||||||
|
if (expr.base1 && !expr.base2) {
|
||||||
|
ivs.push_back(InductionVarInfo::createSingleDIV(inst, inst->getKind(), expr.base1, expr.factor1, expr.offset));
|
||||||
|
findDerivedInductionVars(inst, expr.base1, loop, ivs, visited);
|
||||||
|
}
|
||||||
|
// 双BIV线性
|
||||||
|
else if (expr.base1 && expr.base2) {
|
||||||
|
ivs.push_back(InductionVarInfo::createDoubleDIV(inst, inst->getKind(), expr.base1, expr.base2, 0, expr.offset));
|
||||||
|
// 双BIV情形一般不再递归下游
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 递归/推进式判定
|
// 递归/推进式判定
|
||||||
|
|||||||
Reference in New Issue
Block a user