fix(regalloc): MAX_SPILL_ROUNDS=1 + 保守修复阈值 20→200,修复 spill 错误代码

根因:block-level liveness 下多轮 spill 创建的 reload vreg 与保守修复
(block_defs 全干涉)交互,产生错误寄存器分配,导致段错误/输出不匹配。

修复:
- MAX_SPILL_ROUNDS 3→1:防止多轮 spill 产生错误 reload vreg
- 保守修复阈值 20→200:避免过度干涉导致图着色错误分配

修复用例:
- 04_arr_defn3:段错误 → 正确 (14)
- 05_arr_defn4:错误输出 → 正确 (21)
- 09_BFS:bad_alloc/段错误 → 正确
- 13_LCA、54_hidden_var 等多个预存故障也一并修复

剩余已知问题:84_long_array2(编译超时)、30_many_dimensions(GEP偏移)
lzk
lzkk 4 days ago
parent ca6c9fa540
commit c12b6830b8

@ -555,7 +555,9 @@ namespace mir
}
// 保守修复:对包含大量 vreg 定义的 block强制 def 间全干涉
// 防止 spill reload vreg 的短活区间导致错误寄存器复用
// 防止 spill reload vreg 的短活区间导致错误寄存器复用。
// 阈值从 20 提高到 200——低阈值与 MAX_SPILL_ROUNDS=1 组合在
// 09_BFS 等函数上导致过度干涉,图着色产生错误分配。
for (size_t bi = 0; bi < blocks.size(); ++bi)
{
std::set<int> block_defs;
@ -566,7 +568,7 @@ namespace mir
if (d >= 0 && IsGPClass(function.GetVRegClass(d)))
block_defs.insert(d);
}
if (block_defs.size() > 20)
if (block_defs.size() > 200)
{
for (int u : block_defs)
for (int v : block_defs)
@ -1422,10 +1424,12 @@ namespace mir
if (function.GetNumVRegs() == 0)
return;
// 限制 spill 轮次,防止 spill 代码指数级膨胀。
// 大函数(>120 vreg最多 3 轮,普通函数最多 3 轮。
// 10 轮在 67-vreg 的 mm1 上产生了 11,785 个 spill slot (14→25→48→...→5890)
const int MAX_SPILL_ROUNDS = 3;
// 限制 spill 轮次为 1block-level liveness 下多轮 spill 创建
// 的 reload vreg 与保守修复block_defs 全干涉)交互,产生错误
// 寄存器分配。1 轮足够——循环外 RewriteWithAllocation 用 scratch
// 寄存器处理所有剩余 spill。修复04_arr_defn3/05_arr_defn4 段错误
// 及 09_BFS bad_alloc。
const int MAX_SPILL_ROUNDS = 1;
for (int round = 0; round < MAX_SPILL_ROUNDS; ++round)
{
// 构建 VReg → 定义指令映射(用于再物化判断)

Loading…
Cancel
Save