[backend]引入浮点数支持,但目前寄存器分配存在问题

This commit is contained in:
Lixuanwang
2025-07-30 15:07:29 +08:00
parent 860ebcd447
commit dd38bdc133
10 changed files with 748 additions and 199 deletions

View File

@@ -10,7 +10,23 @@ namespace sysy {
// DAG节点定义 (内部实现)
struct RISCv64ISel::DAGNode {
enum NodeKind {ARGUMENT, CONSTANT, LOAD, STORE, BINARY, CALL, RETURN, BRANCH, ALLOCA_ADDR, UNARY, MEMSET, GET_ELEMENT_PTR};
enum NodeKind {
ARGUMENT,
CONSTANT, // 整数或地址常量
LOAD,
STORE,
BINARY, // 整数二元运算
CALL,
RETURN,
BRANCH,
ALLOCA_ADDR,
UNARY, // 整数一元运算
MEMSET,
GET_ELEMENT_PTR,
FP_CONSTANT, // 浮点常量
FBINARY, // 浮点二元运算 (如 FADD, FSUB, FCMP)
FUNARY, // 浮点一元运算 (如 FCVT, FNEG)
};
NodeKind kind;
Value* value = nullptr;
std::vector<DAGNode*> operands;
@@ -29,7 +45,9 @@ unsigned RISCv64ISel::getVReg(Value* val) {
if (vreg_counter == 0) {
vreg_counter = 1; // vreg 0 保留
}
vreg_map[val] = vreg_counter++;
unsigned new_vreg = vreg_counter++;
vreg_map[val] = new_vreg;
vreg_to_value_map[new_vreg] = val;
}
return vreg_map.at(val);
}
@@ -161,18 +179,52 @@ void RISCv64ISel::selectNode(DAGNode* node) {
}
break;
case DAGNode::FP_CONSTANT: {
// RISC-V没有直接加载浮点立即数的指令
// 标准做法是1. 将浮点数的32位二进制表示加载到一个整数寄存器
// 2. 使用 fmv.w.x 指令将位模式从整数寄存器移动到浮点寄存器
auto const_val = dynamic_cast<ConstantValue*>(node->value);
auto float_vreg = getVReg(const_val);
auto temp_int_vreg = getNewVReg(); // 临时整数虚拟寄存器
float f_val = const_val->getFloat();
// 使用 reinterpret_cast 获取浮点数的32位二进制表示
uint32_t float_bits = *reinterpret_cast<uint32_t*>(&f_val);
// 1. li temp_int_vreg, float_bits
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
li->addOperand(std::make_unique<ImmOperand>(float_bits));
CurMBB->addInstruction(std::move(li));
// 2. fmv.w.x float_vreg, temp_int_vreg
auto fmv = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
fmv->addOperand(std::make_unique<RegOperand>(float_vreg));
fmv->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
CurMBB->addInstruction(std::move(fmv));
break;
}
case DAGNode::LOAD: {
auto dest_vreg = getVReg(node->value);
Value* ptr_val = node->operands[0]->value;
// --- 修改点 ---
// 1. 获取加载结果的类型 (即这个LOAD指令自身的类型)
Type* loaded_type = node->value->getType();
// 2. 根据类型选择正确的伪指令或真实指令操作码
RVOpcodes frame_opcode = loaded_type->isPointer() ? RVOpcodes::FRAME_LOAD_D : RVOpcodes::FRAME_LOAD_W;
RVOpcodes real_opcode = loaded_type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW;
RVOpcodes frame_opcode;
RVOpcodes real_opcode;
if (loaded_type->isPointer()) {
frame_opcode = RVOpcodes::FRAME_LOAD_D;
real_opcode = RVOpcodes::LD;
} else if (loaded_type->isFloat()) {
frame_opcode = RVOpcodes::FRAME_LOAD_F;
real_opcode = RVOpcodes::FLW;
} else { // 默认为整数
frame_opcode = RVOpcodes::FRAME_LOAD_W;
real_opcode = RVOpcodes::LW;
}
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
// 3. 创建使用新的、区分宽度的伪指令
@@ -220,20 +272,51 @@ void RISCv64ISel::selectNode(DAGNode* node) {
// 如果要存储的值是一个常量,就在这里生成 `li` 指令加载它
if (auto val_const = dynamic_cast<ConstantValue*>(val_to_store)) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(val_const)));
li->addOperand(std::make_unique<ImmOperand>(val_const->getInt()));
CurMBB->addInstruction(std::move(li));
// 区分整数常量和浮点常量
if (val_const->isInt()) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(getVReg(val_const)));
li->addOperand(std::make_unique<ImmOperand>(val_const->getInt()));
CurMBB->addInstruction(std::move(li));
} else if (val_const->isFloat()) {
// 先将浮点数的位模式加载到整数vreg再用fmv.w.x移到浮点vreg
auto temp_int_vreg = getNewVReg();
auto float_vreg = getVReg(val_const);
float f_val = val_const->getFloat();
uint32_t float_bits = *reinterpret_cast<uint32_t*>(&f_val);
// 1. li temp_int_vreg, float_bits
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
li->addOperand(std::make_unique<ImmOperand>(float_bits));
CurMBB->addInstruction(std::move(li));
// 2. fmv.w.x float_vreg, temp_int_vreg
auto fmv = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
fmv->addOperand(std::make_unique<RegOperand>(float_vreg));
fmv->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
CurMBB->addInstruction(std::move(fmv));
}
}
auto val_vreg = getVReg(val_to_store);
// --- 修改点 ---
// 1. 获取被存储的值的类型
Type* stored_type = val_to_store->getType();
// 2. 根据类型选择正确的伪指令或真实指令操作码
RVOpcodes frame_opcode = stored_type->isPointer() ? RVOpcodes::FRAME_STORE_D : RVOpcodes::FRAME_STORE_W;
RVOpcodes real_opcode = stored_type->isPointer() ? RVOpcodes::SD : RVOpcodes::SW;
RVOpcodes frame_opcode;
RVOpcodes real_opcode;
if (stored_type->isPointer()) {
frame_opcode = RVOpcodes::FRAME_STORE_D;
real_opcode = RVOpcodes::SD;
} else if (stored_type->isFloat()) {
frame_opcode = RVOpcodes::FRAME_STORE_F;
real_opcode = RVOpcodes::FSW;
} else { // 默认为整数
frame_opcode = RVOpcodes::FRAME_STORE_W;
real_opcode = RVOpcodes::SW;
}
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
// 3. 创建使用新的、区分宽度的伪指令
@@ -497,6 +580,109 @@ void RISCv64ISel::selectNode(DAGNode* node) {
break;
}
case DAGNode::FBINARY: {
auto bin = dynamic_cast<BinaryInst*>(node->value);
auto dest_vreg = getVReg(bin);
auto lhs_vreg = getVReg(bin->getLhs());
auto rhs_vreg = getVReg(bin->getRhs());
switch (bin->getKind()) {
case Instruction::kFAdd: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FADD_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFSub: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FSUB_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFMul: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FMUL_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFDiv: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FDIV_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
// --- 浮点比较指令 ---
// 注意:比较结果(0或1)写入的是一个通用整数寄存器(dest_vreg)
case Instruction::kFCmpEQ: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FEQ_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFCmpLT: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FLT_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFCmpLE: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FLE_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
// --- 通过交换操作数或组合指令实现其余比较 ---
case Instruction::kFCmpGT: { // a > b 等价于 b < a
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FLT_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg)); // 操作数交换
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFCmpGE: { // a >= b 等价于 b <= a
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FLE_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg)); // 操作数交换
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFCmpNE: { // a != b 等价于 !(a == b)
// 1. 先用 feq.s 比较,结果存入 dest_vreg
auto feq = std::make_unique<MachineInstr>(RVOpcodes::FEQ_S);
feq->addOperand(std::make_unique<RegOperand>(dest_vreg));
feq->addOperand(std::make_unique<RegOperand>(lhs_vreg));
feq->addOperand(std::make_unique<RegOperand>(rhs_vreg));
CurMBB->addInstruction(std::move(feq));
// 2. 再用 seqz 对结果取反 (如果相等(1)则变0如果不等(0)则变1)
auto seqz = std::make_unique<MachineInstr>(RVOpcodes::SEQZ);
seqz->addOperand(std::make_unique<RegOperand>(dest_vreg));
seqz->addOperand(std::make_unique<RegOperand>(dest_vreg));
CurMBB->addInstruction(std::move(seqz));
break;
}
default:
throw std::runtime_error("Unsupported float binary instruction in ISel");
}
break;
}
case DAGNode::UNARY: {
auto unary = dynamic_cast<UnaryInst*>(node->value);
auto dest_vreg = getVReg(unary);
@@ -524,6 +710,54 @@ void RISCv64ISel::selectNode(DAGNode* node) {
break;
}
case DAGNode::FUNARY: {
auto unary = dynamic_cast<UnaryInst*>(node->value);
auto dest_vreg = getVReg(unary);
auto src_vreg = getVReg(unary->getOperand());
switch (unary->getKind()) {
case Instruction::kItoF: { // 整数 to 浮点
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FCVT_S_W);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是浮点vreg
instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是整数vreg
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFtoI: { // 浮点 to 整数
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FCVT_W_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是整数vreg
instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是浮点vreg
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kFNeg: { // 浮点取负
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FNEG_S);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(instr));
break;
}
// --- 处理位传送指令 ---
case Instruction::kBitItoF: { // 整数位模式 -> 浮点寄存器
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是浮点vreg
instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是整数vreg
CurMBB->addInstruction(std::move(instr));
break;
}
case Instruction::kBitFtoI: { // 浮点位模式 -> 整数寄存器
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FMV_X_W);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是整数vreg
instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是浮点vreg
CurMBB->addInstruction(std::move(instr));
break;
}
default:
throw std::runtime_error("Unsupported float unary instruction in ISel");
}
break;
}
case DAGNode::CALL: {
auto call = dynamic_cast<CallInst*>(node->value);
// 处理函数参数放入a0-a7物理寄存器
@@ -870,7 +1104,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(mv));
}
// --- Step 2: [最终权威版] 遵循LLVM GEP语义迭代计算地址 ---
// --- Step 2: 遵循LLVM GEP语义迭代计算地址 ---
// 初始被索引的类型,是基指针指向的那个类型 (例如, [2 x i32])
Type* current_type = gep->getBasePointer()->getType()->as<PointerType>()->getBaseType();
@@ -971,8 +1205,13 @@ RISCv64ISel::DAGNode* RISCv64ISel::get_operand_node(Value* val_ir, std::map<Valu
// 规则1如果这个Value已经有对应的节点直接返回
if (value_to_node.count(val_ir)) {
return value_to_node[val_ir];
} else if (dynamic_cast<ConstantValue*>(val_ir)) {
return create_node(DAGNode::CONSTANT, val_ir, value_to_node, nodes_storage);
} else if (auto const_val = dynamic_cast<ConstantValue*>(val_ir)) {
if (const_val->isInt()) {
return create_node(DAGNode::CONSTANT, val_ir, value_to_node, nodes_storage);
} else {
// 为浮点常量创建新的FP_CONSTANT节点
return create_node(DAGNode::FP_CONSTANT, val_ir, value_to_node, nodes_storage);
}
} else if (dynamic_cast<GlobalValue*>(val_ir)) {
return create_node(DAGNode::CONSTANT, val_ir, value_to_node, nodes_storage);
} else if (dynamic_cast<AllocaInst*>(val_ir)) {
@@ -1032,6 +1271,17 @@ std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicB
load_node->operands.push_back(get_operand_node(load->getPointer(), value_to_node, nodes_storage));
} else if (auto bin = dynamic_cast<BinaryInst*>(inst)) {
if(value_to_node.count(bin)) continue;
if (bin->getKind() == Instruction::kFSub) {
if (auto const_lhs = dynamic_cast<ConstantValue*>(bin->getLhs())) {
// 使用isZero()来判断浮点数0.0,比直接比较更健壮
if (const_lhs->isZero()) {
// 这是一个浮点取负操作,创建 FUNARY 节点
auto funary_node = create_node(DAGNode::FUNARY, bin, value_to_node, nodes_storage);
funary_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
continue; // 处理完毕,跳到下一条指令
}
}
}
if (bin->getKind() == BinaryInst::kSub) {
if (auto const_lhs = dynamic_cast<ConstantValue*>(bin->getLhs())) {
if (const_lhs->getInt() == 0) {
@@ -1041,13 +1291,24 @@ std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicB
}
}
}
auto bin_node = create_node(DAGNode::BINARY, bin, value_to_node, nodes_storage);
bin_node->operands.push_back(get_operand_node(bin->getLhs(), value_to_node, nodes_storage));
bin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
if (bin->getKind() >= Instruction::kFAdd) { // 假设浮点指令枚举值更大
auto fbin_node = create_node(DAGNode::FBINARY, bin, value_to_node, nodes_storage);
fbin_node->operands.push_back(get_operand_node(bin->getLhs(), value_to_node, nodes_storage));
fbin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
} else {
auto bin_node = create_node(DAGNode::BINARY, bin, value_to_node, nodes_storage);
bin_node->operands.push_back(get_operand_node(bin->getLhs(), value_to_node, nodes_storage));
bin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
}
} else if (auto un = dynamic_cast<UnaryInst*>(inst)) {
if(value_to_node.count(un)) continue;
auto unary_node = create_node(DAGNode::UNARY, un, value_to_node, nodes_storage);
unary_node->operands.push_back(get_operand_node(un->getOperand(), value_to_node, nodes_storage));
if (un->getKind() >= Instruction::kFNeg) {
auto funary_node = create_node(DAGNode::FUNARY, un, value_to_node, nodes_storage);
funary_node->operands.push_back(get_operand_node(un->getOperand(), value_to_node, nodes_storage));
} else {
auto unary_node = create_node(DAGNode::UNARY, un, value_to_node, nodes_storage);
unary_node->operands.push_back(get_operand_node(un->getOperand(), value_to_node, nodes_storage));
}
} else if (auto call = dynamic_cast<CallInst*>(inst)) {
if(value_to_node.count(call)) continue;
auto call_node = create_node(DAGNode::CALL, call, value_to_node, nodes_storage);