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); // 检查是否已经计算过相同的表达式