Files
mysysy/src/backend/RISCv64/RISCv64LinearScan.cpp
2025-08-05 16:10:04 +08:00

695 lines
35 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "RISCv64LinearScan.h"
#include "RISCv64LLIR.h"
#include "RISCv64ISel.h"
#include "RISCv64Info.h"
#include "RISCv64AsmPrinter.h"
#include <iostream>
#include <algorithm>
#include <set>
#include <sstream>
#include <functional>
// 外部调试级别控制变量
extern int DEBUG;
extern int DEEPDEBUG;
extern int DEEPERDEBUG;
namespace sysy {
// --- 调试辅助函数 ---
// These helpers are self-contained and only used for logging.
static std::string pregToString(PhysicalReg preg) {
// This map is a copy from AsmPrinter to avoid dependency issues.
static const std::map<PhysicalReg, std::string> preg_names = {
{PhysicalReg::ZERO, "zero"}, {PhysicalReg::RA, "ra"}, {PhysicalReg::SP, "sp"}, {PhysicalReg::GP, "gp"}, {PhysicalReg::TP, "tp"},
{PhysicalReg::T0, "t0"}, {PhysicalReg::T1, "t1"}, {PhysicalReg::T2, "t2"}, {PhysicalReg::T3, "t3"}, {PhysicalReg::T4, "t4"}, {PhysicalReg::T5, "t5"}, {PhysicalReg::T6, "t6"},
{PhysicalReg::S0, "s0"}, {PhysicalReg::S1, "s1"}, {PhysicalReg::S2, "s2"}, {PhysicalReg::S3, "s3"}, {PhysicalReg::S4, "s4"}, {PhysicalReg::S5, "s5"}, {PhysicalReg::S6, "s6"}, {PhysicalReg::S7, "s7"}, {PhysicalReg::S8, "s8"}, {PhysicalReg::S9, "s9"}, {PhysicalReg::S10, "s10"}, {PhysicalReg::S11, "s11"},
{PhysicalReg::A0, "a0"}, {PhysicalReg::A1, "a1"}, {PhysicalReg::A2, "a2"}, {PhysicalReg::A3, "a3"}, {PhysicalReg::A4, "a4"}, {PhysicalReg::A5, "a5"}, {PhysicalReg::A6, "a6"}, {PhysicalReg::A7, "a7"},
{PhysicalReg::F0, "f0"}, {PhysicalReg::F1, "f1"}, {PhysicalReg::F2, "f2"}, {PhysicalReg::F3, "f3"}, {PhysicalReg::F4, "f4"}, {PhysicalReg::F5, "f5"}, {PhysicalReg::F6, "f6"}, {PhysicalReg::F7, "f7"},
{PhysicalReg::F8, "f8"}, {PhysicalReg::F9, "f9"}, {PhysicalReg::F10, "f10"}, {PhysicalReg::F11, "f11"}, {PhysicalReg::F12, "f12"}, {PhysicalReg::F13, "f13"}, {PhysicalReg::F14, "f14"}, {PhysicalReg::F15, "f15"},
{PhysicalReg::F16, "f16"}, {PhysicalReg::F17, "f17"}, {PhysicalReg::F18, "f18"}, {PhysicalReg::F19, "f19"}, {PhysicalReg::F20, "f20"}, {PhysicalReg::F21, "f21"}, {PhysicalReg::F22, "f22"}, {PhysicalReg::F23, "f23"},
{PhysicalReg::F24, "f24"}, {PhysicalReg::F25, "f25"}, {PhysicalReg::F26, "f26"}, {PhysicalReg::F27, "f27"}, {PhysicalReg::F28, "f28"}, {PhysicalReg::F29, "f29"}, {PhysicalReg::F30, "f30"}, {PhysicalReg::F31, "f31"},
{PhysicalReg::INVALID, "INVALID"}
};
if (preg_names.count(preg)) return preg_names.at(preg);
return "UnknownPreg";
}
template<typename T>
static std::string setToString(const std::set<T>& s, std::function<std::string(T)> formatter) {
std::stringstream ss;
ss << "{ ";
bool first = true;
for (const auto& item : s) {
if (!first) ss << ", ";
ss << formatter(item);
first = false;
}
ss << " }";
return ss.str();
}
static std::string vregSetToString(const std::set<unsigned>& s) {
return setToString<unsigned>(s, [](unsigned v){ return "%v" + std::to_string(v); });
}
static std::string pregSetToString(const std::set<PhysicalReg>& s) {
return setToString<PhysicalReg>(s, pregToString);
}
// Helper function to check if a register is callee-saved.
// Defined locally to avoid scope issues.
static bool isCalleeSaved(PhysicalReg preg) {
if (preg >= PhysicalReg::S0 && preg <= PhysicalReg::S11) return true;
if (preg >= PhysicalReg::F8 && preg <= PhysicalReg::F9) return true;
if (preg >= PhysicalReg::F18 && preg <= PhysicalReg::F27) return true;
return false;
}
RISCv64LinearScan::RISCv64LinearScan(MachineFunction* mfunc)
: MFunc(mfunc),
ISel(mfunc->getISel()),
vreg_type_map(ISel->getVRegTypeMap()) {
allocable_int_regs = {
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3, PhysicalReg::T6,
PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3, PhysicalReg::S4, PhysicalReg::S5, PhysicalReg::S6, PhysicalReg::S7,
PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11,
};
allocable_fp_regs = {
PhysicalReg::F0, PhysicalReg::F1, PhysicalReg::F2, PhysicalReg::F3, PhysicalReg::F4, PhysicalReg::F5, PhysicalReg::F6, PhysicalReg::F7,
PhysicalReg::F10, PhysicalReg::F11, PhysicalReg::F12, PhysicalReg::F13, PhysicalReg::F14, PhysicalReg::F15, PhysicalReg::F16, PhysicalReg::F17,
PhysicalReg::F8, PhysicalReg::F9, PhysicalReg::F18, PhysicalReg::F19, PhysicalReg::F20, PhysicalReg::F21, PhysicalReg::F22,
PhysicalReg::F23, PhysicalReg::F24, PhysicalReg::F25, PhysicalReg::F26, PhysicalReg::F27,
PhysicalReg::F28, PhysicalReg::F29, PhysicalReg::F30, PhysicalReg::F31,
};
if (MFunc->getFunc()) {
int int_arg_idx = 0;
int fp_arg_idx = 0;
for (Argument* arg : MFunc->getFunc()->getArguments()) {
unsigned arg_vreg = ISel->getVReg(arg);
if (arg->getType()->isFloat()) {
if (fp_arg_idx < 8) {
auto preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::F10) + fp_arg_idx++);
abi_vreg_map[arg_vreg] = preg;
}
} else {
if (int_arg_idx < 8) {
auto preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + int_arg_idx++);
abi_vreg_map[arg_vreg] = preg;
}
}
}
}
}
bool RISCv64LinearScan::run() {
if (DEBUG) std::cerr << "===== [LSRA] Running for function: " << MFunc->getName() << " =====\n";
const int MAX_ITERATIONS = 3;
for (int iteration = 1; ; ++iteration) {
if (DEBUG && iteration > 1) {
std::cerr << "\n----- [LSRA] Re-running iteration " << iteration << " -----\n";
}
linearizeBlocks();
computeLiveIntervals();
bool needs_spill = linearScan();
// 如果当前这轮线性扫描不需要溢出,说明分配成功,直接跳出循环。
if (!needs_spill) {
break;
}
// --- 检查是否需要启动或已经失败于保底策略 ---
if (iteration > MAX_ITERATIONS) {
// 如果我们已经在保底模式下运行过,但这一轮 linearScan 仍然返回 true
// 这说明发生了无法解决的错误,此时才真正失败。
if (conservative_spill_mode) {
std::cerr << "\n!!!!!! [LSRA-FATAL] Allocation failed to converge even in Conservative Spill Mode. Triggering final fallback. !!!!!!\n\n";
return false; // 返回失败而不是exit
}
// 这是第一次达到最大迭代次数,触发保底策略。
std::cerr << "\n!!!!!! [LSRA-WARN] Convergence failed after " << MAX_ITERATIONS
<< " iterations. Entering Conservative Spill Mode for the next attempt. !!!!!!\n\n";
conservative_spill_mode = true; // 开启保守溢出模式,将在下一次循环生效
}
// 只要需要溢出,就重写程序
if (DEBUG) std::cerr << "[LSRA] Spilling detected, will rewrite program.\n";
rewriteProgram();
}
if (DEBUG) std::cerr << "[LSRA] Applying final allocation.\n";
applyAllocation();
MFunc->getFrameInfo().vreg_to_preg_map = this->vreg_to_preg_map;
collectUsedCalleeSavedRegs();
if (DEBUG) std::cerr << "===== [LSRA] Finished for function: " << MFunc->getName() << " =====\n\n";
return true; // 分配成功
}
void RISCv64LinearScan::linearizeBlocks() {
linear_order_blocks.clear();
for (auto& mbb : MFunc->getBlocks()) {
linear_order_blocks.push_back(mbb.get());
}
}
void RISCv64LinearScan::computeLiveIntervals() {
if (DEBUG) std::cerr << "[LSRA-Live] Starting live interval computation.\n";
instr_numbering.clear();
live_intervals.clear();
unhandled.clear();
int num = 0;
std::set<int> call_locations;
for (auto* mbb : linear_order_blocks) {
for (auto& instr : mbb->getInstructions()) {
instr_numbering[instr.get()] = num;
if (instr->getOpcode() == RVOpcodes::CALL) call_locations.insert(num);
num += 2;
}
}
if (DEEPDEBUG) std::cerr << " [Live] Starting live variable dataflow analysis...\n";
std::map<const MachineBasicBlock*, std::set<unsigned>> live_in, live_out;
bool changed = true;
int df_iter = 0;
while(changed) {
changed = false;
df_iter++;
std::vector<MachineBasicBlock*> reversed_blocks = linear_order_blocks;
std::reverse(reversed_blocks.begin(), reversed_blocks.end());
for(auto* mbb : reversed_blocks) {
std::set<unsigned> old_live_in = live_in[mbb];
std::set<unsigned> current_live_out;
for (auto* succ : mbb->successors) current_live_out.insert(live_in[succ].begin(), live_in[succ].end());
std::set<unsigned> use, def;
std::set<unsigned> temp_live = current_live_out;
auto& instrs = mbb->getInstructions();
for (auto it = instrs.rbegin(); it != instrs.rend(); ++it) {
use.clear(); def.clear();
getInstrUseDef(it->get(), use, def);
for (unsigned vreg : def) temp_live.erase(vreg);
for (unsigned vreg : use) temp_live.insert(vreg);
}
if (live_in[mbb] != temp_live || live_out[mbb] != current_live_out) {
changed = true;
live_in[mbb] = temp_live;
live_out[mbb] = current_live_out;
}
}
}
if (DEEPDEBUG) std::cerr << " [Live] Dataflow analysis converged after " << df_iter << " iterations.\n";
if (DEEPERDEBUG) {
std::cerr << " [Live-Debug] Live-in sets:\n";
for (auto* mbb : linear_order_blocks) std::cerr << " " << mbb->getName() << ": " << vregSetToString(live_in[mbb]) << "\n";
std::cerr << " [Live-Debug] Live-out sets:\n";
for (auto* mbb : linear_order_blocks) std::cerr << " " << mbb->getName() << ": " << vregSetToString(live_out[mbb]) << "\n";
}
if (DEEPDEBUG) std::cerr << " [Live] Building precise intervals...\n";
std::map<unsigned, int> first_def, last_use;
for (auto* mbb : linear_order_blocks) {
for (auto& instr_ptr : mbb->getInstructions()) {
int instr_num = instr_numbering.at(instr_ptr.get());
std::set<unsigned> use, def;
getInstrUseDef(instr_ptr.get(), use, def);
for (unsigned vreg : def) if (first_def.find(vreg) == first_def.end()) first_def[vreg] = instr_num;
for (unsigned vreg : use) last_use[vreg] = instr_num;
}
}
if (DEEPERDEBUG) {
std::cerr << " [Live-Debug] First def points:\n";
for (auto const& [vreg, pos] : first_def) std::cerr << " %v" << vreg << ": " << pos << "\n";
std::cerr << " [Live-Debug] Last use points:\n";
for (auto const& [vreg, pos] : last_use) std::cerr << " %v" << vreg << ": " << pos << "\n";
}
for (auto const& [vreg, start] : first_def) {
live_intervals.emplace(vreg, LiveInterval(vreg));
auto& interval = live_intervals.at(vreg);
interval.start = start;
interval.end = last_use.count(vreg) ? last_use.at(vreg) : start;
}
for (auto const& [mbb, live_set] : live_out) {
if (mbb->getInstructions().empty()) continue;
int block_end_num = instr_numbering.at(mbb->getInstructions().back().get());
for (unsigned vreg : live_set) {
if (live_intervals.count(vreg)) {
if (DEEPERDEBUG && live_intervals.at(vreg).end < block_end_num) {
std::cerr << " [Live-Debug] Extending interval for %v" << vreg << " from " << live_intervals.at(vreg).end << " to " << block_end_num << " due to live_out of " << mbb->getName() << "\n";
}
live_intervals.at(vreg).end = std::max(live_intervals.at(vreg).end, block_end_num);
}
}
}
for (auto& pair : live_intervals) {
auto& interval = pair.second;
auto it = call_locations.lower_bound(interval.start);
if (it != call_locations.end() && *it < interval.end) interval.crosses_call = true;
}
for (auto& pair : live_intervals) unhandled.push_back(&pair.second);
std::sort(unhandled.begin(), unhandled.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->start < b->start; });
if (DEBUG) {
std::cerr << "[LSRA-Live] Finished. Total intervals: " << unhandled.size() << "\n";
if (DEEPDEBUG) {
std::cerr << " [Live] Computed Intervals (vreg: [start, end]):\n";
for(const auto* interval : unhandled) {
std::cerr << " %v" << interval->vreg << ": [" << interval->start << ", " << interval->end << "]"
<< (interval->crosses_call ? " (crosses call)" : "") << "\n";
}
}
}
// ================== 新增的调试代码 ==================
// 检查活性分析找到的vreg与指令扫描找到的vreg是否一致
if (DEEPERDEBUG) {
// 修正:将 std.set 修改为 std::set
std::set<unsigned> vregs_from_liveness;
for (const auto& pair : live_intervals) {
vregs_from_liveness.insert(pair.first);
}
std::set<unsigned> vregs_from_instr_scan;
for (auto* mbb : linear_order_blocks) {
for (auto& instr_ptr : mbb->getInstructions()) {
std::set<unsigned> use, def;
getInstrUseDef(instr_ptr.get(), use, def);
vregs_from_instr_scan.insert(use.begin(), use.end());
vregs_from_instr_scan.insert(def.begin(), def.end());
}
}
std::cerr << " [Live-Debug] VReg Consistency Check:\n";
std::cerr << " VRegs found by Liveness Analysis: " << vregs_from_liveness.size() << "\n";
std::cerr << " VRegs found by getInstrUseDef Scan: " << vregs_from_instr_scan.size() << "\n";
// 修正:将 std.set 修改为 std::set
std::set<unsigned> diff;
std::set_difference(vregs_from_liveness.begin(), vregs_from_liveness.end(),
vregs_from_instr_scan.begin(), vregs_from_instr_scan.end(),
std::inserter(diff, diff.begin()));
if (!diff.empty()) {
std::cerr << " !!!!!! [Live-Debug] DISCREPANCY DETECTED !!!!!!\n";
std::cerr << " The following vregs were found by liveness but NOT by getInstrUseDef scan:\n";
std::cerr << " " << vregSetToString(diff) << "\n";
} else {
std::cerr << " [Live-Debug] VReg sets are consistent.\n";
}
}
// ======================================================
}
bool RISCv64LinearScan::linearScan() {
// ================== 终极保底策略 (新逻辑) ==================
// 当此标志位为true时我们进入最暴力的溢出模式。
if (conservative_spill_mode) {
if (DEBUG) std::cerr << "[LSRA-Scan-Panic] In Conservative Mode. Spilling all unhandled vregs.\n";
// 1. 清空溢出列表,准备重新计算
spilled_vregs.clear();
// 2. 遍历所有计算出的活性区间
for (auto& pair : live_intervals) {
// 3. 如果一个vreg不是ABI规定的寄存器就必须溢出
if (abi_vreg_map.find(pair.first) == abi_vreg_map.end()) {
spilled_vregs.insert(pair.first);
}
}
// 4. 只要有任何vreg被标记为溢出就返回true以触发最终的rewriteProgram。
// 下一轮迭代时由于所有vreg都已被重写将不再有新的溢出保证收敛。
return !spilled_vregs.empty();
}
// ==========================================================
// ================== 常规线性扫描逻辑 (您已有的代码) ==================
// 只有在非保守模式下才会执行以下代码
if (DEBUG) std::cerr << "[LSRA-Scan] Starting main linear scan algorithm.\n";
active.clear();
spilled_vregs.clear();
vreg_to_preg_map.clear();
std::set<PhysicalReg> free_caller_int_regs, free_callee_int_regs;
std::set<PhysicalReg> free_caller_fp_regs, free_callee_fp_regs;
for (auto preg : allocable_int_regs) {
if (isCalleeSaved(preg)) free_callee_int_regs.insert(preg); else free_caller_int_regs.insert(preg);
}
for (auto preg : allocable_fp_regs) {
if (isCalleeSaved(preg)) free_callee_fp_regs.insert(preg); else free_caller_fp_regs.insert(preg);
}
if (DEEPDEBUG) {
std::cerr << " [Scan] Initial free regs:\n";
std::cerr << " Caller-Saved Int: " << pregSetToString(free_caller_int_regs) << "\n";
std::cerr << " Callee-Saved Int: " << pregSetToString(free_callee_int_regs) << "\n";
}
vreg_to_preg_map.insert(abi_vreg_map.begin(), abi_vreg_map.end());
std::vector<LiveInterval*> normal_unhandled;
for(LiveInterval* interval : unhandled) {
if(abi_vreg_map.count(interval->vreg)) {
active.push_back(interval);
PhysicalReg preg = abi_vreg_map.at(interval->vreg);
if (isFPVReg(interval->vreg)) {
if(isCalleeSaved(preg)) free_callee_fp_regs.erase(preg); else free_caller_fp_regs.erase(preg);
} else {
if(isCalleeSaved(preg)) free_callee_int_regs.erase(preg); else free_caller_int_regs.erase(preg);
}
} else {
normal_unhandled.push_back(interval);
}
}
unhandled = normal_unhandled;
std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->end < b->end; });
for (LiveInterval* current : unhandled) {
if (DEEPDEBUG) std::cerr << "\n [Scan] Processing interval %v" << current->vreg << " [" << current->start << ", " << current->end << "]\n";
std::vector<LiveInterval*> new_active;
for (LiveInterval* active_interval : active) {
if (active_interval->end < current->start) {
PhysicalReg preg = vreg_to_preg_map.at(active_interval->vreg);
if (DEEPDEBUG) std::cerr << " [Scan] Expiring interval %v" << active_interval->vreg << ", freeing " << pregToString(preg) << "\n";
if (isFPVReg(active_interval->vreg)) {
if(isCalleeSaved(preg)) free_callee_fp_regs.insert(preg); else free_caller_fp_regs.insert(preg);
} else {
if(isCalleeSaved(preg)) free_callee_int_regs.insert(preg); else free_caller_int_regs.insert(preg);
}
} else {
new_active.push_back(active_interval);
}
}
active = new_active;
bool is_fp = isFPVReg(current->vreg);
auto& free_caller = is_fp ? free_caller_fp_regs : free_caller_int_regs;
auto& free_callee = is_fp ? free_callee_fp_regs : free_callee_int_regs;
PhysicalReg allocated_preg = PhysicalReg::INVALID;
if (current->crosses_call) {
if (!free_callee.empty()) {
allocated_preg = *free_callee.begin();
free_callee.erase(allocated_preg);
}
} else {
if (!free_caller.empty()) {
allocated_preg = *free_caller.begin();
free_caller.erase(allocated_preg);
} else if (!free_callee.empty()) {
allocated_preg = *free_callee.begin();
free_callee.erase(allocated_preg);
}
}
if (allocated_preg != PhysicalReg::INVALID) {
if (DEEPDEBUG) std::cerr << " [Scan] Allocated " << pregToString(allocated_preg) << " to %v" << current->vreg << "\n";
vreg_to_preg_map[current->vreg] = allocated_preg;
active.push_back(current);
std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->end < b->end; });
} else {
if (DEEPDEBUG) std::cerr << " [Scan] No free registers for %v" << current->vreg << ". Spilling...\n";
spillAtInterval(current);
}
}
return !spilled_vregs.empty();
}
void RISCv64LinearScan::spillAtInterval(LiveInterval* current) {
// 保持您的原始逻辑
LiveInterval* spill_candidate = nullptr;
if (!active.empty()) {
spill_candidate = active.back();
}
if (DEEPERDEBUG) {
std::cerr << " [Spill-Debug] Spill decision for current=%v" << current->vreg << "[" << current->start << "," << current->end << "]\n";
std::cerr << " [Spill-Debug] Active intervals (sorted by end point):\n";
for (const auto* i : active) {
std::cerr << " %v" << i->vreg << "[" << i->start << "," << i->end << "] in " << pregToString(vreg_to_preg_map[i->vreg]) << "\n";
}
if(spill_candidate) {
std::cerr << " [Spill-Debug] Candidate is %v" << spill_candidate->vreg << ". Its end is " << spill_candidate->end << ", current's end is " << current->end << "\n";
} else {
std::cerr << " [Spill-Debug] No active candidate.\n";
}
}
if (spill_candidate && spill_candidate->end > current->end) {
if (DEEPDEBUG) std::cerr << " [Spill] Decision: Spilling active %v" << spill_candidate->vreg << ".\n";
PhysicalReg preg = vreg_to_preg_map.at(spill_candidate->vreg);
vreg_to_preg_map.erase(spill_candidate->vreg); // 确保移除旧映射
vreg_to_preg_map[current->vreg] = preg;
active.pop_back();
active.push_back(current);
std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->end < b->end; });
spilled_vregs.insert(spill_candidate->vreg);
} else {
if (DEEPDEBUG) std::cerr << " [Spill] Decision: Spilling current %v" << current->vreg << ".\n";
spilled_vregs.insert(current->vreg);
}
}
void RISCv64LinearScan::rewriteProgram() {
if (DEBUG) {
std::cerr << "[LSRA-Rewrite] Starting program rewrite. Spilled vregs: " << vregSetToString(spilled_vregs) << "\n";
}
StackFrameInfo& frame_info = MFunc->getFrameInfo();
int spill_current_offset = frame_info.locals_end_offset - frame_info.spill_size;
for (unsigned vreg : spilled_vregs) {
// 保持您的原始逻辑
if (frame_info.spill_offsets.count(vreg)) continue;
Type* type = vreg_type_map.count(vreg) ? vreg_type_map.at(vreg) : Type::getIntType();
int size = isFPVReg(vreg) ? 4 : (type->isPointer() ? 8 : 4);
spill_current_offset -= size;
spill_current_offset = (spill_current_offset & ~7);
frame_info.spill_offsets[vreg] = spill_current_offset;
if (DEEPDEBUG) std::cerr << " [Rewrite] Assigned new stack offset " << frame_info.spill_offsets.at(vreg) << " to spilled %v" << vreg << "\n";
}
frame_info.spill_size = -(spill_current_offset - frame_info.locals_end_offset);
for (auto& mbb : MFunc->getBlocks()) {
auto& instrs = mbb->getInstructions();
std::vector<std::unique_ptr<MachineInstr>> new_instrs;
if (DEEPERDEBUG) std::cerr << " [Rewrite] Processing block " << mbb->getName() << "\n";
for (auto it = instrs.begin(); it != instrs.end(); ++it) {
auto& instr = *it;
std::set<unsigned> use_vregs, def_vregs;
getInstrUseDef(instr.get(), use_vregs, def_vregs);
if (conservative_spill_mode) {
// ================== 紧急模式重写逻辑 ==================
// 直接使用物理寄存器 t4 (SPILL_TEMP_REG) 进行加载/存储
// 为调试日志准备一个指令打印机
auto printer = DEEPERDEBUG ? std::make_unique<RISCv64AsmPrinter>(MFunc) : nullptr;
auto original_instr_str_for_log = DEEPERDEBUG ? printer->formatInstr(instr.get()) : "";
bool modified = false;
for (unsigned old_vreg : use_vregs) {
if (spilled_vregs.count(old_vreg)) {
modified = true;
Type* type = vreg_type_map.at(old_vreg);
RVOpcodes load_op = isFPVReg(old_vreg) ? RVOpcodes::FLW : (type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW);
auto load = std::make_unique<MachineInstr>(load_op);
// 直接加载到保留的物理寄存器
load->addOperand(std::make_unique<RegOperand>(SPILL_TEMP_REG));
load->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(old_vreg))));
if (DEEPERDEBUG) {
std::cerr << " [Rewrite-Panic] Inserting LOAD for use of %v" << old_vreg
<< " into " << pregToString(SPILL_TEMP_REG)
<< " before: " << original_instr_str_for_log << "\n";
}
new_instrs.push_back(std::move(load));
// 替换指令中的操作数
instr->replaceVRegWithPReg(old_vreg, SPILL_TEMP_REG);
}
}
// 在处理 def 之前,先替换定义自身的 vreg
for (unsigned old_vreg : def_vregs) {
if (spilled_vregs.count(old_vreg)) {
modified = true;
instr->replaceVRegWithPReg(old_vreg, SPILL_TEMP_REG);
}
}
// 将原始指令(可能已被修改)放入新列表
new_instrs.push_back(std::move(instr));
if (DEEPERDEBUG && modified) {
std::cerr << " [Rewrite-Panic] Original: " << original_instr_str_for_log
<< " -> Rewritten: " << printer->formatInstr(new_instrs.back().get()) << "\n";
}
for (unsigned old_vreg : def_vregs) {
if (spilled_vregs.count(old_vreg)) {
// 指令本身已经被修改为定义到 SPILL_TEMP_REG现在从它存回内存
Type* type = vreg_type_map.at(old_vreg);
RVOpcodes store_op = isFPVReg(old_vreg) ? RVOpcodes::FSW : (type->isPointer() ? RVOpcodes::SD : RVOpcodes::SW);
auto store = std::make_unique<MachineInstr>(store_op);
store->addOperand(std::make_unique<RegOperand>(SPILL_TEMP_REG));
store->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(old_vreg))));
if (DEEPERDEBUG) {
std::cerr << " [Rewrite-Panic] Inserting STORE for def of %v" << old_vreg
<< " from " << pregToString(SPILL_TEMP_REG) << " after original instr.\n";
}
new_instrs.push_back(std::move(store));
}
}
} else {
// ================== 常规模式重写逻辑 (您的原始代码) ==================
std::map<unsigned, unsigned> use_remap, def_remap;
for (unsigned old_vreg : use_vregs) {
if (spilled_vregs.count(old_vreg) && use_remap.find(old_vreg) == use_remap.end()) {
Type* type = vreg_type_map.at(old_vreg);
unsigned new_temp_vreg = ISel->getNewVReg(type);
use_remap[old_vreg] = new_temp_vreg;
RVOpcodes load_op = isFPVReg(old_vreg) ? RVOpcodes::FLW : (type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW);
auto load = std::make_unique<MachineInstr>(load_op);
load->addOperand(std::make_unique<RegOperand>(new_temp_vreg));
load->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(old_vreg))));
if (DEEPERDEBUG) {
RISCv64AsmPrinter printer(MFunc);
std::cerr << " [Rewrite] Inserting LOAD for use of %v" << old_vreg << " into new %v" << new_temp_vreg << " before: " << printer.formatInstr(instr.get()) << "\n";
}
new_instrs.push_back(std::move(load));
}
}
for (unsigned old_vreg : def_vregs) {
if (spilled_vregs.count(old_vreg) && def_remap.find(old_vreg) == def_remap.end()) {
Type* type = vreg_type_map.at(old_vreg);
unsigned new_temp_vreg = ISel->getNewVReg(type);
def_remap[old_vreg] = new_temp_vreg;
}
}
auto original_instr_str_for_log = DEEPERDEBUG ? RISCv64AsmPrinter(MFunc).formatInstr(instr.get()) : "";
instr->remapVRegs(use_remap, def_remap);
new_instrs.push_back(std::move(instr));
if (DEEPERDEBUG && (!use_remap.empty() || !def_remap.empty())) std::cerr << " [Rewrite] Original: " << original_instr_str_for_log << " -> Rewritten: " << RISCv64AsmPrinter(MFunc).formatInstr(new_instrs.back().get()) << "\n";
for(const auto& pair : def_remap) {
unsigned old_vreg = pair.first;
unsigned new_temp_vreg = pair.second;
Type* type = vreg_type_map.at(old_vreg);
RVOpcodes store_op = isFPVReg(old_vreg) ? RVOpcodes::FSW : (type->isPointer() ? RVOpcodes::SD : RVOpcodes::SW);
auto store = std::make_unique<MachineInstr>(store_op);
store->addOperand(std::make_unique<RegOperand>(new_temp_vreg));
store->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(old_vreg))));
if (DEEPERDEBUG) std::cerr << " [Rewrite] Inserting STORE for def of %v" << old_vreg << " from new %v" << new_temp_vreg << " after original instr.\n";
new_instrs.push_back(std::move(store));
}
}
}
instrs = std::move(new_instrs);
}
}
void RISCv64LinearScan::applyAllocation() {
if (DEBUG) std::cerr << "[LSRA-Apply] Applying final vreg->preg mapping.\n";
for (auto& mbb : MFunc->getBlocks()) {
for (auto& instr_ptr : mbb->getInstructions()) {
for (auto& op_ptr : instr_ptr->getOperands()) {
if (op_ptr->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand*>(op_ptr.get());
if (reg_op->isVirtual()) {
unsigned vreg = reg_op->getVRegNum();
if (vreg_to_preg_map.count(vreg)) {
reg_op->setPReg(vreg_to_preg_map.at(vreg));
} else {
std::cerr << "ERROR: Uncolored virtual register %v" << vreg << " found during applyAllocation! in func " << MFunc->getName() << "\n";
// Forcing an error is better than silent failure.
// reg_op->setPReg(PhysicalReg::T5);
}
}
} else if (op_ptr->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand*>(op_ptr.get());
auto reg_op = mem_op->getBase();
if (reg_op->isVirtual()) {
unsigned vreg = reg_op->getVRegNum();
if (vreg_to_preg_map.count(vreg)) {
reg_op->setPReg(vreg_to_preg_map.at(vreg));
} else {
std::cerr << "ERROR: Uncolored virtual register %v" << vreg << " in memory operand! in func " << MFunc->getName() << "\n";
// reg_op->setPReg(PhysicalReg::T5);
}
}
}
}
}
}
}
// void getInstrUseDef(const MachineInstr* instr, std::set<unsigned>& use, std::set<unsigned>& def) {
// auto opcode = instr->getOpcode();
// const auto& operands = instr->getOperands();
// auto get_vreg_id_if_virtual = [&](const MachineOperand* op, std::set<unsigned>& s) {
// if (op->getKind() == MachineOperand::KIND_REG) {
// auto reg_op = static_cast<const RegOperand*>(op);
// if (reg_op->isVirtual()) s.insert(reg_op->getVRegNum());
// } else if (op->getKind() == MachineOperand::KIND_MEM) {
// auto mem_op = static_cast<const MemOperand*>(op);
// auto reg_op = mem_op->getBase();
// if (reg_op->isVirtual()) s.insert(reg_op->getVRegNum());
// }
// };
// if (op_info.count(opcode)) {
// const auto& info = op_info.at(opcode);
// for (int idx : info.first) if (idx < operands.size()) get_vreg_id_if_virtual(operands[idx].get(), def);
// for (int idx : info.second) if (idx < operands.size()) get_vreg_id_if_virtual(operands[idx].get(), use);
// for (const auto& op : operands) if (op->getKind() == MachineOperand::KIND_MEM) get_vreg_id_if_virtual(op.get(), use);
// } else if (opcode == RVOpcodes::CALL) {
// if (!operands.empty() && operands[0]->getKind() == MachineOperand::KIND_REG) get_vreg_id_if_virtual(operands[0].get(), def);
// for (size_t i = 1; i < operands.size(); ++i) if (operands[i]->getKind() == MachineOperand::KIND_REG) get_vreg_id_if_virtual(operands[i].get(), use);
// }
// }
bool RISCv64LinearScan::isFPVReg(unsigned vreg) const {
return vreg_type_map.count(vreg) && vreg_type_map.at(vreg)->isFloat();
}
void RISCv64LinearScan::collectUsedCalleeSavedRegs() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
frame_info.used_callee_saved_regs.clear();
const auto& callee_saved_int = getCalleeSavedIntRegs();
const auto& callee_saved_fp = getCalleeSavedFpRegs();
std::set<PhysicalReg> callee_saved_set(callee_saved_int.begin(), callee_saved_int.end());
callee_saved_set.insert(callee_saved_fp.begin(), callee_saved_fp.end());
callee_saved_set.insert(PhysicalReg::S0);
for(const auto& pair : vreg_to_preg_map) {
PhysicalReg preg = pair.second;
if(callee_saved_set.count(preg)) {
frame_info.used_callee_saved_regs.insert(preg);
}
}
}
} // namespace sysy