From 120140abd1c0e3b659f6a69c0ff602fa4dccbd8c Mon Sep 17 00:00:00 2001 From: lzkk <956449176@qq.com> Date: Thu, 28 May 2026 20:19:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9F=BA=E7=A1=80=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 11 + src/ir/passes/LoopUnroll.cpp | 654 ++++++++++++----------------------- 2 files changed, 227 insertions(+), 438 deletions(-) diff --git a/.gitignore b/.gitignore index 9852433d..2bdf62b8 100644 --- a/.gitignore +++ b/.gitignore @@ -116,3 +116,14 @@ Error.txt time_opt.txt settings.json 指令数基线.md + +.claude/ +.claudeignore +.codegraph/ +.count_tmp.s +results.csv +results.json +Error.txt +time_opt.txt +settings.json +指令数基线.md diff --git a/src/ir/passes/LoopUnroll.cpp b/src/ir/passes/LoopUnroll.cpp index 7f7a184d..f3345404 100644 --- a/src/ir/passes/LoopUnroll.cpp +++ b/src/ir/passes/LoopUnroll.cpp @@ -1,350 +1,30 @@ // 简单 countdown 循环全展开: // - 处理形如 while(len) { body; len = len - 1; } 的递减循环 -// - 支持多块体(含 if-else):自动 if-convert 为算术 select 后展开 -// - 要求 len 初值为编译时常量且 ≤64 -// - 全展开后函数可能变为单 BB,可被 Inline 内联 +// - 要求 body 为单 BB,len 初值为编译时常量且 ≤64 +// - 全展开后函数变为单 BB,可被 Inline 内联 // - 配合 ConstFold 将 len/power 等常量传播到每次迭代 #include "ir/IR.h" #include #include -#include #include namespace ir { namespace { -// 展开 icmp ne (zext(X), 0) → X -static Value* UnwrapCondition(Value* cond) { - for (int pass = 0; pass < 2; ++pass) { - auto* outer = dynamic_cast(cond); - if (!outer || outer->GetOpcode() != Opcode::Ne) break; - auto* rc = dynamic_cast(outer->GetRhs()); - if (!rc || rc->GetValue() != 0) break; - auto* zext = dynamic_cast(outer->GetLhs()); - if (!zext || zext->GetOpcode() != Opcode::ZExt) break; - cond = zext->GetOperandValue(); - } - return cond; -} - -// 获取块的唯一无条件跳转目标,否则 nullptr -static BasicBlock* GetOnlySuccessor(BasicBlock* bb) { - const auto& insts = bb->GetInstructions(); - if (insts.empty()) return nullptr; - auto* br = dynamic_cast(insts.back().get()); - return br ? br->GetTarget() : nullptr; -} - -// 查找从 start 到 header 路径上的所有块(循环体块),不包含 header 本身 -static void FindLoopBodyBlocks(BasicBlock* start, BasicBlock* header, - std::unordered_set& loop_blocks) { - std::vector worklist; - std::unordered_set visited; - worklist.push_back(start); - while (!worklist.empty()) { - auto* bb = worklist.back(); - worklist.pop_back(); - if (bb == header || !visited.insert(bb).second) continue; - loop_blocks.insert(bb); - for (const auto& inst : bb->GetInstructions()) { - if (auto* br = dynamic_cast(inst.get())) - worklist.push_back(br->GetTarget()); - else if (auto* cbr = dynamic_cast(inst.get())) { - worklist.push_back(cbr->GetTrueTarget()); - worklist.push_back(cbr->GetFalseTarget()); - } - if (inst->IsTerminator()) break; - } - } -} - -// 判断块是否可安全 if-convert(无副作用) -static bool IsSimpleBlock(BasicBlock* bb) { - for (const auto& inst : bb->GetInstructions()) { - switch (inst->GetOpcode()) { - case Opcode::Add: case Opcode::Sub: case Opcode::Mul: - case Opcode::Div: case Opcode::Mod: - case Opcode::And: case Opcode::Or: - case Opcode::Eq: case Opcode::Ne: case Opcode::Lt: - case Opcode::Le: case Opcode::Gt: case Opcode::Ge: - case Opcode::ZExt: case Opcode::SIToFP: case Opcode::FPToSI: - case Opcode::Br: - continue; - default: - return false; - } - } - return true; -} - -// phi 辅助函数 -static Value* GetPhiValueFrom(PhiInst* phi, BasicBlock* bb) { - for (size_t i = 0; i < phi->GetNumOperands(); i += 2) { - auto* pred = dynamic_cast(phi->GetOperand(i + 1)); - if (pred == bb) return phi->GetOperand(i); - } - return nullptr; -} - -static void RemovePhiEntriesFrom(PhiInst* phi, BasicBlock* bb) { - std::vector> keep; - for (size_t i = 0; i < phi->GetNumOperands(); i += 2) { - auto* pred = dynamic_cast(phi->GetOperand(i + 1)); - if (pred != bb) - keep.push_back({phi->GetOperand(i), phi->GetOperand(i + 1)}); - } - if (keep.size() * 2 != phi->GetNumOperands()) { - phi->ClearOperands(); - for (auto& [val, pred] : keep) { - phi->AddOperand(val); - phi->AddOperand(pred); - } - } -} - -static void SetPhiEntry(PhiInst* phi, BasicBlock* bb, Value* val) { - for (size_t i = 0; i < phi->GetNumOperands(); i += 2) { - if (dynamic_cast(phi->GetOperand(i + 1)) == bb) { - phi->SetOperand(i, val); - return; - } - } - phi->AddOperand(val); - phi->AddOperand(bb); -} - -// 尝试对单个 diamond 做 if-conversion: B → CondBr → T → Br → M, F == M -// 返回 true 表示转换成功 -static bool TryIfConvertDiamond(BasicBlock* B, BasicBlock* T, BasicBlock* F, - Value* cond_i1, Context& ctx) { - if (!IsSimpleBlock(T)) return false; - BasicBlock* M = F; - if (GetOnlySuccessor(T) != M) return false; - - // 收集 M 中需要转换的 phi 节点 - struct PhiEntry { PhiInst* phi; Value* val_t; Value* val_f; }; - std::vector to_convert; - for (const auto& inst : M->GetInstructions()) { - auto* phi = dynamic_cast(inst.get()); - if (!phi) break; - Value* val_t = GetPhiValueFrom(phi, T); - if (!val_t) continue; - Value* val_f = GetPhiValueFrom(phi, B); - if (!val_f) { - for (size_t i = 0; i < phi->GetNumOperands(); i += 2) { - auto* pred = dynamic_cast(phi->GetOperand(i + 1)); - if (pred != T) { val_f = phi->GetOperand(i); break; } - } - } - if (!val_f) continue; - to_convert.push_back({phi, val_t, val_f}); - } - if (to_convert.empty()) return false; - - // 移除 B 的 CondBr - auto* cbr = B->GetInstructions().back().get(); - B->TakeInstruction(cbr); - - // 移动 T 的非终止指令到 B - std::vector t_to_move; - for (const auto& inst : T->GetInstructions()) - if (inst->GetOpcode() != Opcode::Br) - t_to_move.push_back(inst.get()); - for (auto* inst : t_to_move) { - auto taken = T->TakeInstruction(inst); - B->InsertInstructionBeforeTerminator(std::move(taken)); - } - // 移除 T 的 Br - if (!T->GetInstructions().empty()) - T->TakeInstruction(T->GetInstructions().back().get()); - - // 生成算术 select: fv + (tv - fv) * zext(cond) - for (auto& [phi, val_t, val_f] : to_convert) { - if (val_t == val_f) { - RemovePhiEntriesFrom(phi, T); - SetPhiEntry(phi, B, val_f); - continue; - } - auto* zext = B->Append(Opcode::ZExt, - Type::GetInt32Type(), cond_i1, ctx.NextTemp()); - auto* diff = B->Append(Opcode::Sub, Type::GetInt32Type(), - val_t, val_f, ctx.NextTemp()); - auto* masked = B->Append(Opcode::Mul, Type::GetInt32Type(), - diff, zext, ctx.NextTemp()); - auto* select_val = B->Append(Opcode::Add, Type::GetInt32Type(), - val_f, masked, ctx.NextTemp()); - RemovePhiEntriesFrom(phi, T); - SetPhiEntry(phi, B, select_val); - } - - B->Append(Type::GetVoidType(), M); - return true; -} - -// 对循环体内的 diamond 做迭代 if-conversion(从内向外) -static void IfConvertLoopBody(const std::unordered_set& loop_blocks, - Context& ctx) { - bool changed = true; - while (changed) { - changed = false; - for (auto* bb : loop_blocks) { - const auto& insts = bb->GetInstructions(); - if (insts.empty()) continue; - auto* cbr = dynamic_cast(insts.back().get()); - if (!cbr) continue; - - BasicBlock* T = cbr->GetTrueTarget(); - BasicBlock* F = cbr->GetFalseTarget(); - // 只转换 T 在循环体内且 F 在循环体内(或 F 是 latch 合并且仍在体内) - if (!loop_blocks.count(T)) continue; - Value* cond = UnwrapCondition(cbr->GetCond()); - - if (TryIfConvertDiamond(bb, T, F, cond, ctx)) { - changed = true; - break; - } - } - } - - // 清理仅剩单一条目的 phi - for (auto* bb : loop_blocks) { - auto& insts = const_cast>&>( - bb->GetInstructions()); - for (size_t i = 0; i < insts.size(); ) { - auto* phi = dynamic_cast(insts[i].get()); - if (!phi) break; - Value* unique_val = nullptr; - bool all_same = true; - for (size_t j = 0; j < phi->GetNumOperands(); j += 2) { - Value* v = phi->GetOperand(j); - if (!unique_val) unique_val = v; - else if (unique_val != v) { all_same = false; break; } - } - if (all_same && unique_val) { - phi->ReplaceAllUsesWith(unique_val); - phi->ClearOperands(); - insts.erase(insts.begin() + i); - continue; - } - ++i; - } - } -} - -// 合并循环体内单前驱无 phi 块(将链式 BB 压平) -static void MergeLoopBodyBlocks(const std::unordered_set& loop_blocks, - Function* func) { - // 构建使用 def-use 信息计算前驱 - auto compute_preds = [&](BasicBlock* bb) -> std::vector { - std::vector preds; - for (auto* other : loop_blocks) { - if (other == bb) continue; - const auto& insts = other->GetInstructions(); - if (insts.empty()) continue; - auto* term = insts.back().get(); - if (auto* br = dynamic_cast(term)) { - if (br->GetTarget() == bb) preds.push_back(other); - } else if (auto* cbr = dynamic_cast(term)) { - if (cbr->GetTrueTarget() == bb || cbr->GetFalseTarget() == bb) - preds.push_back(other); - } - } - return preds; - }; - - bool changed = true; - while (changed) { - changed = false; - for (auto* bb : loop_blocks) { - // 检查是否有 phi - bool has_phi = false; - for (const auto& inst : bb->GetInstructions()) { - if (dynamic_cast(inst.get())) { has_phi = true; break; } - } - if (has_phi) continue; - - auto preds = compute_preds(bb); - if (preds.size() != 1) continue; - BasicBlock* pred = preds[0]; - if (pred == bb) continue; - - // pred 必须以无条件 Br 指向 bb - auto* pred_term = pred->GetInstructions().back().get(); - auto* br = dynamic_cast(pred_term); - if (!br || br->GetTarget() != bb) continue; - - // 合并:移除 pred 的 terminator - pred->TakeInstruction(pred_term); - - // 移动 bb 的所有指令到 pred - auto& bb_insts = const_cast>&>( - bb->GetInstructions()); - std::vector to_move; - for (auto& inst : bb_insts) - to_move.push_back(inst.get()); - - for (auto* inst : to_move) { - auto taken = bb->TakeInstruction(inst); - pred->InsertInstructionBeforeTerminator(std::move(taken)); - } - - // 更新后继块的 phi:将对 bb 的引用改为 pred - for (auto* succ_bb : loop_blocks) { - if (succ_bb == bb) continue; - auto& succ_insts = const_cast>&>( - succ_bb->GetInstructions()); - for (auto& inst : succ_insts) { - auto* phi = dynamic_cast(inst.get()); - if (!phi) break; - for (size_t i = 0; i < phi->GetNumOperands(); i += 2) { - if (dynamic_cast(phi->GetOperand(i + 1)) == bb) - phi->SetOperand(i + 1, pred); - } - } - } - - // 也要更新 header 的 phi - auto* header = func->GetEntry(); // will be found by scanning - // 实际上 header 不在 loop_blocks 中,需要单独处理 - for (const auto& hdr_bb : func->GetBlocks()) { - for (const auto& inst : hdr_bb->GetInstructions()) { - auto* phi = dynamic_cast(inst.get()); - if (!phi) break; - for (size_t i = 0; i < phi->GetNumOperands(); i += 2) { - if (dynamic_cast(phi->GetOperand(i + 1)) == bb) - phi->SetOperand(i + 1, pred); - } - } - } - - changed = true; - break; - } - } -} - // 检测递减循环模式,返回 (phi, trip_count) 或 nullptr -// 支持多块体:header → body_entry → ... → latch → header -static PhiInst* DetectSimpleCountdown(BasicBlock* header, BasicBlock* body_entry, +static PhiInst* DetectSimpleCountdown(BasicBlock* header, BasicBlock* body, BasicBlock* exit_bb, int& trip_count) { - // 找到 latch(循环体内分支回 header 的块) - BasicBlock* latch = nullptr; - std::unordered_set loop_blocks; - FindLoopBodyBlocks(body_entry, header, loop_blocks); - - for (auto* bb : loop_blocks) { - for (const auto& inst : bb->GetInstructions()) { - if (auto* br = dynamic_cast(inst.get())) - if (br->GetTarget() == header) { latch = bb; break; } - } - if (latch) break; + // 检查 body → header 回边 + bool has_backedge = false; + for (const auto& inst : body->GetInstructions()) { + if (auto* br = dynamic_cast(inst.get())) + if (br->GetTarget() == header) has_backedge = true; } - if (!latch) return nullptr; + if (!has_backedge) return nullptr; - // 查找 header 中的 countdown phi for (const auto& inst : header->GetInstructions()) { auto* phi = dynamic_cast(inst.get()); if (!phi) continue; @@ -357,8 +37,8 @@ static PhiInst* DetectSimpleCountdown(BasicBlock* header, BasicBlock* body_entry Value* init_val = nullptr; Value* update_val = nullptr; - if (bb0 != latch && bb1 == latch) { init_val = val0; update_val = val1; } - else if (bb1 != latch && bb0 == latch) { init_val = val1; update_val = val0; } + if (bb0 != body && bb1 == body) { init_val = val0; update_val = val1; } + else if (bb1 != body && bb0 == body) { init_val = val1; update_val = val0; } else continue; auto* init_c = dynamic_cast(init_val); @@ -377,7 +57,14 @@ static PhiInst* DetectSimpleCountdown(BasicBlock* header, BasicBlock* body_entry for (const auto& inst : header->GetInstructions()) { if (auto* cbr = dynamic_cast(inst.get())) { Value* cond = cbr->GetCond(); - cond = UnwrapCondition(cond); + if (auto* outer = dynamic_cast(cond)) { + if (outer->GetOpcode() == Opcode::Ne) { + auto* rc = dynamic_cast(outer->GetRhs()); + if (rc && rc->GetValue() == 0) + if (auto* zext = dynamic_cast(outer->GetLhs())) + if (zext->GetOpcode() == Opcode::ZExt) cond = zext->GetOperandValue(); + } + } if (auto* cmp = dynamic_cast(cond)) { Value* other = nullptr; if (cmp->GetLhs() == phi) other = cmp->GetRhs(); @@ -454,40 +141,11 @@ static std::unique_ptr CloneInstruction( } // 展开 countdown 循环 -static bool UnrollSimple(Function* func, BasicBlock* header, BasicBlock* body_entry, +static bool UnrollSimple(Function* func, BasicBlock* header, BasicBlock* body, BasicBlock* exit_bb, PhiInst* phi, int trip_count, Context& ctx) { auto& fb = const_cast>&>(func->GetBlocks()); - // 找所有循环体块 - std::unordered_set loop_blocks; - FindLoopBodyBlocks(body_entry, header, loop_blocks); - - // 找 latch(含回边的块) - BasicBlock* latch = nullptr; - for (auto* bb : loop_blocks) { - for (const auto& inst : bb->GetInstructions()) { - if (auto* br = dynamic_cast(inst.get())) - if (br->GetTarget() == header) latch = bb; - } - } - - // if-convert 循环体内的 diamond 模式 - IfConvertLoopBody(loop_blocks, ctx); - - // 合并不再有 phi 的链式块 - MergeLoopBodyBlocks(loop_blocks, func); - - // 重新找 body(if-conversion 后 body_entry 可能已变) - BasicBlock* body = nullptr; - for (auto* bb : loop_blocks) { - for (const auto& inst : bb->GetInstructions()) { - if (auto* br = dynamic_cast(inst.get())) - if (br->GetTarget() == header) body = bb; - } - } - if (!body) body = body_entry; - // 收集 body 指令(不含回边) std::vector body_insts; for (const auto& inst : body->GetInstructions()) { @@ -509,46 +167,14 @@ static bool UnrollSimple(Function* func, BasicBlock* header, BasicBlock* body_en if (preheader) break; } - // 收集循环体中所有 phi 的初始值和步进值(用于跨迭代值映射) - struct PhiMapping { - PhiInst* phi; - Value* init_val; - Instruction* latch_val; // 指令在 latch 中产生下一个迭代的值 - }; - std::vector phi_mappings; - for (const auto& inst : header->GetInstructions()) { - auto* hdr_phi = dynamic_cast(inst.get()); - if (!hdr_phi) break; - if (hdr_phi == phi) continue; // len 特殊处理 - - Value* init = nullptr; - Value* latch_val = nullptr; - for (size_t i = 0; i < hdr_phi->GetNumOperands(); i += 2) { - auto* pred = dynamic_cast(hdr_phi->GetOperand(i + 1)); - if (pred != latch && pred != body) init = hdr_phi->GetOperand(i); - else latch_val = hdr_phi->GetOperand(i); - } - if (init && latch_val) - phi_mappings.push_back({hdr_phi, init, dynamic_cast(latch_val)}); - } - // 克隆 N 次 std::vector> new_blocks; - std::unordered_map prev_values; // phi → 上次迭代产生的新值 - for (auto& pm : phi_mappings) - prev_values[pm.phi] = pm.init_val; - for (int iter = 0; iter < trip_count; ++iter) { auto new_bb = std::make_unique(ctx.NextTemp() + "_unroll"); std::unordered_map vm; - - // phi 替换:len → 常量,其他 → 上次迭代的值 vm[phi] = ctx.GetConstInt(trip_count - iter); - for (auto& pm : phi_mappings) - vm[pm.phi] = prev_values[pm.phi]; for (auto* inst : body_insts) { - // 跳过 len = len - 1 if (auto* bin = dynamic_cast(inst)) if (bin->GetOpcode() == Opcode::Sub && bin->GetLhs() == phi) continue; @@ -558,13 +184,6 @@ static bool UnrollSimple(Function* func, BasicBlock* header, BasicBlock* body_en new_bb->InsertInstructionBeforeTerminator(std::move(cloned)); } - // 更新下次迭代的 phi 值 - for (auto& pm : phi_mappings) { - auto it = vm.find(pm.latch_val); - if (it != vm.end()) - prev_values[pm.phi] = it->second; - } - // 最后一份 body 后跳到 exit if (iter == trip_count - 1) { auto br_exit = std::make_unique(Type::GetVoidType(), exit_bb); @@ -588,7 +207,7 @@ static bool UnrollSimple(Function* func, BasicBlock* header, BasicBlock* body_en } } - // 删除 header + 循环体块,插入新块 + // 删除 header + body,插入新块 auto ipos = fb.begin(); if (preheader) { for (auto it = fb.begin(); it != fb.end(); ++it) @@ -596,15 +215,197 @@ static bool UnrollSimple(Function* func, BasicBlock* header, BasicBlock* body_en } for (auto& nb : new_blocks) ipos = fb.insert(ipos, std::move(nb)) + 1; - - // 移除 header 和所有循环体块 fb.erase(std::remove_if(fb.begin(), fb.end(), [&](const std::unique_ptr& bb) { - return bb.get() == header || loop_blocks.count(bb.get()); + return bb.get() == header || bb.get() == body; }), fb.end()); return true; } +// 展开 icmp ne (zext(X), 0) → X +static Value* UnwrapZExtCond(Value* cond) { + if (auto* outer = dynamic_cast(cond)) { + if (outer->GetOpcode() == Opcode::Ne) { + auto* rc = dynamic_cast(outer->GetRhs()); + if (rc && rc->GetValue() == 0) + if (auto* zext = dynamic_cast(outer->GetLhs())) + if (zext->GetOpcode() == Opcode::ZExt) + return zext->GetOperandValue(); + } + } + return cond; +} + +// 简化含 if-else 的循环体:将简单 diamond 转成算术 select 使体变单 BB +// 模式: body → CondBr → if_then → Br → merge +// ↘ merge +// 其中 if_then 只有一条 add 指令 +static bool SimplifyLoopBody(Function* func, Context& ctx) { + bool changed = false; + + for (const auto& bb : func->GetBlocks()) { + const auto& insts = bb->GetInstructions(); + if (insts.empty()) continue; + auto* cbr = dynamic_cast(insts.back().get()); + if (!cbr) continue; + + BasicBlock* T = cbr->GetTrueTarget(); + BasicBlock* F = cbr->GetFalseTarget(); + BasicBlock* B = bb.get(); + + // 只处理一个分支有单条 add、另一分支直达 merge 的模式 + auto check_simple_if = [](BasicBlock* then_bb, BasicBlock* merge_bb) -> Instruction* { + const auto& ti = then_bb->GetInstructions(); + // 恰好两条指令: add + br + if (ti.size() != 2) return nullptr; + auto* add = dynamic_cast(ti[0].get()); + if (!add || add->GetOpcode() != Opcode::Add) return nullptr; + auto* br = dynamic_cast(ti[1].get()); + if (!br || br->GetTarget() != merge_bb) return nullptr; + return add; + }; + + // 模式: T 有 add+Br 到 F + if (auto* add = check_simple_if(T, F)) { + // 检查 F 有 phi 合并来自 B 和 T 的值 + for (const auto& mi : F->GetInstructions()) { + auto* phi = dynamic_cast(mi.get()); + if (!phi) break; + Value* val_t = nullptr; + Value* val_f = nullptr; + for (size_t i = 0; i < phi->GetNumOperands(); i += 2) { + auto* pred = dynamic_cast(phi->GetOperand(i + 1)); + if (pred == T) val_t = phi->GetOperand(i); + if (pred == B) val_f = phi->GetOperand(i); + } + if (!val_t || !val_f) continue; + + // if-convert: fv + (tv - fv) * zext(cond) + Value* cond = UnwrapZExtCond(cbr->GetCond()); + + // 移除 B 的 CondBr + B->TakeInstruction(cbr); + + // 移动 T 的 add 指令到 B + auto add_owned = T->TakeInstruction(add); + B->InsertInstructionBeforeTerminator(std::move(add_owned)); + + // 生成算术 select + auto* zext = B->Append(Opcode::ZExt, + Type::GetInt32Type(), cond, ctx.NextTemp()); + auto* diff = B->Append(Opcode::Sub, Type::GetInt32Type(), + val_t, val_f, ctx.NextTemp()); + auto* masked = B->Append(Opcode::Mul, Type::GetInt32Type(), + diff, zext, ctx.NextTemp()); + auto* sel = B->Append(Opcode::Add, Type::GetInt32Type(), + val_f, masked, ctx.NextTemp()); + + // 更新 phi: 移除 T 条目,将 B 条目值设为 sel + std::vector> keep; + for (size_t i = 0; i < phi->GetNumOperands(); i += 2) { + auto* pred = dynamic_cast(phi->GetOperand(i + 1)); + if (pred != T && pred != B) + keep.push_back({phi->GetOperand(i), phi->GetOperand(i + 1)}); + } + phi->ClearOperands(); + phi->AddOperand(sel); + phi->AddOperand(B); + for (auto& [v, p] : keep) { + phi->AddOperand(v); + phi->AddOperand(p); + } + + // B 跳转到 F + B->Append(Type::GetVoidType(), F); + + // 清理 T(移除其 Br,T 变为空块) + auto& t_insts = const_cast>&>(T->GetInstructions()); + if (!t_insts.empty()) T->TakeInstruction(t_insts.back().get()); + + changed = true; + goto next_block; + } + } + next_block:; + } + + // 合并单前驱无 phi 块 + for (const auto& bb : func->GetBlocks()) { + // 计算前驱 + std::vector preds; + for (const auto& other : func->GetBlocks()) { + if (other.get() == bb.get()) continue; + const auto& oi = other->GetInstructions(); + if (oi.empty()) continue; + if (auto* br = dynamic_cast(oi.back().get())) + if (br->GetTarget() == bb.get()) preds.push_back(other.get()); + } + if (preds.size() != 1) continue; + BasicBlock* pred = preds[0]; + + // 检查无 phi + bool has_phi = false; + for (const auto& mi : bb->GetInstructions()) + if (dynamic_cast(mi.get())) { has_phi = true; break; } + if (has_phi) continue; + + // pred 必须以无条件 Br 指向此块 + auto* pred_term = pred->GetInstructions().back().get(); + auto* br = dynamic_cast(pred_term); + if (!br || br->GetTarget() != bb.get()) continue; + + // 合并: pred 移除 terminator, 移入 bb 的全部指令 + pred->TakeInstruction(pred_term); + auto& bb_insts = const_cast>&>(bb->GetInstructions()); + std::vector to_move; + for (auto& mi : bb_insts) to_move.push_back(mi.get()); + for (auto* mi : to_move) { + auto taken = bb->TakeInstruction(mi); + pred->InsertInstructionBeforeTerminator(std::move(taken)); + } + + // 更新后继块 phi 中对 bb 的引用 + for (const auto& succ : func->GetBlocks()) { + auto& si = const_cast>&>(succ->GetInstructions()); + for (auto& mi : si) { + auto* phi = dynamic_cast(mi.get()); + if (!phi) break; + for (size_t i = 0; i < phi->GetNumOperands(); i += 2) + if (dynamic_cast(phi->GetOperand(i + 1)) == bb.get()) + phi->SetOperand(i + 1, pred); + } + } + + changed = true; + break; + } + + // 清理冗余 phi(单一条目或所有值相同) + for (const auto& bb : func->GetBlocks()) { + auto& insts = const_cast>&>(bb->GetInstructions()); + for (size_t i = 0; i < insts.size(); ) { + auto* phi = dynamic_cast(insts[i].get()); + if (!phi) break; + Value* unique_val = nullptr; + bool all_same = true; + for (size_t j = 0; j < phi->GetNumOperands(); j += 2) { + Value* v = phi->GetOperand(j); + if (!unique_val) unique_val = v; + else if (unique_val != v) { all_same = false; break; } + } + if (all_same && unique_val) { + phi->ReplaceAllUsesWith(unique_val); + phi->ClearOperands(); + insts.erase(insts.begin() + i); + continue; + } + ++i; + } + } + + return changed; +} + } // namespace void RunLoopUnroll(Module& module) { @@ -612,6 +413,10 @@ void RunLoopUnroll(Module& module) { for (auto& func : module.GetFunctions()) { if (func->IsExternal()) continue; if (!func->GetType()->IsInt32()) continue; + + // 先简化循环体: if-convert + merge, 让多块体变单块体 + while (SimplifyLoopBody(func.get())) {} + bool changed = true; while (changed) { changed = false; @@ -624,42 +429,15 @@ void RunLoopUnroll(Module& module) { auto* cbr = dynamic_cast(tgt_inst.get()); if (!cbr) continue; BasicBlock *t = cbr->GetTrueTarget(), *f = cbr->GetFalseTarget(); - - // 确定循环体入口和出口 - BasicBlock *body_entry = nullptr, *exit_bb = nullptr; - // 模式1: bb 是 preheader(bb → header → body/exit) - // 找 header 的哪个后继包含回到 header 的路径 - for (auto* cand : {t, f}) { - std::unordered_set temp; - FindLoopBodyBlocks(cand, target, temp); - bool has_backedge = false; - for (auto* lb : temp) { - for (const auto& li : lb->GetInstructions()) { - if (auto* lbr = dynamic_cast(li.get())) - if (lbr->GetTarget() == target) has_backedge = true; - } - } - if (has_backedge) body_entry = cand; - } - if (!body_entry) { - // 回退到原有逻辑:body_entry 是等于 bb 的那个 - if (t == bb.get()) { body_entry = t; exit_bb = f; } - else if (f == bb.get()) { body_entry = f; exit_bb = t; } - else continue; - } - // 找 exit - if (!exit_bb) { - if (body_entry == t) exit_bb = f; - else exit_bb = t; - } - - // 不能自指 - if (!body_entry || !exit_bb || body_entry == target || exit_bb == target) continue; + BasicBlock *body = nullptr, *exit_bb = nullptr; + if (t == bb.get()) { body = t; exit_bb = f; } + else if (f == bb.get()) { body = f; exit_bb = t; } + if (!body || !exit_bb || body == target || exit_bb == target) continue; int tc = 0; - auto* phi = DetectSimpleCountdown(target, body_entry, exit_bb, tc); + auto* phi = DetectSimpleCountdown(target, body, exit_bb, tc); if (!phi) continue; - if (UnrollSimple(func.get(), target, body_entry, exit_bb, phi, tc, + if (UnrollSimple(func.get(), target, body, exit_bb, phi, tc, module.GetContext())) { ++unrolled; changed = true; goto next_func; }