deploy-20250820-3 #1
@@ -1,13 +1,14 @@
|
|||||||
#include "RISCv64Backend.h"
|
#include "RISCv64Backend.h"
|
||||||
#include "RISCv64ISel.h"
|
#include "RISCv64ISel.h"
|
||||||
#include "RISCv64RegAlloc.h"
|
#include "RISCv64RegAlloc.h"
|
||||||
#include "RISCv64LinearScan.h" // <--- 新增此行
|
#include "RISCv64LinearScan.h"
|
||||||
|
#include "RISCv64BasicBlockAlloc.h"
|
||||||
#include "RISCv64AsmPrinter.h"
|
#include "RISCv64AsmPrinter.h"
|
||||||
#include "RISCv64Passes.h"
|
#include "RISCv64Passes.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <future> // <--- 新增此行
|
#include <future>
|
||||||
#include <chrono> // <--- 新增此行
|
#include <chrono>
|
||||||
#include <iostream> // <--- 新增此行,用于打印超时警告
|
#include <iostream>
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
// 顶层入口
|
// 顶层入口
|
||||||
@@ -196,139 +197,7 @@ std::string RISCv64CodeGen::module_gen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string RISCv64CodeGen::function_gen(Function* func) {
|
std::string RISCv64CodeGen::function_gen(Function* func) {
|
||||||
if (DEBUG) {
|
// === 完整的后端处理流水线 ===
|
||||||
// === 完整的后端处理流水线 ===
|
|
||||||
|
|
||||||
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
|
|
||||||
DEBUG = 0;
|
|
||||||
DEEPDEBUG = 0;
|
|
||||||
|
|
||||||
RISCv64ISel isel;
|
|
||||||
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
|
|
||||||
|
|
||||||
// 第一次调试打印输出
|
|
||||||
std::stringstream ss_after_isel;
|
|
||||||
RISCv64AsmPrinter printer_isel(mfunc.get());
|
|
||||||
printer_isel.run(ss_after_isel, true);
|
|
||||||
// DEBUG = 1;
|
|
||||||
// DEEPDEBUG = 1;
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
|
|
||||||
<< ss_after_isel.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
|
|
||||||
// 这个Pass必须在寄存器分配之前运行
|
|
||||||
EliminateFrameIndicesPass efi_pass;
|
|
||||||
efi_pass.runOnMachineFunction(mfunc.get());
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cerr << "====== stack info after eliminate frame indices ======\n";
|
|
||||||
mfunc->dumpStackFrameInfo(std::cerr);
|
|
||||||
std::stringstream ss_after_eli;
|
|
||||||
printer_isel.run(ss_after_eli, true);
|
|
||||||
std::cerr << "====== LLIR after eliminate frame indices ======\n"
|
|
||||||
<< ss_after_eli.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 阶段 2: 除法强度削弱优化 (Division Strength Reduction)
|
|
||||||
DivStrengthReduction div_strength_reduction;
|
|
||||||
div_strength_reduction.runOnMachineFunction(mfunc.get());
|
|
||||||
|
|
||||||
// // 阶段 2.1: 指令调度 (Instruction Scheduling)
|
|
||||||
// PreRA_Scheduler scheduler;
|
|
||||||
// scheduler.runOnMachineFunction(mfunc.get());
|
|
||||||
|
|
||||||
// 阶段 3: 物理寄存器分配 (Register Allocation)
|
|
||||||
|
|
||||||
DEBUG = 1;
|
|
||||||
// DEEPERDEBUG = 1;
|
|
||||||
|
|
||||||
// 阶段 3: 物理寄存器分配 (带超时回退机制)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* [临时修改]
|
|
||||||
* 为了优先测试线性扫描分配器,暂时注释掉图着色分配器及其超时逻辑。
|
|
||||||
* 原始逻辑是:优先使用图着色,超时(20s)后回退到线性扫描。
|
|
||||||
* 在线性扫描分配器测试稳定后,可以恢复此处的代码。
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
// 首先尝试图着色分配器
|
|
||||||
if (DEBUG) std::cerr << "Attempting Register Allocation with Graph Coloring...\n";
|
|
||||||
RISCv64RegAlloc gc_alloc(mfunc.get());
|
|
||||||
|
|
||||||
// 异步执行图着色分配
|
|
||||||
auto future = std::async(std::launch::async, [&gc_alloc]{
|
|
||||||
gc_alloc.run();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 等待最多20秒
|
|
||||||
auto status = future.wait_for(std::chrono::seconds(20));
|
|
||||||
|
|
||||||
if (status == std::future_status::timeout) {
|
|
||||||
// 超时,切换到线性扫描分配器
|
|
||||||
std::cerr << "Warning: Graph coloring register allocation timed out for function '"
|
|
||||||
<< func->getName()
|
|
||||||
<< "'. Switching to Linear Scan allocator."
|
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
// 注意:由于无法安全地停止gc_alloc线程,我们只能放弃它的结果。
|
|
||||||
// 在此项目中,我们假设超时后原mfunc状态未被严重破坏,
|
|
||||||
// 或者线性扫描会基于isel后的状态重新开始。
|
|
||||||
// 为了安全,我们应该用一个新的mfunc或者重置mfunc状态,
|
|
||||||
// 但在这里我们简化处理,直接在同一个mfunc上运行线性扫描。
|
|
||||||
|
|
||||||
RISCv64LinearScan ls_alloc(mfunc.get());
|
|
||||||
ls_alloc.run();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// 图着色成功完成
|
|
||||||
if (DEBUG) std::cerr << "Graph Coloring allocation completed successfully.\n";
|
|
||||||
// future.get()会重新抛出在线程中发生的任何异常
|
|
||||||
future.get();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// [临时修改] 直接调用线性扫描分配器进行测试
|
|
||||||
std::cerr << "Info: Directly testing Register Allocation with Linear Scan...\n";
|
|
||||||
RISCv64LinearScan ls_alloc(mfunc.get());
|
|
||||||
ls_alloc.run();
|
|
||||||
|
|
||||||
// 阶段 3.1: 处理被调用者保存寄存器
|
|
||||||
CalleeSavedHandler callee_handler;
|
|
||||||
callee_handler.runOnMachineFunction(mfunc.get());
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cerr << "====== stack info after callee handler ======\n";
|
|
||||||
mfunc->dumpStackFrameInfo(std::cerr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// // 阶段 4: 窥孔优化 (Peephole Optimization)
|
|
||||||
// PeepholeOptimizer peephole;
|
|
||||||
// peephole.runOnMachineFunction(mfunc.get());
|
|
||||||
|
|
||||||
// 阶段 5: 局部指令调度 (Local Scheduling)
|
|
||||||
PostRA_Scheduler local_scheduler;
|
|
||||||
local_scheduler.runOnMachineFunction(mfunc.get());
|
|
||||||
|
|
||||||
// 阶段 3.2: 插入序言和尾声
|
|
||||||
PrologueEpilogueInsertionPass pei_pass;
|
|
||||||
pei_pass.runOnMachineFunction(mfunc.get());
|
|
||||||
|
|
||||||
DEBUG = 0;
|
|
||||||
DEEPDEBUG = 0;
|
|
||||||
// 阶段 3.3: 大立即数合法化
|
|
||||||
LegalizeImmediatesPass legalizer;
|
|
||||||
legalizer.runOnMachineFunction(mfunc.get());
|
|
||||||
|
|
||||||
// 阶段 6: 代码发射 (Code Emission)
|
|
||||||
std::stringstream ss;
|
|
||||||
RISCv64AsmPrinter printer(mfunc.get());
|
|
||||||
printer.run(ss);
|
|
||||||
|
|
||||||
return ss.str();
|
|
||||||
} else {
|
|
||||||
// === 完整的后端处理流水线 ===
|
|
||||||
|
|
||||||
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
|
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
|
||||||
RISCv64ISel isel;
|
RISCv64ISel isel;
|
||||||
@@ -367,12 +236,56 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
|
|||||||
// scheduler.runOnMachineFunction(mfunc.get());
|
// scheduler.runOnMachineFunction(mfunc.get());
|
||||||
|
|
||||||
// 阶段 3: 物理寄存器分配 (Register Allocation)
|
// 阶段 3: 物理寄存器分配 (Register Allocation)
|
||||||
// RISCv64RegAlloc reg_alloc(mfunc.get());
|
|
||||||
// reg_alloc.run();
|
// 首先尝试图着色分配器
|
||||||
// [临时修改] 直接调用线性扫描分配器进行测试
|
if (DEBUG) std::cerr << "Attempting Register Allocation with Graph Coloring...\n";
|
||||||
std::cerr << "Info: Directly testing Register Allocation with Linear Scan...\n";
|
RISCv64RegAlloc gc_alloc(mfunc.get());
|
||||||
RISCv64LinearScan ls_alloc(mfunc.get());
|
|
||||||
ls_alloc.run();
|
// 异步执行图着色分配
|
||||||
|
auto future = std::async(std::launch::async, [&gc_alloc]{
|
||||||
|
gc_alloc.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 等待最多20秒
|
||||||
|
auto status = future.wait_for(std::chrono::seconds(20));
|
||||||
|
|
||||||
|
if (status == std::future_status::timeout) {
|
||||||
|
// 超时,切换到线性扫描分配器
|
||||||
|
std::cerr << "Warning: Graph coloring register allocation timed out for function '"
|
||||||
|
<< func->getName()
|
||||||
|
<< "'. Switching to Linear Scan allocator."
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
// 注意:由于无法安全地停止gc_alloc线程,我们只能放弃它的结果。
|
||||||
|
// 在此项目中,我们假设超时后原mfunc状态未被严重破坏,
|
||||||
|
// 或者线性扫描会基于isel后的状态重新开始。
|
||||||
|
// 为了安全,我们应该用一个新的mfunc或者重置mfunc状态,
|
||||||
|
// 但在这里我们简化处理,直接在同一个mfunc上运行线性扫描。
|
||||||
|
|
||||||
|
RISCv64LinearScan ls_alloc(mfunc.get());
|
||||||
|
bool success = ls_alloc.run();
|
||||||
|
if (!success) {
|
||||||
|
// 如果线性扫描最终失败,则调用基本块分配器作为终极后备
|
||||||
|
std::cerr << "Info: Linear Scan failed. Switching to Basic Block Allocator as final fallback.\n";
|
||||||
|
|
||||||
|
// 注意:我们需要在一个“干净”的MachineFunction上运行。
|
||||||
|
// 最安全的方式是重新运行指令选择。
|
||||||
|
RISCv64ISel isel_fallback;
|
||||||
|
mfunc = isel_fallback.runOnFunction(func);
|
||||||
|
EliminateFrameIndicesPass efi_pass_fallback;
|
||||||
|
efi_pass_fallback.runOnMachineFunction(mfunc.get());
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cerr << "====== stack info after reg alloc ======\n";
|
||||||
|
}
|
||||||
|
RISCv64BasicBlockAlloc bb_alloc(mfunc.get());
|
||||||
|
bb_alloc.run();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 图着色成功完成
|
||||||
|
if (DEBUG) std::cerr << "Graph Coloring allocation completed successfully.\n";
|
||||||
|
// future.get()会重新抛出在线程中发生的任何异常
|
||||||
|
future.get();
|
||||||
|
}
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
std::cerr << "====== stack info after reg alloc ======\n";
|
std::cerr << "====== stack info after reg alloc ======\n";
|
||||||
@@ -410,7 +323,6 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
|
|||||||
printer.run(ss);
|
printer.run(ss);
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sysy
|
} // namespace sysy
|
||||||
@@ -643,31 +643,31 @@ void RISCv64LinearScan::applyAllocation() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void getInstrUseDef(const MachineInstr* instr, std::set<unsigned>& use, std::set<unsigned>& def) {
|
// void getInstrUseDef(const MachineInstr* instr, std::set<unsigned>& use, std::set<unsigned>& def) {
|
||||||
auto opcode = instr->getOpcode();
|
// auto opcode = instr->getOpcode();
|
||||||
const auto& operands = instr->getOperands();
|
// const auto& operands = instr->getOperands();
|
||||||
|
|
||||||
auto get_vreg_id_if_virtual = [&](const MachineOperand* op, std::set<unsigned>& s) {
|
// auto get_vreg_id_if_virtual = [&](const MachineOperand* op, std::set<unsigned>& s) {
|
||||||
if (op->getKind() == MachineOperand::KIND_REG) {
|
// if (op->getKind() == MachineOperand::KIND_REG) {
|
||||||
auto reg_op = static_cast<const RegOperand*>(op);
|
// auto reg_op = static_cast<const RegOperand*>(op);
|
||||||
if (reg_op->isVirtual()) s.insert(reg_op->getVRegNum());
|
// if (reg_op->isVirtual()) s.insert(reg_op->getVRegNum());
|
||||||
} else if (op->getKind() == MachineOperand::KIND_MEM) {
|
// } else if (op->getKind() == MachineOperand::KIND_MEM) {
|
||||||
auto mem_op = static_cast<const MemOperand*>(op);
|
// auto mem_op = static_cast<const MemOperand*>(op);
|
||||||
auto reg_op = mem_op->getBase();
|
// auto reg_op = mem_op->getBase();
|
||||||
if (reg_op->isVirtual()) s.insert(reg_op->getVRegNum());
|
// if (reg_op->isVirtual()) s.insert(reg_op->getVRegNum());
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
if (op_info.count(opcode)) {
|
// if (op_info.count(opcode)) {
|
||||||
const auto& info = op_info.at(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.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 (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);
|
// for (const auto& op : operands) if (op->getKind() == MachineOperand::KIND_MEM) get_vreg_id_if_virtual(op.get(), use);
|
||||||
} else if (opcode == RVOpcodes::CALL) {
|
// } else if (opcode == RVOpcodes::CALL) {
|
||||||
if (!operands.empty() && operands[0]->getKind() == MachineOperand::KIND_REG) get_vreg_id_if_virtual(operands[0].get(), def);
|
// 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);
|
// 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 {
|
bool RISCv64LinearScan::isFPVReg(unsigned vreg) const {
|
||||||
return vreg_type_map.count(vreg) && vreg_type_map.at(vreg)->isFloat();
|
return vreg_type_map.count(vreg) && vreg_type_map.at(vreg)->isFloat();
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 主入口: 迭代运行分配算法直到无溢出
|
// 主入口: 迭代运行分配算法直到无溢出
|
||||||
void RISCv64RegAlloc::run() {
|
bool RISCv64RegAlloc::run() {
|
||||||
if (DEBUG) std::cerr << "===== LLIR Before Running Graph Coloring Register Allocation " << MFunc->getName() << " =====\n";
|
if (DEBUG) std::cerr << "===== LLIR Before Running Graph Coloring Register Allocation " << MFunc->getName() << " =====\n";
|
||||||
std::stringstream ss_before_reg_alloc;
|
std::stringstream ss_before_reg_alloc;
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
@@ -108,6 +108,7 @@ void RISCv64RegAlloc::run() {
|
|||||||
MFunc->getFrameInfo().vreg_to_preg_map = this->color_map;
|
MFunc->getFrameInfo().vreg_to_preg_map = this->color_map;
|
||||||
collectUsedCalleeSavedRegs();
|
collectUsedCalleeSavedRegs();
|
||||||
if (DEBUG) std::cerr << "===== Finished Graph Coloring Register Allocation =====\n\n";
|
if (DEBUG) std::cerr << "===== Finished Graph Coloring Register Allocation =====\n\n";
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 单次分配的核心流程
|
// 单次分配的核心流程
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public:
|
|||||||
RISCv64RegAlloc(MachineFunction* mfunc);
|
RISCv64RegAlloc(MachineFunction* mfunc);
|
||||||
|
|
||||||
// 模块主入口
|
// 模块主入口
|
||||||
void run();
|
bool run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// 类型定义,与Python版本对应
|
// 类型定义,与Python版本对应
|
||||||
|
|||||||
Reference in New Issue
Block a user