[midend][backend]补全了符合RV64调用约定的寄存器着色规则
This commit is contained in:
@ -18,6 +18,7 @@ RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc) : MFunc(mfunc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RISCv64RegAlloc::run() {
|
void RISCv64RegAlloc::run() {
|
||||||
|
handleCallingConvention();
|
||||||
eliminateFrameIndices();
|
eliminateFrameIndices();
|
||||||
analyzeLiveness();
|
analyzeLiveness();
|
||||||
buildInterferenceGraph();
|
buildInterferenceGraph();
|
||||||
@ -25,16 +26,67 @@ void RISCv64RegAlloc::run() {
|
|||||||
rewriteFunction();
|
rewriteFunction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 处理调用约定,预先为函数参数分配物理寄存器。
|
||||||
|
*/
|
||||||
|
void RISCv64RegAlloc::handleCallingConvention() {
|
||||||
|
Function* F = MFunc->getFunc();
|
||||||
|
RISCv64ISel* isel = MFunc->getISel();
|
||||||
|
|
||||||
|
// 获取函数的Argument对象列表
|
||||||
|
if (F) {
|
||||||
|
auto& args = F->getArguments();
|
||||||
|
|
||||||
|
// RISC-V RV64G调用约定:前8个整型/指针参数通过 a0-a7 传递
|
||||||
|
int arg_idx = 0;
|
||||||
|
// 遍历 AllocaInst* 列表
|
||||||
|
for (Argument* arg : args) {
|
||||||
|
if (arg_idx >= 8) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 获取该 Argument 对象对应的虚拟寄存器
|
||||||
|
unsigned vreg = isel->getVReg(arg);
|
||||||
|
|
||||||
|
// 2. 根据参数索引,确定对应的物理寄存器 (a0, a1, ...)
|
||||||
|
auto preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + arg_idx);
|
||||||
|
|
||||||
|
// 3. 在 color_map 中,将 vreg "预着色" 为对应的物理寄存器
|
||||||
|
color_map[vreg] = preg;
|
||||||
|
|
||||||
|
arg_idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RISCv64RegAlloc::eliminateFrameIndices() {
|
void RISCv64RegAlloc::eliminateFrameIndices() {
|
||||||
StackFrameInfo& frame_info = MFunc->getFrameInfo();
|
StackFrameInfo& frame_info = MFunc->getFrameInfo();
|
||||||
// 初始偏移量,为保存ra和s0留出空间。可以根据你的函数序言调整。
|
// 初始偏移量,为保存ra和s0留出空间。
|
||||||
// 假设序言是 addi sp, sp, -stack_size; sd ra, stack_size-8(sp); sd s0, stack_size-16(sp);
|
// 假设序言是 addi sp, sp, -stack_size; sd ra, stack_size-8(sp); sd s0, stack_size-16(sp);
|
||||||
int current_offset = 16;
|
int current_offset = 16;
|
||||||
|
|
||||||
Function* F = MFunc->getFunc();
|
Function* F = MFunc->getFunc();
|
||||||
RISCv64ISel* isel = MFunc->getISel();
|
RISCv64ISel* isel = MFunc->getISel();
|
||||||
|
|
||||||
// --- MODIFICATION START: 动态计算栈帧大小 ---
|
// 在处理局部变量前,首先为栈参数计算偏移量。
|
||||||
|
if (F) {
|
||||||
|
int arg_idx = 0;
|
||||||
|
for (Argument* arg : F->getArguments()) {
|
||||||
|
// 我们只关心第8个索引及之后的参数(即第9个参数开始)
|
||||||
|
if (arg_idx >= 8) {
|
||||||
|
// 计算偏移量:第一个栈参数(idx=8)在0(s0),第二个(idx=9)在8(s0),以此类推。
|
||||||
|
int offset = (arg_idx - 8) * 8;
|
||||||
|
unsigned vreg = isel->getVReg(arg);
|
||||||
|
|
||||||
|
// 将这个vreg和它的栈偏移存入map。
|
||||||
|
// 我们可以复用alloca_offsets,因为它们都代表“vreg到栈偏移”的映射。
|
||||||
|
frame_info.alloca_offsets[vreg] = offset;
|
||||||
|
}
|
||||||
|
arg_idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理局部变量
|
||||||
// 遍历AllocaInst来计算局部变量所需的总空间
|
// 遍历AllocaInst来计算局部变量所需的总空间
|
||||||
for (auto& bb : F->getBasicBlocks()) {
|
for (auto& bb : F->getBasicBlocks()) {
|
||||||
for (auto& inst : bb->getInstructions()) {
|
for (auto& inst : bb->getInstructions()) {
|
||||||
@ -49,12 +101,12 @@ void RISCv64RegAlloc::eliminateFrameIndices() {
|
|||||||
|
|
||||||
current_offset += size;
|
current_offset += size;
|
||||||
unsigned alloca_vreg = isel->getVReg(alloca);
|
unsigned alloca_vreg = isel->getVReg(alloca);
|
||||||
|
// 局部变量使用相对于s0的负向偏移
|
||||||
frame_info.alloca_offsets[alloca_vreg] = -current_offset;
|
frame_info.alloca_offsets[alloca_vreg] = -current_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
frame_info.locals_size = current_offset;
|
frame_info.locals_size = current_offset;
|
||||||
// --- MODIFICATION END ---
|
|
||||||
|
|
||||||
// 遍历所有机器指令,将伪指令展开为真实指令
|
// 遍历所有机器指令,将伪指令展开为真实指令
|
||||||
for (auto& mbb : MFunc->getBlocks()) {
|
for (auto& mbb : MFunc->getBlocks()) {
|
||||||
@ -325,13 +377,17 @@ void RISCv64RegAlloc::buildInterferenceGraph() {
|
|||||||
void RISCv64RegAlloc::colorGraph() {
|
void RISCv64RegAlloc::colorGraph() {
|
||||||
std::vector<unsigned> sorted_vregs;
|
std::vector<unsigned> sorted_vregs;
|
||||||
for (auto const& [vreg, neighbors] : interference_graph) {
|
for (auto const& [vreg, neighbors] : interference_graph) {
|
||||||
|
if (color_map.find(vreg) == color_map.end()) {
|
||||||
sorted_vregs.push_back(vreg);
|
sorted_vregs.push_back(vreg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排序
|
||||||
std::sort(sorted_vregs.begin(), sorted_vregs.end(), [&](unsigned a, unsigned b) {
|
std::sort(sorted_vregs.begin(), sorted_vregs.end(), [&](unsigned a, unsigned b) {
|
||||||
return interference_graph[a].size() > interference_graph[b].size();
|
return interference_graph[a].size() > interference_graph[b].size();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 着色
|
||||||
for (unsigned vreg : sorted_vregs) {
|
for (unsigned vreg : sorted_vregs) {
|
||||||
std::set<PhysicalReg> used_colors;
|
std::set<PhysicalReg> used_colors;
|
||||||
for (unsigned neighbor : interference_graph.at(vreg)) {
|
for (unsigned neighbor : interference_graph.at(vreg)) {
|
||||||
|
|||||||
@ -34,6 +34,9 @@ private:
|
|||||||
// 辅助函数,获取指令的Use/Def集合
|
// 辅助函数,获取指令的Use/Def集合
|
||||||
void getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet& def);
|
void getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet& def);
|
||||||
|
|
||||||
|
// 辅助函数,处理调用约定
|
||||||
|
void handleCallingConvention();
|
||||||
|
|
||||||
MachineFunction* MFunc;
|
MachineFunction* MFunc;
|
||||||
|
|
||||||
// 活跃性分析结果
|
// 活跃性分析结果
|
||||||
|
|||||||
Reference in New Issue
Block a user