diff --git a/src/mir/LinearScanAlloc.cpp b/src/mir/LinearScanAlloc.cpp index be4ac6ab..933868b4 100644 --- a/src/mir/LinearScanAlloc.cpp +++ b/src/mir/LinearScanAlloc.cpp @@ -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;