[backend]强化了线性扫描逻辑
This commit is contained in:
@ -89,22 +89,27 @@ void RISCv64LinearScan::linearizeBlocks() {
|
||||
}
|
||||
}
|
||||
|
||||
// 步骤 1.2: 计算活跃区间
|
||||
// RISCv64LinearScan.cpp
|
||||
|
||||
void RISCv64LinearScan::computeLiveIntervals() {
|
||||
instr_numbering.clear();
|
||||
live_intervals.clear();
|
||||
unhandled.clear();
|
||||
|
||||
// a. 对所有指令进行线性编号
|
||||
// a. 对所有指令进行线性编号,并记录CALL指令的位置
|
||||
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; // 指令编号间隔为2,方便在溢出重写时插入指令
|
||||
}
|
||||
}
|
||||
|
||||
// b. (新逻辑) 遍历所有指令,记录每个vreg首次和末次出现的位置
|
||||
// b. 遍历所有指令,记录每个vreg首次和末次出现的位置
|
||||
std::map<unsigned, std::pair<int, int>> vreg_ranges; // vreg -> {first_instr_num, last_instr_num}
|
||||
|
||||
for (auto* mbb : linear_order_blocks) {
|
||||
@ -114,28 +119,31 @@ void RISCv64LinearScan::computeLiveIntervals() {
|
||||
std::set<unsigned> use, def;
|
||||
getInstrUseDef(instr, use, def);
|
||||
|
||||
// 合并use和def集合,获取本条指令涉及的所有vreg
|
||||
auto all_vregs = use;
|
||||
all_vregs.insert(def.begin(), def.end());
|
||||
|
||||
// 更新每个vreg的区间边界
|
||||
for (unsigned vreg : all_vregs) {
|
||||
if (vreg_ranges.find(vreg) == vreg_ranges.end()) {
|
||||
// 第一次见到这个vreg,记录首次和末次位置
|
||||
vreg_ranges[vreg] = {instr_num, instr_num};
|
||||
} else {
|
||||
// 更新末次位置
|
||||
vreg_ranges[vreg].second = std::max(vreg_ranges[vreg].second, instr_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// c. 根据记录的边界,创建LiveInterval对象
|
||||
// c. 根据记录的边界,创建LiveInterval对象,并检查是否跨越CALL
|
||||
for (auto const& [vreg, range] : vreg_ranges) {
|
||||
live_intervals.emplace(vreg, LiveInterval(vreg));
|
||||
live_intervals.at(vreg).start = range.first;
|
||||
live_intervals.at(vreg).end = range.second;
|
||||
auto& interval = live_intervals.at(vreg);
|
||||
interval.start = range.first;
|
||||
interval.end = range.second;
|
||||
|
||||
// 检查此区间是否跨越了任何CALL指令
|
||||
auto it = call_locations.lower_bound(interval.start);
|
||||
if (it != call_locations.end() && *it < interval.end) {
|
||||
interval.crosses_call = true;
|
||||
}
|
||||
}
|
||||
|
||||
// d. 将所有计算出的活跃区间放入 unhandled 列表
|
||||
@ -147,62 +155,106 @@ void RISCv64LinearScan::computeLiveIntervals() {
|
||||
});
|
||||
}
|
||||
|
||||
// 步骤 2: 线性扫描主算法
|
||||
// RISCv64LinearScan.cpp
|
||||
|
||||
// 在类的定义中添加一个辅助函数来判断寄存器类型
|
||||
bool isCalleeSaved(PhysicalReg preg) {
|
||||
if (preg >= PhysicalReg::S1 && preg <= PhysicalReg::S11) return true;
|
||||
if (preg == PhysicalReg::S0) return true; // s0 通常也作为被调用者保存
|
||||
// 浮点寄存器
|
||||
if (preg >= PhysicalReg::F8 && preg <= PhysicalReg::F9) return true;
|
||||
if (preg >= PhysicalReg::F18 && preg <= PhysicalReg::F27) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 线性扫描主算法
|
||||
bool RISCv64LinearScan::linearScan() {
|
||||
// 初始化/重置状态
|
||||
active.clear();
|
||||
spilled_vregs.clear();
|
||||
vreg_to_preg_map.clear();
|
||||
free_int_regs.clear();
|
||||
free_fp_regs.clear();
|
||||
free_int_regs.insert(allocable_int_regs.begin(), allocable_int_regs.end());
|
||||
free_fp_regs.insert(allocable_fp_regs.begin(), allocable_fp_regs.end());
|
||||
|
||||
// 1. 将ABI参数的vreg直接分配给其固定的物理寄存器
|
||||
// 将寄存器池分为调用者保存和被调用者保存两类
|
||||
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);
|
||||
}
|
||||
|
||||
// 预处理ABI参数寄存器
|
||||
vreg_to_preg_map.insert(abi_vreg_map.begin(), abi_vreg_map.end());
|
||||
|
||||
// 2. 从unhandled列表中移除这些ABI参数区间,并将其加入active列表
|
||||
std::vector<LiveInterval*> normal_unhandled;
|
||||
for(LiveInterval* interval : unhandled) {
|
||||
if(abi_vreg_map.count(interval->vreg)) {
|
||||
// 这是一个ABI参数区间,它已经被“预分配”
|
||||
active.push_back(interval);
|
||||
// 从空闲池中移除对应的物理寄存器
|
||||
PhysicalReg preg = abi_vreg_map.at(interval->vreg);
|
||||
if (isFPVReg(interval->vreg)) {
|
||||
free_fp_regs.erase(preg);
|
||||
if(isCalleeSaved(preg)) free_callee_fp_regs.erase(preg); else free_caller_fp_regs.erase(preg);
|
||||
} else {
|
||||
free_int_regs.erase(preg);
|
||||
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; // 更新unhandled列表,只包含普通区间
|
||||
|
||||
// 3. 对active列表(现在只包含ABI参数)按结束点排序
|
||||
std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){
|
||||
return a->end < b->end;
|
||||
});
|
||||
unhandled = normal_unhandled;
|
||||
std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->end < b->end; });
|
||||
|
||||
// 主循环
|
||||
for (LiveInterval* current : unhandled) {
|
||||
// a. 检查并释放 active 列表中已经结束的区间
|
||||
// a. 释放active列表中已结束的区间
|
||||
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 (isFPVReg(active_interval->vreg)) free_fp_regs.insert(preg);
|
||||
else free_int_regs.insert(preg);
|
||||
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;
|
||||
|
||||
// b. 尝试为当前区间分配寄存器
|
||||
chooseRegForInterval(current);
|
||||
// b. 约束化地为当前区间分配寄存器
|
||||
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) {
|
||||
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 {
|
||||
// c. 没有可用寄存器,需要溢出
|
||||
spillAtInterval(current);
|
||||
}
|
||||
}
|
||||
return !spilled_vregs.empty();
|
||||
}
|
||||
@ -228,33 +280,29 @@ void RISCv64LinearScan::chooseRegForInterval(LiveInterval* current) {
|
||||
}
|
||||
|
||||
void RISCv64LinearScan::spillAtInterval(LiveInterval* current) {
|
||||
// 启发式:比较当前区间和 active 列表中结束点最晚的区间
|
||||
LiveInterval* spill_candidate = active.back(); // active已按end排序,最后一个就是结束最晚的
|
||||
|
||||
if (spill_candidate->end > current->end) {
|
||||
// active中的区间结束得更晚,溢出它
|
||||
PhysicalReg preg = vreg_to_preg_map.at(spill_candidate->vreg);
|
||||
|
||||
// 将被溢出区间的物理寄存器分配给当前区间
|
||||
vreg_to_preg_map[current->vreg] = preg;
|
||||
|
||||
// 更新 active 列表
|
||||
active.pop_back(); // 移除被溢出的
|
||||
active.push_back(current); // 加入当前的
|
||||
std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){
|
||||
return a->end < b->end;
|
||||
});
|
||||
LiveInterval* spill_candidate = nullptr;
|
||||
// 启发式溢出:
|
||||
// 如果current需要callee-saved,则从active中找一个占用callee-saved且结束最晚的区间比较
|
||||
// 否则,找active中结束最晚的区间
|
||||
// 这里简化处理:总是找active中结束最晚的区间
|
||||
auto last_active = active.back();
|
||||
|
||||
if (last_active->end > current->end) {
|
||||
// 溢出active中的区间
|
||||
spill_candidate = last_active;
|
||||
PhysicalReg preg = vreg_to_preg_map.at(spill_candidate->vreg);
|
||||
vreg_to_preg_map[current->vreg] = preg; // 把换出的寄存器给current
|
||||
// 更新active列表
|
||||
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);
|
||||
if(DEBUG) std::cerr << " Spilling vreg" << spill_candidate->vreg << " to make room for vreg" << current->vreg << "\n";
|
||||
} else {
|
||||
// 当前区间结束得更晚,直接溢出当前区间
|
||||
// 溢出当前区间
|
||||
spilled_vregs.insert(current->vreg);
|
||||
if(DEBUG) std::cerr << " Spilling current vreg" << current->vreg << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 步骤 3: 重写程序,插入溢出代码
|
||||
void RISCv64LinearScan::rewriteProgram() {
|
||||
StackFrameInfo& frame_info = MFunc->getFrameInfo();
|
||||
@ -276,15 +324,20 @@ void RISCv64LinearScan::rewriteProgram() {
|
||||
|
||||
for (auto it = instrs.begin(); it != instrs.end(); ++it) {
|
||||
auto& instr = *it;
|
||||
std::set<unsigned> use, def;
|
||||
getInstrUseDef(instr.get(), use, def);
|
||||
std::set<unsigned> use_vregs, def_vregs;
|
||||
getInstrUseDef(instr.get(), use_vregs, def_vregs);
|
||||
|
||||
// 为每个溢出的 use 创建 load
|
||||
for (unsigned old_vreg : use) {
|
||||
if (spilled_vregs.count(old_vreg)) {
|
||||
// 建立溢出vreg到新临时vreg的映射
|
||||
std::map<unsigned, unsigned> use_remap;
|
||||
std::map<unsigned, unsigned> def_remap;
|
||||
|
||||
// 1. 为所有溢出的USE创建LOAD指令和映射
|
||||
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));
|
||||
@ -293,52 +346,74 @@ void RISCv64LinearScan::rewriteProgram() {
|
||||
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(old_vreg))
|
||||
));
|
||||
new_instrs.push_back(std::move(load));
|
||||
}
|
||||
}
|
||||
|
||||
// 替换原指令中的 use
|
||||
for(auto& op : instr->getOperands()) {
|
||||
if(op->getKind() == MachineOperand::KIND_REG) {
|
||||
auto reg_op = static_cast<RegOperand*>(op.get());
|
||||
if(reg_op->isVirtual() && reg_op->getVRegNum() == old_vreg) {
|
||||
reg_op->setVRegNum(new_temp_vreg);
|
||||
}
|
||||
} else if(op->getKind() == MachineOperand::KIND_MEM) {
|
||||
auto mem_op = static_cast<MemOperand*>(op.get());
|
||||
auto base_reg = mem_op->getBase();
|
||||
if(base_reg->isVirtual() && base_reg->getVRegNum() == old_vreg) {
|
||||
base_reg->setVRegNum(new_temp_vreg);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 2. 为所有溢出的DEF创建映射
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
new_instrs.push_back(std::move(instr));
|
||||
// 3. 基于角色精确地替换原指令中的操作数
|
||||
auto opcode = instr->getOpcode();
|
||||
auto& operands = instr->getOperands();
|
||||
|
||||
// 为每个溢出的 def 创建 store
|
||||
for (unsigned old_vreg : def) {
|
||||
if (spilled_vregs.count(old_vreg)) {
|
||||
Type* type = vreg_type_map.at(old_vreg);
|
||||
unsigned new_temp_vreg = ISel->getNewVReg(type);
|
||||
|
||||
// 替换原指令中的 def
|
||||
for(auto& op : new_instrs.back()->getOperands()) {
|
||||
if(op->getKind() == MachineOperand::KIND_REG) {
|
||||
auto reg_op = static_cast<RegOperand*>(op.get());
|
||||
if(reg_op->isVirtual() && reg_op->getVRegNum() == old_vreg) {
|
||||
reg_op->setVRegNum(new_temp_vreg);
|
||||
}
|
||||
auto replace_reg_op = [](RegOperand* reg_op, const std::map<unsigned, unsigned>& remap) {
|
||||
if (reg_op->isVirtual() && remap.count(reg_op->getVRegNum())) {
|
||||
reg_op->setVRegNum(remap.at(reg_op->getVRegNum()));
|
||||
}
|
||||
};
|
||||
|
||||
if (op_info.count(opcode)) {
|
||||
const auto& info = op_info.at(opcode);
|
||||
// 替换 Defs
|
||||
for (int idx : info.first) {
|
||||
if (idx < operands.size() && operands[idx]->getKind() == MachineOperand::KIND_REG) {
|
||||
replace_reg_op(static_cast<RegOperand*>(operands[idx].get()), def_remap);
|
||||
}
|
||||
}
|
||||
// 替换 Uses
|
||||
for (int idx : info.second) {
|
||||
if (idx < operands.size()) {
|
||||
if (operands[idx]->getKind() == MachineOperand::KIND_REG) {
|
||||
replace_reg_op(static_cast<RegOperand*>(operands[idx].get()), use_remap);
|
||||
} else if (operands[idx]->getKind() == MachineOperand::KIND_MEM) {
|
||||
replace_reg_op(static_cast<MemOperand*>(operands[idx].get())->getBase(), use_remap);
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
));
|
||||
new_instrs.push_back(std::move(store));
|
||||
}
|
||||
} else if (opcode == RVOpcodes::CALL) {
|
||||
// 特殊处理 CALL 指令
|
||||
if (!operands.empty() && operands[0]->getKind() == MachineOperand::KIND_REG) {
|
||||
replace_reg_op(static_cast<RegOperand*>(operands[0].get()), def_remap);
|
||||
}
|
||||
for (size_t i = 1; i < operands.size(); ++i) {
|
||||
if (operands[i]->getKind() == MachineOperand::KIND_REG) {
|
||||
replace_reg_op(static_cast<RegOperand*>(operands[i].get()), use_remap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 将修改后的指令放入新列表
|
||||
new_instrs.push_back(std::move(instr));
|
||||
|
||||
// 5. 为所有溢出的DEF创建STORE指令
|
||||
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))
|
||||
));
|
||||
new_instrs.push_back(std::move(store));
|
||||
}
|
||||
}
|
||||
instrs = std::move(new_instrs);
|
||||
@ -382,33 +457,12 @@ void RISCv64LinearScan::applyAllocation() {
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助函数: 获取指令的use/def集合 (仅虚拟寄存器)
|
||||
void RISCv64LinearScan::getInstrUseDef(const MachineInstr* instr, std::set<unsigned>& use, std::set<unsigned>& def) {
|
||||
// 这个函数与图着色版本中的 getInstrUseDef 逻辑完全相同,此处直接复用
|
||||
auto opcode = instr->getOpcode();
|
||||
const auto& operands = instr->getOperands();
|
||||
|
||||
static const std::map<RVOpcodes, std::pair<std::vector<int>, std::vector<int>>> op_info = {
|
||||
{RVOpcodes::ADD, {{0}, {1, 2}}}, {RVOpcodes::SUB, {{0}, {1, 2}}}, {RVOpcodes::MUL, {{0}, {1, 2}}},
|
||||
{RVOpcodes::DIV, {{0}, {1, 2}}}, {RVOpcodes::REM, {{0}, {1, 2}}}, {RVOpcodes::ADDW, {{0}, {1, 2}}},
|
||||
{RVOpcodes::SUBW, {{0}, {1, 2}}}, {RVOpcodes::MULW, {{0}, {1, 2}}}, {RVOpcodes::DIVW, {{0}, {1, 2}}},
|
||||
{RVOpcodes::REMW, {{0}, {1, 2}}}, {RVOpcodes::SLT, {{0}, {1, 2}}}, {RVOpcodes::SLTU, {{0}, {1, 2}}},
|
||||
{RVOpcodes::ADDI, {{0}, {1}}}, {RVOpcodes::ADDIW, {{0}, {1}}}, {RVOpcodes::XORI, {{0}, {1}}},
|
||||
{RVOpcodes::SLTI, {{0}, {1}}}, {RVOpcodes::SLTIU, {{0}, {1}}}, {RVOpcodes::LB, {{0}, {}}},
|
||||
{RVOpcodes::LH, {{0}, {}}}, {RVOpcodes::LW, {{0}, {}}}, {RVOpcodes::LD, {{0}, {}}},
|
||||
{RVOpcodes::LBU, {{0}, {}}}, {RVOpcodes::LHU, {{0}, {}}}, {RVOpcodes::LWU, {{0}, {}}},
|
||||
{RVOpcodes::FLW, {{0}, {}}}, {RVOpcodes::FLD, {{0}, {}}}, {RVOpcodes::SB, {{}, {0, 1}}},
|
||||
{RVOpcodes::SH, {{}, {0, 1}}}, {RVOpcodes::SW, {{}, {0, 1}}}, {RVOpcodes::SD, {{}, {0, 1}}},
|
||||
{RVOpcodes::FSW, {{}, {0, 1}}}, {RVOpcodes::FSD, {{}, {0, 1}}}, {RVOpcodes::BEQ, {{}, {0, 1}}},
|
||||
{RVOpcodes::BNE, {{}, {0, 1}}}, {RVOpcodes::BLT, {{}, {0, 1}}}, {RVOpcodes::BGE, {{}, {0, 1}}},
|
||||
{RVOpcodes::JALR, {{0}, {1}}}, {RVOpcodes::LI, {{0}, {}}}, {RVOpcodes::LA, {{0}, {}}},
|
||||
{RVOpcodes::MV, {{0}, {1}}}, {RVOpcodes::SEQZ, {{0}, {1}}}, {RVOpcodes::SNEZ, {{0}, {1}}},
|
||||
{RVOpcodes::RET, {{}, {}}}, {RVOpcodes::FADD_S, {{0}, {1, 2}}}, {RVOpcodes::FSUB_S, {{0}, {1, 2}}},
|
||||
{RVOpcodes::FMUL_S, {{0}, {1, 2}}}, {RVOpcodes::FDIV_S, {{0}, {1, 2}}}, {RVOpcodes::FEQ_S, {{0}, {1, 2}}},
|
||||
{RVOpcodes::FLT_S, {{0}, {1, 2}}}, {RVOpcodes::FLE_S, {{0}, {1, 2}}}, {RVOpcodes::FCVT_S_W, {{0}, {1}}},
|
||||
{RVOpcodes::FCVT_W_S, {{0}, {1}}}, {RVOpcodes::FMV_S, {{0}, {1}}}, {RVOpcodes::FMV_W_X, {{0}, {1}}},
|
||||
{RVOpcodes::FMV_X_W, {{0}, {1}}}, {RVOpcodes::FNEG_S, {{0}, {1}}}
|
||||
};
|
||||
// op_info 的定义已被移到函数外部的命名空间中
|
||||
|
||||
auto get_vreg_id_if_virtual = [&](const MachineOperand* op, std::set<unsigned>& s) {
|
||||
if (op->getKind() == MachineOperand::KIND_REG) {
|
||||
@ -425,9 +479,13 @@ void RISCv64LinearScan::getInstrUseDef(const MachineInstr* instr, std::set<unsig
|
||||
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);
|
||||
// MemOperand 的基址寄存器总是一个 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) {
|
||||
// CALL指令的特殊处理
|
||||
// 第一个操作数(如果有)是def(返回值)
|
||||
if (!operands.empty() && operands[0]->getKind() == MachineOperand::KIND_REG) get_vreg_id_if_virtual(operands[0].get(), def);
|
||||
// 后续的寄存器操作数是use(参数)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,6 +41,8 @@ enum class PhysicalReg {
|
||||
// 假设 vreg_counter 不会达到这么大的值
|
||||
PHYS_REG_START_ID = 1000000,
|
||||
PHYS_REG_END_ID = PHYS_REG_START_ID + 320, // 预留足够的空间
|
||||
|
||||
INVALID, ///< 无效寄存器标记
|
||||
};
|
||||
|
||||
// RISC-V 指令操作码枚举
|
||||
|
||||
@ -23,7 +23,8 @@ struct LiveInterval {
|
||||
unsigned vreg = 0;
|
||||
int start = -1;
|
||||
int end = -1;
|
||||
|
||||
bool crosses_call = false;
|
||||
|
||||
LiveInterval(unsigned vreg) : vreg(vreg) {}
|
||||
|
||||
// 用于排序,按起始点从小到大
|
||||
@ -76,6 +77,28 @@ private:
|
||||
const std::map<unsigned, Type*>& vreg_type_map;
|
||||
};
|
||||
|
||||
static const std::map<RVOpcodes, std::pair<std::vector<int>, std::vector<int>>> op_info = {
|
||||
{RVOpcodes::ADD, {{0}, {1, 2}}}, {RVOpcodes::SUB, {{0}, {1, 2}}}, {RVOpcodes::MUL, {{0}, {1, 2}}},
|
||||
{RVOpcodes::DIV, {{0}, {1, 2}}}, {RVOpcodes::REM, {{0}, {1, 2}}}, {RVOpcodes::ADDW, {{0}, {1, 2}}},
|
||||
{RVOpcodes::SUBW, {{0}, {1, 2}}}, {RVOpcodes::MULW, {{0}, {1, 2}}}, {RVOpcodes::DIVW, {{0}, {1, 2}}},
|
||||
{RVOpcodes::REMW, {{0}, {1, 2}}}, {RVOpcodes::SLT, {{0}, {1, 2}}}, {RVOpcodes::SLTU, {{0}, {1, 2}}},
|
||||
{RVOpcodes::ADDI, {{0}, {1}}}, {RVOpcodes::ADDIW, {{0}, {1}}}, {RVOpcodes::XORI, {{0}, {1}}},
|
||||
{RVOpcodes::SLTI, {{0}, {1}}}, {RVOpcodes::SLTIU, {{0}, {1}}}, {RVOpcodes::LB, {{0}, {}}},
|
||||
{RVOpcodes::LH, {{0}, {}}}, {RVOpcodes::LW, {{0}, {}}}, {RVOpcodes::LD, {{0}, {}}},
|
||||
{RVOpcodes::LBU, {{0}, {}}}, {RVOpcodes::LHU, {{0}, {}}}, {RVOpcodes::LWU, {{0}, {}}},
|
||||
{RVOpcodes::FLW, {{0}, {}}}, {RVOpcodes::FLD, {{0}, {}}}, {RVOpcodes::SB, {{}, {0, 1}}},
|
||||
{RVOpcodes::SH, {{}, {0, 1}}}, {RVOpcodes::SW, {{}, {0, 1}}}, {RVOpcodes::SD, {{}, {0, 1}}},
|
||||
{RVOpcodes::FSW, {{}, {0, 1}}}, {RVOpcodes::FSD, {{}, {0, 1}}}, {RVOpcodes::BEQ, {{}, {0, 1}}},
|
||||
{RVOpcodes::BNE, {{}, {0, 1}}}, {RVOpcodes::BLT, {{}, {0, 1}}}, {RVOpcodes::BGE, {{}, {0, 1}}},
|
||||
{RVOpcodes::JALR, {{0}, {1}}}, {RVOpcodes::LI, {{0}, {}}}, {RVOpcodes::LA, {{0}, {}}},
|
||||
{RVOpcodes::MV, {{0}, {1}}}, {RVOpcodes::SEQZ, {{0}, {1}}}, {RVOpcodes::SNEZ, {{0}, {1}}},
|
||||
{RVOpcodes::RET, {{}, {}}}, {RVOpcodes::FADD_S, {{0}, {1, 2}}}, {RVOpcodes::FSUB_S, {{0}, {1, 2}}},
|
||||
{RVOpcodes::FMUL_S, {{0}, {1, 2}}}, {RVOpcodes::FDIV_S, {{0}, {1, 2}}}, {RVOpcodes::FEQ_S, {{0}, {1, 2}}},
|
||||
{RVOpcodes::FLT_S, {{0}, {1, 2}}}, {RVOpcodes::FLE_S, {{0}, {1, 2}}}, {RVOpcodes::FCVT_S_W, {{0}, {1}}},
|
||||
{RVOpcodes::FCVT_W_S, {{0}, {1}}}, {RVOpcodes::FMV_S, {{0}, {1}}}, {RVOpcodes::FMV_W_X, {{0}, {1}}},
|
||||
{RVOpcodes::FMV_X_W, {{0}, {1}}}, {RVOpcodes::FNEG_S, {{0}, {1}}}
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
|
||||
#endif // RISCV64_LINEARSCAN_H
|
||||
Reference in New Issue
Block a user