diff --git a/src/include/midend/Pass/Analysis/LoopCharacteristics.h b/src/include/midend/Pass/Analysis/LoopCharacteristics.h index a9e3d5b..e5ccafb 100644 --- a/src/include/midend/Pass/Analysis/LoopCharacteristics.h +++ b/src/include/midend/Pass/Analysis/LoopCharacteristics.h @@ -20,6 +20,42 @@ namespace sysy { // 前向声明 class LoopCharacteristicsResult; +enum IVKind { + kBasic, // 基本归纳变量 + kLinear, // 线性归纳变量 + kCmplx // 复杂派生归纳变量 +} ; // 归纳变量类型 + +struct InductionVarInfo { + Value* div; // 派生归纳变量的指令 + Value* base = nullptr; // 其根phi或BIV或DIV + std::pair 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 createBasicBIV(Value* v, Instruction::Kind kind, Value* base = nullptr, int factor = 1, int offset = 0) { + return std::make_unique( + InductionVarInfo{v, base, {nullptr, nullptr}, kind, factor, offset, true, IVKind::kBasic} + ); +} + +static std::unique_ptr createSingleDIV(Value* v, Instruction::Kind kind, Value* base = nullptr, int factor = 1, int offset = 0) { + return std::make_unique( + InductionVarInfo{v, base, {nullptr, nullptr}, kind, factor, offset, true, IVKind::kLinear} + ); +} + +static std::unique_ptr createDoubleDIV(Value* v, Instruction::Kind kind, Value* base1 = nullptr, Value* base2 = nullptr, int factor = 1, int offset = 0) { + return std::make_unique( + InductionVarInfo{v, nullptr, {base1, base2}, kind, factor, offset, false, IVKind::kCmplx} + ); +} +}; + /** * @brief 循环特征信息结构 - 基础循环分析阶段 * 存储循环的基本特征信息,为后续精确分析提供基础 @@ -33,13 +69,13 @@ struct LoopCharacteristics { bool hasComplexControlFlow; // 是否有复杂控制流 (break, continue) bool isInnermost; // 是否为最内层循环 - // ========== 基础归纳变量分析 ========== - std::vector basicInductionVars; // 基本归纳变量 - std::map inductionSteps; // 归纳变量的步长(简化) + // ========== 归纳变量分析 ========== // ========== 基础循环不变量分析 ========== std::unordered_set loopInvariants; // 循环不变量 std::unordered_set invariantInsts; // 可提升的不变指令 + + std::vector> InductionVars; // 归纳变量 // ========== 基础边界分析 ========== std::optional staticTripCount; // 静态循环次数(如果可确定) @@ -307,6 +343,12 @@ private: // ========== 辅助方法 ========== bool isClassicLoopInvariant(Value* val, Loop* loop, const std::unordered_set& invariants); + void findDerivedInductionVars(Value* root, + Value* base, // 只传单一BIV base + Loop* loop, + std::vector>& ivs, + std::set& visited + ); bool isBasicInductionVariable(Value* val, Loop* loop); bool hasSimpleMemoryPattern(Loop* loop); // 简单的内存模式检查 }; diff --git a/src/midend/Pass/Analysis/LoopCharacteristics.cpp b/src/midend/Pass/Analysis/LoopCharacteristics.cpp index 58c0c11..c6f6d2c 100644 --- a/src/midend/Pass/Analysis/LoopCharacteristics.cpp +++ b/src/midend/Pass/Analysis/LoopCharacteristics.cpp @@ -80,8 +80,8 @@ void LoopCharacteristicsResult::print() const { std::cout << std::endl; // 归纳变量 - if (!chars->basicInductionVars.empty()) { - std::cout << " Basic Induction Vars: " << chars->basicInductionVars.size() << std::endl; + if (!chars->InductionVars.empty()) { + 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) { - // 寻找基本归纳变量(简化版本) - BasicBlock* header = loop->getHeader(); +bool LoopCharacteristicsPass::isBasicInductionVariable(Value* val, Loop* loop) { + // 简化的基础归纳变量检测 + auto* phiInst = dynamic_cast(val); + if (!phiInst) return false; - // 遍历循环头的phi指令,寻找基本归纳变量模式 - for (auto& inst : header->getInstructions()) { - auto* phiInst = dynamic_cast(inst.get()); - if (!phiInst) continue; - - // 检查phi指令是否符合基本归纳变量模式 - if (isBasicInductionVariable(phiInst, loop)) { - characteristics->basicInductionVars.push_back(phiInst); - characteristics->inductionSteps[phiInst] = 1; // 简化:默认步长为1 - - if (DEBUG) - std::cout << " Found basic induction variable: " << phiInst->getName() << std::endl; + // 检查phi指令是否在循环头 + if (phiInst->getParent() != loop->getHeader()) return false; + + // 检查是否有来自循环内的更新 + for (auto& [incomingBB, incomingVal] : phiInst->getIncomingValues()) { + if (loop->contains(incomingBB)) { + return true; // 简化:有来自循环内的值就认为是基础归纳变量 } } + + return false; +} + + +void LoopCharacteristicsPass::identifyBasicInductionVariables( + Loop* loop, LoopCharacteristics* characteristics) { + BasicBlock* header = loop->getHeader(); + std::vector> ivs; + + // 1. 识别所有BIV + for (auto& inst : header->getInstructions()) { + auto* phi = dynamic_cast(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 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>& ivs) { + // 递归归约val为线性表达式 + // 只支持单/双BIV线性组合 + // 见下方详细实现 + // ---------- + // 基本变量:常数 + if (auto* cint = dynamic_cast(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(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) { - // 经典推进法:反复遍历,直到收敛 + // 经典推进法:反复遍历,直到收敛 TODO:优化 bool changed; std::unordered_set invariants = characteristics->loopInvariants; // 可能为空 @@ -334,7 +456,7 @@ void LoopCharacteristicsPass::identifyBasicLoopInvariants(Loop* loop, LoopCharac void LoopCharacteristicsPass::analyzeBasicLoopBounds(Loop* loop, LoopCharacteristics* characteristics) { // 简化的基础边界分析 // 检查是否有静态可确定的循环次数(简化版本) - if (characteristics->isCountingLoop && !characteristics->basicInductionVars.empty()) { + if (characteristics->isCountingLoop && !characteristics->InductionVars.empty()) { // 简化:如果是计数循环且有基本归纳变量,尝试确定循环次数 if (characteristics->instructionCount < 10) { characteristics->staticTripCount = 100; // 简化估计 @@ -373,22 +495,46 @@ void LoopCharacteristicsPass::evaluateBasicOptimizationOpportunities(Loop* loop, // ========== 辅助方法实现 ========== -bool LoopCharacteristicsPass::isBasicInductionVariable(Value* val, Loop* loop) { - // 简化的基础归纳变量检测 - auto* phiInst = dynamic_cast(val); - if (!phiInst) return false; - - // 检查phi指令是否在循环头 - if (phiInst->getParent() != loop->getHeader()) return false; - - // 检查是否有来自循环内的更新 - for (auto& [incomingBB, incomingVal] : phiInst->getIncomingValues()) { - if (loop->contains(incomingBB)) { - return true; // 简化:有来自循环内的值就认为是基础归纳变量 +// 递归识别DIV,支持线性与复杂归纳变量 +void LoopCharacteristicsPass::findDerivedInductionVars( + Value* root, + Value* base, // 只传单一BIV base + Loop* loop, + std::vector>& ivs, + std::set& visited) +{ + if (visited.count(root)) return; + visited.insert(root); + + for (auto use : root->getUses()) { + auto user = use->getUser(); + Instruction* inst = dynamic_cast(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; } // 递归/推进式判定