[backend]修复了多参数传递的错误
This commit is contained in:
@@ -23,7 +23,7 @@ EXECUTE_MODE=false
|
|||||||
CLEAN_MODE=false
|
CLEAN_MODE=false
|
||||||
SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒)
|
SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒)
|
||||||
GCC_TIMEOUT=10 # gcc 编译超时 (秒)
|
GCC_TIMEOUT=10 # gcc 编译超时 (秒)
|
||||||
EXEC_TIMEOUT=5 # qemu 自动化执行超时 (秒)
|
EXEC_TIMEOUT=600 # qemu 自动化执行超时 (秒)
|
||||||
MAX_OUTPUT_LINES=50 # 对比失败时显示的最大行数
|
MAX_OUTPUT_LINES=50 # 对比失败时显示的最大行数
|
||||||
SY_FILES=() # 存储用户提供的 .sy 文件列表
|
SY_FILES=() # 存储用户提供的 .sy 文件列表
|
||||||
PASSED_CASES=0
|
PASSED_CASES=0
|
||||||
|
|||||||
@@ -1,12 +1,27 @@
|
|||||||
#include "PrologueEpilogueInsertion.h"
|
#include "PrologueEpilogueInsertion.h"
|
||||||
#include "RISCv64ISel.h"
|
#include "RISCv64ISel.h"
|
||||||
#include "RISCv64RegAlloc.h" // 需要访问RegAlloc的结果
|
#include "RISCv64RegAlloc.h" // 需要访问RegAlloc的结果
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace sysy {
|
namespace sysy {
|
||||||
|
|
||||||
char PrologueEpilogueInsertionPass::ID = 0;
|
char PrologueEpilogueInsertionPass::ID = 0;
|
||||||
|
|
||||||
void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) {
|
void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc) {
|
||||||
|
for (auto& mbb : mfunc->getBlocks()) {
|
||||||
|
auto& instrs = mbb->getInstructions();
|
||||||
|
|
||||||
|
// 使用标准的 Erase-Remove Idiom 来删除满足条件的元素
|
||||||
|
instrs.erase(
|
||||||
|
std::remove_if(instrs.begin(), instrs.end(),
|
||||||
|
[](const std::unique_ptr<MachineInstr>& instr) {
|
||||||
|
return instr->getOpcode() == RVOpcodes::PSEUDO_KEEPALIVE;
|
||||||
|
}
|
||||||
|
),
|
||||||
|
instrs.end()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
StackFrameInfo& frame_info = mfunc->getFrameInfo();
|
||||||
Function* F = mfunc->getFunc();
|
Function* F = mfunc->getFunc();
|
||||||
RISCv64ISel* isel = mfunc->getISel();
|
RISCv64ISel* isel = mfunc->getISel();
|
||||||
@@ -64,54 +79,35 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
|||||||
set_fp->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
|
set_fp->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
|
||||||
prologue_instrs.push_back(std::move(set_fp));
|
prologue_instrs.push_back(std::move(set_fp));
|
||||||
|
|
||||||
// --- [正确逻辑] 在s0设置完毕后,使用物理寄存器加载栈参数 ---
|
// --- 在s0设置完毕后,使用物理寄存器加载栈参数 ---
|
||||||
if (F && isel) {
|
if (F && isel) {
|
||||||
// 定义暂存寄存器
|
|
||||||
const PhysicalReg INT_SCRATCH_REG = PhysicalReg::T5;
|
|
||||||
const PhysicalReg FP_SCRATCH_REG = PhysicalReg::F7;
|
|
||||||
|
|
||||||
int arg_idx = 0;
|
int arg_idx = 0;
|
||||||
for (Argument* arg : F->getArguments()) {
|
for (Argument* arg : F->getArguments()) {
|
||||||
if (arg_idx >= 8) {
|
if (arg_idx >= 8) {
|
||||||
unsigned vreg = isel->getVReg(arg);
|
unsigned vreg = isel->getVReg(arg);
|
||||||
|
|
||||||
// 确认RegAlloc已经为这个vreg计算了偏移量,并且分配了物理寄存器
|
|
||||||
if (frame_info.alloca_offsets.count(vreg) && vreg_to_preg_map.count(vreg)) {
|
if (frame_info.alloca_offsets.count(vreg) && vreg_to_preg_map.count(vreg)) {
|
||||||
int offset = frame_info.alloca_offsets.at(vreg);
|
int offset = frame_info.alloca_offsets.at(vreg);
|
||||||
PhysicalReg dest_preg = vreg_to_preg_map.at(vreg);
|
PhysicalReg dest_preg = vreg_to_preg_map.at(vreg);
|
||||||
Type* arg_type = arg->getType();
|
Type* arg_type = arg->getType();
|
||||||
|
|
||||||
// 根据类型执行不同的加载序列
|
|
||||||
if (arg_type->isFloat()) {
|
if (arg_type->isFloat()) {
|
||||||
// 1. flw ft7, offset(s0)
|
|
||||||
auto load_arg = std::make_unique<MachineInstr>(RVOpcodes::FLW);
|
auto load_arg = std::make_unique<MachineInstr>(RVOpcodes::FLW);
|
||||||
load_arg->addOperand(std::make_unique<RegOperand>(FP_SCRATCH_REG));
|
load_arg->addOperand(std::make_unique<RegOperand>(dest_preg));
|
||||||
load_arg->addOperand(std::make_unique<MemOperand>(
|
load_arg->addOperand(std::make_unique<MemOperand>(
|
||||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||||
std::make_unique<ImmOperand>(offset)
|
std::make_unique<ImmOperand>(offset)
|
||||||
));
|
));
|
||||||
prologue_instrs.push_back(std::move(load_arg));
|
prologue_instrs.push_back(std::move(load_arg));
|
||||||
// 2. fmv.s dest_preg, ft7
|
|
||||||
auto move_arg = std::make_unique<MachineInstr>(RVOpcodes::FMV_S);
|
|
||||||
move_arg->addOperand(std::make_unique<RegOperand>(dest_preg));
|
|
||||||
move_arg->addOperand(std::make_unique<RegOperand>(FP_SCRATCH_REG));
|
|
||||||
prologue_instrs.push_back(std::move(move_arg));
|
|
||||||
} else {
|
} else {
|
||||||
// 确定是加载32位(lw)还是64位(ld)
|
|
||||||
RVOpcodes load_op = arg_type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW;
|
RVOpcodes load_op = arg_type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW;
|
||||||
// 1. lw/ld t5, offset(s0)
|
|
||||||
auto load_arg = std::make_unique<MachineInstr>(load_op);
|
auto load_arg = std::make_unique<MachineInstr>(load_op);
|
||||||
load_arg->addOperand(std::make_unique<RegOperand>(INT_SCRATCH_REG));
|
load_arg->addOperand(std::make_unique<RegOperand>(dest_preg));
|
||||||
load_arg->addOperand(std::make_unique<MemOperand>(
|
load_arg->addOperand(std::make_unique<MemOperand>(
|
||||||
std::make_unique<RegOperand>(PhysicalReg::S0),
|
std::make_unique<RegOperand>(PhysicalReg::S0),
|
||||||
std::make_unique<ImmOperand>(offset)
|
std::make_unique<ImmOperand>(offset)
|
||||||
));
|
));
|
||||||
prologue_instrs.push_back(std::move(load_arg));
|
prologue_instrs.push_back(std::move(load_arg));
|
||||||
// 2. mv dest_preg, t5
|
|
||||||
auto move_arg = std::make_unique<MachineInstr>(RVOpcodes::MV);
|
|
||||||
move_arg->addOperand(std::make_unique<RegOperand>(dest_preg));
|
|
||||||
move_arg->addOperand(std::make_unique<RegOperand>(INT_SCRATCH_REG));
|
|
||||||
prologue_instrs.push_back(std::move(move_arg));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,6 +144,9 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
|
|||||||
case RVOpcodes::FRAME_STORE_F:
|
case RVOpcodes::FRAME_STORE_F:
|
||||||
if (!debug) throw std::runtime_error("FRAME_STORE_F not eliminated before AsmPrinter");
|
if (!debug) throw std::runtime_error("FRAME_STORE_F not eliminated before AsmPrinter");
|
||||||
*OS << "frame_store_f "; break;
|
*OS << "frame_store_f "; break;
|
||||||
|
case RVOpcodes::PSEUDO_KEEPALIVE:
|
||||||
|
if (!debug) throw std::runtime_error("PSEUDO_KEEPALIVE not eliminated before AsmPrinter");
|
||||||
|
*OS << "keepalive "; break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unknown opcode in AsmPrinter");
|
throw std::runtime_error("Unknown opcode in AsmPrinter");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,6 +166,33 @@ void RISCv64ISel::selectBasicBlock(BasicBlock* bb) {
|
|||||||
select_recursive(node_to_select);
|
select_recursive(node_to_select);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CurMBB == MFunc->getBlocks().front().get()) { // 只对入口块操作
|
||||||
|
auto keepalive = std::make_unique<MachineInstr>(RVOpcodes::PSEUDO_KEEPALIVE);
|
||||||
|
for (Argument* arg : F->getArguments()) {
|
||||||
|
keepalive->addOperand(std::make_unique<RegOperand>(getVReg(arg)));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& instrs = CurMBB->getInstructions();
|
||||||
|
auto insert_pos = instrs.end();
|
||||||
|
|
||||||
|
// 关键:检查基本块是否以一个“终止指令”结尾
|
||||||
|
if (!instrs.empty()) {
|
||||||
|
RVOpcodes last_op = instrs.back()->getOpcode();
|
||||||
|
// 扩充了判断条件,涵盖所有可能的终止指令
|
||||||
|
if (last_op == RVOpcodes::J || last_op == RVOpcodes::RET ||
|
||||||
|
last_op == RVOpcodes::BEQ || last_op == RVOpcodes::BNE ||
|
||||||
|
last_op == RVOpcodes::BLT || last_op == RVOpcodes::BGE ||
|
||||||
|
last_op == RVOpcodes::BLTU || last_op == RVOpcodes::BGEU)
|
||||||
|
{
|
||||||
|
// 如果是,插入点就在这个终止指令之前
|
||||||
|
insert_pos = std::prev(instrs.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在计算出的正确位置插入伪指令
|
||||||
|
instrs.insert(insert_pos, std::move(keepalive));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 核心函数:为DAG节点选择并生成MachineInstr (已修复和增强的完整版本)
|
// 核心函数:为DAG节点选择并生成MachineInstr (已修复和增强的完整版本)
|
||||||
|
|||||||
@@ -351,6 +351,18 @@ void RISCv64RegAlloc::getInstrUseDef(MachineInstr* instr, LiveSet& use, LiveSet&
|
|||||||
bool first_reg_is_def = true; // 默认情况下,指令的第一个寄存器操作数是定义 (def)
|
bool first_reg_is_def = true; // 默认情况下,指令的第一个寄存器操作数是定义 (def)
|
||||||
auto opcode = instr->getOpcode();
|
auto opcode = instr->getOpcode();
|
||||||
|
|
||||||
|
if (opcode == RVOpcodes::PSEUDO_KEEPALIVE) {
|
||||||
|
for (auto& op : instr->getOperands()) {
|
||||||
|
if (op->getKind() == MachineOperand::KIND_REG) {
|
||||||
|
auto reg_op = static_cast<RegOperand*>(op.get());
|
||||||
|
if (reg_op->isVirtual()) {
|
||||||
|
use.insert(reg_op->getVRegNum()); // 它的所有操作数都是 "use"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return; // 处理完毕
|
||||||
|
}
|
||||||
|
|
||||||
// 1. 特殊指令的 `is_def` 标志调整
|
// 1. 特殊指令的 `is_def` 标志调整
|
||||||
// 这些指令的第一个寄存器操作数是源操作数 (use),而不是目标操作数 (def)。
|
// 这些指令的第一个寄存器操作数是源操作数 (use),而不是目标操作数 (def)。
|
||||||
if (opcode == RVOpcodes::SW || opcode == RVOpcodes::SD || opcode == RVOpcodes::FSW ||
|
if (opcode == RVOpcodes::SW || opcode == RVOpcodes::SD || opcode == RVOpcodes::FSW ||
|
||||||
@@ -673,6 +685,22 @@ void RISCv64RegAlloc::buildInterferenceGraph() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 所有在某一点上同时活跃的寄存器(即live_out集合中的所有成员),
|
||||||
|
// 它们之间必须两两互相干扰。
|
||||||
|
// 这会根据我们修正后的 liveness 信息,在所有参数vreg之间构建一个完全图(clique)。
|
||||||
|
std::vector<unsigned> live_out_vec(live_out.begin(), live_out.end());
|
||||||
|
for (size_t i = 0; i < live_out_vec.size(); ++i) {
|
||||||
|
for (size_t j = i + 1; j < live_out_vec.size(); ++j) {
|
||||||
|
unsigned u = live_out_vec[i];
|
||||||
|
unsigned v = live_out_vec[j];
|
||||||
|
if (DEEPDEBUG && interference_graph[u].find(v) == interference_graph[u].end()) {
|
||||||
|
std::cerr << " Edge (Live-Live): %vreg" << u << " <-> %vreg" << v << "\n";
|
||||||
|
}
|
||||||
|
interference_graph[u].insert(v);
|
||||||
|
interference_graph[v].insert(u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 在非move指令中,def 与 use 互相干扰
|
// 在非move指令中,def 与 use 互相干扰
|
||||||
if (instr->getOpcode() != RVOpcodes::MV) {
|
if (instr->getOpcode() != RVOpcodes::MV) {
|
||||||
for (unsigned d : def) {
|
for (unsigned d : def) {
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ enum class RVOpcodes {
|
|||||||
FMV_X_W, // fmv.x.w rd, rs1 (浮点寄存器位模式 -> 整数寄存器)
|
FMV_X_W, // fmv.x.w rd, rs1 (浮点寄存器位模式 -> 整数寄存器)
|
||||||
FNEG_S, // fneg.s rd, rs (浮点取负)
|
FNEG_S, // fneg.s rd, rs (浮点取负)
|
||||||
|
|
||||||
// 新增伪指令,用于解耦栈帧处理
|
// 伪指令
|
||||||
FRAME_LOAD_W, // 从栈帧加载 32位 Word (对应 lw)
|
FRAME_LOAD_W, // 从栈帧加载 32位 Word (对应 lw)
|
||||||
FRAME_LOAD_D, // 从栈帧加载 64位 Doubleword (对应 ld)
|
FRAME_LOAD_D, // 从栈帧加载 64位 Doubleword (对应 ld)
|
||||||
FRAME_STORE_W, // 保存 32位 Word 到栈帧 (对应 sw)
|
FRAME_STORE_W, // 保存 32位 Word 到栈帧 (对应 sw)
|
||||||
@@ -100,6 +100,7 @@ enum class RVOpcodes {
|
|||||||
FRAME_LOAD_F, // 从栈帧加载单精度浮点数
|
FRAME_LOAD_F, // 从栈帧加载单精度浮点数
|
||||||
FRAME_STORE_F, // 将单精度浮点数存入栈帧
|
FRAME_STORE_F, // 将单精度浮点数存入栈帧
|
||||||
FRAME_ADDR, // 获取栈帧变量的地址
|
FRAME_ADDR, // 获取栈帧变量的地址
|
||||||
|
PSEUDO_KEEPALIVE, // 保持寄存器活跃,防止优化器删除
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool isGPR(PhysicalReg reg) {
|
inline bool isGPR(PhysicalReg reg) {
|
||||||
|
|||||||
Reference in New Issue
Block a user