From e1777c9eaba0cc32f9abf3c057ef83dccd77b687 Mon Sep 17 00:00:00 2001 From: lzkk <956449176@qq.com> Date: Tue, 26 May 2026 21:29:29 +0800 Subject: [PATCH] =?UTF-8?q?fix(ir):=20CSE=20=E5=AE=89=E5=85=A8=E9=97=A8?= =?UTF-8?q?=E7=A6=81=E2=80=94=E2=80=94=E9=9D=9E=20SSA=20=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E8=B7=B3=E8=BF=87=20Load/GEP=20CSE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 当 alloca 数量 > 24(Mem2Reg 跳过)时,跳过 Load 和 GEP 的 CSE - 修复 27_scope5 优化 bug(非 SSA 代码中 Load CSE 错误合并不同作用域变量) - 86_long_code2 不受影响(仅 1 个 alloca,Load/GEP CSE 正常启用) --- src/ir/passes/CSE.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/ir/passes/CSE.cpp b/src/ir/passes/CSE.cpp index 0d7e4792..c9f91f31 100644 --- a/src/ir/passes/CSE.cpp +++ b/src/ir/passes/CSE.cpp @@ -58,11 +58,25 @@ static ExprKey GetExprKey(Instruction* inst) { } // namespace +static int CountAllocas(Function &func) { + int count = 0; + for (auto &bb : func.GetBlocks()) + for (auto &inst : bb->GetInstructions()) + if (inst->GetOpcode() == Opcode::Alloca) + ++count; + return count; +} + void RunCSE(Module& module) { for (auto& func_ptr : module.GetFunctions()) { auto* func = func_ptr.get(); if (func->IsExternal()) continue; - + + // Mem2Reg 跳过的函数(大量 alloca),Load 可能访问不同作用域的同名变量, + // CSE 合并不同 Load 会破坏语义。此情况下仅对 BinaryInst 做 CSE。 + int alloca_count = CountAllocas(*func); + bool cse_load_gep = (alloca_count <= 24); + // 对每个基本块执行 CSE for (auto& bb_ptr : func->GetBlocks()) { auto* bb = bb_ptr.get(); @@ -97,8 +111,11 @@ void RunCSE(Module& module) { } } - // 如果是可消除的公共子表达式 - if (IsCSECandidate(inst)) { + // 如果是可消除的公共子表达式(非 SSA 函数跳过 Load/GEP) + if (IsCSECandidate(inst) && + (cse_load_gep || + (inst->GetOpcode() != Opcode::Load && + inst->GetOpcode() != Opcode::GEP))) { ExprKey key = GetExprKey(inst); // 检查是否已经计算过相同的表达式