diff --git a/src/mir/InstLiveness.cpp b/src/mir/InstLiveness.cpp index 0e7f789c..23690108 100644 --- a/src/mir/InstLiveness.cpp +++ b/src/mir/InstLiveness.cpp @@ -375,7 +375,19 @@ namespace mir // — remove from live so that earlier positions don't see it // (unless a later use re-adds it for the prior value). if (def_vreg >= 0) + { + // 记录 def 位置作为区间起点。即使 def vreg 不在当前活跃集中 + // (跨块数据流边界情况可能导致),区间也必须覆盖 def 位置, + // 确保寄存器分配在定义点能找到对应的范围。 + auto sit = vreg_start.find(def_vreg); + if (sit == vreg_start.end() || pos < sit->second) + vreg_start[def_vreg] = pos; + auto eit = vreg_end.find(def_vreg); + if (eit == vreg_end.end() || pos > eit->second) + vreg_end[def_vreg] = pos; + live.erase(def_vreg); + } } // After processing all instructions, live should equal live_in. diff --git a/src/mir/LinearScanAlloc.cpp b/src/mir/LinearScanAlloc.cpp index 933868b4..990ae827 100644 --- a/src/mir/LinearScanAlloc.cpp +++ b/src/mir/LinearScanAlloc.cpp @@ -15,10 +15,12 @@ namespace mir // ---- AArch64 可分配寄存器 -------------------------------------------- - // GP 可分配:x8(间接结果)/x9-x12/temp/x15/x16-x17/IP0-IP1/x19-x28/callee-saved - // x0-x7 参数传递,x13-x14 临时(被排除避免调用冲突),x18 平台,x29-31 保留 - static const int GP_ALLOCATABLE[] = {8, 9, 10, 11, 12, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28}; - static const int K_GP = 18; + // GP 可分配:x19-x28(callee-saved)。当前限定为 callee-saved + // 避免跨函数调用时 caller-saved 寄存器被破坏。TODO:后续可加入 + // caller-saved 寄存器(x8-x12,x15-x17)用于不跨调用活跃的 vreg。 + // x0-x7 参数传递,x13-x14/scratch,x18 平台,x29-31 保留。 + static const int GP_ALLOCATABLE[] = {19, 20, 21, 22, 23, 24, 25, 26, 27, 28}; + static const int K_GP = 10; // FP 可分配:s8-s31 static const int FP_ALLOCATABLE[] = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; @@ -323,6 +325,29 @@ namespace mir } } + // ---- 记录 callee-saved 寄存器使用 ---- + // 当前 GP_ALLOCATABLE 全为 callee-saved(x19-x28),遍历已分配的 + // 范围找出实际使用的寄存器,通知 FrameLowering 保存/恢复。 + std::unordered_set used_callee_gp; + std::unordered_set used_callee_fp; + for (int vi = 0; vi < num_vregs; ++vi) + { + for (const auto &rng : vreg_ranges[vi]) + { + if (rng.reg_idx < 0) + continue; + VRegClass vc = func.GetVRegClass(vi); + if (vc == VRegClass::Float) + used_callee_fp.insert(rng.reg_idx); + else + used_callee_gp.insert(rng.reg_idx); + } + } + for (int idx : used_callee_gp) + func.AddCalleeSavedReg(AllocIdxToPhysReg(idx, VRegClass::Int)); + for (int idx : used_callee_fp) + func.AddCalleeSavedReg(AllocIdxToPhysReg(idx, VRegClass::Float)); + // ---- 重写指令 ---------------------------------------------------------- RewriteWithAllocation(func, vreg_ranges, vreg_to_slot, save_points); } diff --git a/src/utils/CLI.cpp b/src/utils/CLI.cpp index 1f37c290..375dae9e 100644 --- a/src/utils/CLI.cpp +++ b/src/utils/CLI.cpp @@ -88,8 +88,8 @@ CLIOptions ParseCLI(int argc, char** argv) { } // 寄存器分配器选择 - if (std::strncmp(arg, "--regalloc=", 12) == 0) { - opt.regalloc = arg + 12; + if (std::strncmp(arg, "--regalloc=", 11) == 0) { + opt.regalloc = arg + 11; if (opt.regalloc != "linear" && opt.regalloc != "graphcoloring") { throw std::runtime_error( FormatError("cli", std::string("未知寄存器分配器: ") + opt.regalloc +