fix(mir): 线性扫描区间分裂修复 + 多定义点 vreg 跳过逻辑修复

- 区间分裂: last.end = cur.start (而非 cur.end),确保 save point 之后寄存器值正确
- 多定义点 vreg: 改为按区间覆盖检查,支持 phi-copy 插入的多定义场景
- 30_many_dimensions 已修复(19D 嵌套循环输出正确)
- 25_while_if 循环变量映射仍有 bug,待进一步修复
lzk
lzkk 4 days ago
parent fbea91986d
commit 28c336728d

@ -214,10 +214,21 @@ namespace mir
{
LiveInterval &cur = queue[qi];
// 同一 vreg 可能有多个 LiveInterval分割产生跳过已处理(已有范围)的
if (cur.vreg >= 0 && cur.vreg < num_vregs &&
vreg_has_range[cur.vreg])
continue;
// 检查当前区间是否已被覆盖split 产生的溢出区间已有 vreg_ranges 条目)
if (cur.vreg >= 0 && cur.vreg < num_vregs)
{
bool already_covered = false;
for (const auto &rng : vreg_ranges[cur.vreg])
{
if (rng.start <= cur.start && cur.end <= rng.end)
{
already_covered = true;
break;
}
}
if (already_covered)
continue;
}
// 选择对应寄存器池
const int K = (cur.vreg_class == VRegClass::Float) ? K_FP : K_GP;
@ -269,10 +280,10 @@ namespace mir
VRegRange &last = ranges.back();
if (last.reg_idx == stolen_reg)
{
// 把 last.end 截断到 cur.end后半段新建溢出范围
// 截断范围:寄存器在 cur.start 通过 save point 保存后即被 cur 覆写
int orig_end = last.end;
last.end = cur.end;
vreg_ranges[evicted_vreg].push_back({cur.end + 1, orig_end, -1});
last.end = cur.start;
vreg_ranges[evicted_vreg].push_back({cur.start + 1, orig_end, -1});
// 在此位置需要保存被驱逐的值到栈
int slot = GetOrCreateSpillSlot(func, evicted_vreg, vreg_to_slot);
@ -281,7 +292,7 @@ namespace mir
// 把分割后的溢出部分送回队列(它以 evicted 的 vreg 标识,但 vreg_has_range 已为真)
LiveInterval split_li;
split_li.vreg = evicted_vreg;
split_li.start = cur.end + 1;
split_li.start = cur.start + 1;
split_li.end = orig_end;
split_li.vreg_class = spill_cand.interval->vreg_class;
split_li.spilled = true;

Loading…
Cancel
Save