[backend-float]修复部分问题

This commit is contained in:
Lixuanwang
2025-07-30 16:00:02 +08:00
parent 39c13c46ec
commit 877a0f5dc2
3 changed files with 214 additions and 79 deletions

View File

@ -48,10 +48,17 @@ unsigned RISCv64ISel::getVReg(Value* val) {
unsigned new_vreg = vreg_counter++;
vreg_map[val] = new_vreg;
vreg_to_value_map[new_vreg] = val;
vreg_type_map[new_vreg] = val->getType();
}
return vreg_map.at(val);
}
unsigned RISCv64ISel::getNewVReg(Type* type) {
unsigned new_vreg = vreg_counter++;
vreg_type_map[new_vreg] = type; // 记录这个新vreg的类型
return new_vreg;
}
// 主入口函数
std::unique_ptr<MachineFunction> RISCv64ISel::runOnFunction(Function* func) {
F = func;
@ -185,7 +192,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
// 2. 使用 fmv.w.x 指令将位模式从整数寄存器移动到浮点寄存器
auto const_val = dynamic_cast<ConstantValue*>(node->value);
auto float_vreg = getVReg(const_val);
auto temp_int_vreg = getNewVReg(); // 临时整数虚拟寄存器
auto temp_int_vreg = getNewVReg(Type::getIntType()); // 临时整数虚拟寄存器
float f_val = const_val->getFloat();
// 使用 reinterpret_cast 获取浮点数的32位二进制表示
@ -235,7 +242,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
} else if (auto global = dynamic_cast<GlobalValue*>(ptr_val)) {
// 对于全局变量,先用 la 加载其地址
auto addr_vreg = getNewVReg();
auto addr_vreg = getNewVReg(Type::getPointerType(global->getType()));
auto la = std::make_unique<MachineInstr>(RVOpcodes::LA);
la->addOperand(std::make_unique<RegOperand>(addr_vreg));
la->addOperand(std::make_unique<LabelOperand>(global->getName()));
@ -280,7 +287,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(li));
} else if (val_const->isFloat()) {
// 先将浮点数的位模式加载到整数vreg再用fmv.w.x移到浮点vreg
auto temp_int_vreg = getNewVReg();
auto temp_int_vreg = getNewVReg(Type::getIntType());
auto float_vreg = getVReg(val_const);
float f_val = val_const->getFloat();
@ -327,7 +334,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
} else if (auto global = dynamic_cast<GlobalValue*>(ptr_val)) {
// 向全局变量存储
auto addr_vreg = getNewVReg();
auto addr_vreg = getNewVReg(Type::getIntType());
auto la = std::make_unique<MachineInstr>(RVOpcodes::LA);
la->addOperand(std::make_unique<RegOperand>(addr_vreg));
la->addOperand(std::make_unique<LabelOperand>(global->getName()));
@ -387,7 +394,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
}
// 2. [修改] 根据基地址的类型,生成不同的指令来获取基地址
auto base_addr_vreg = getNewVReg(); // 创建一个新的临时vreg来存放基地址
auto base_addr_vreg = getNewVReg(Type::getIntType()); // 创建一个新的临时vreg来存放基地址
// 情况一:基地址是局部栈变量
if (auto alloca_base = dynamic_cast<AllocaInst*>(base)) {
@ -760,107 +767,195 @@ void RISCv64ISel::selectNode(DAGNode* node) {
case DAGNode::CALL: {
auto call = dynamic_cast<CallInst*>(node->value);
// 处理函数参数放入a0-a7物理寄存器
size_t num_operands = node->operands.size();
size_t reg_arg_count = std::min(num_operands, (size_t)8);
for (size_t i = 0; i < reg_arg_count; ++i) {
DAGNode* arg_node = node->operands[i];
auto arg_preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + i);
if (arg_node->kind == DAGNode::CONSTANT) {
if (auto const_val = dynamic_cast<ConstantValue*>(arg_node->value)) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(arg_preg));
li->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li));
// --- 步骤 1: 分配寄存器参数和栈参数 ---
// 根据RISC-V调用约定前8个整数/指针参数通过a0-a7传递
// 前8个浮点参数通过fa0-fa7传递 (物理寄存器 f10-f17)。其余参数通过栈传递。
int int_reg_idx = 0; // a0-a7 的索引
int fp_reg_idx = 0; // fa0-fa7 的索引
// 用于存储需要通过栈传递的参数
std::vector<DAGNode*> stack_args;
for (size_t i = 0; i < num_operands; ++i) {
DAGNode* arg_node = node->operands[i];
Value* arg_val = arg_node->value;
Type* arg_type = arg_val->getType();
// 判断参数是浮点类型还是整型/指针类型
if (arg_type->isFloat()) {
if (fp_reg_idx < 8) {
// --- 处理浮点寄存器参数 (fa0-fa7, 对应物理寄存器 F10-F17) ---
auto arg_preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::F10) + fp_reg_idx);
fp_reg_idx++;
if (auto const_val = dynamic_cast<ConstantValue*>(arg_val)) {
// 如果是浮点常量,需要先物化
// 1. 获取其32位二进制表示
float f_val = const_val->getFloat();
uint32_t float_bits = *reinterpret_cast<uint32_t*>(&f_val);
// 2. 将位模式加载到一个临时整数寄存器 (使用t0)
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(PhysicalReg::T0));
li->addOperand(std::make_unique<ImmOperand>(float_bits));
CurMBB->addInstruction(std::move(li));
// 3. 使用fmv.w.x将位模式从整数寄存器移动到目标浮点参数寄存器
auto fmv_wx = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
fmv_wx->addOperand(std::make_unique<RegOperand>(arg_preg));
fmv_wx->addOperand(std::make_unique<RegOperand>(PhysicalReg::T0));
CurMBB->addInstruction(std::move(fmv_wx));
} else {
// 如果已经是虚拟寄存器,直接用 fmv.s 移动
auto src_vreg = getVReg(arg_val);
auto fmv_s = std::make_unique<MachineInstr>(RVOpcodes::FMV_S);
fmv_s->addOperand(std::make_unique<RegOperand>(arg_preg));
fmv_s->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(fmv_s));
}
} else {
// 浮点寄存器已用完,放到栈上传递
stack_args.push_back(arg_node);
}
} else { // 整数或指针参数
if (int_reg_idx < 8) {
// --- 处理整数/指针寄存器参数 (a0-a7) ---
auto arg_preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + int_reg_idx);
int_reg_idx++;
if (arg_node->kind == DAGNode::CONSTANT) {
if (auto const_val = dynamic_cast<ConstantValue*>(arg_val)) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(arg_preg));
li->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li));
}
} else {
auto src_vreg = getVReg(arg_val);
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(arg_preg));
mv->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(mv));
}
} else {
// 整数寄存器已用完,放到栈上传递
stack_args.push_back(arg_node);
}
} else {
auto src_vreg = getVReg(arg_node->value);
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(arg_preg));
mv->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(mv));
}
}
if (num_operands > 8) {
size_t stack_arg_count = num_operands - 8;
int stack_space = stack_arg_count * 8; // RV64中每个参数槽位8字节
// 2a. 在栈上分配空间
auto alloc_instr = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
alloc_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
alloc_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
alloc_instr->addOperand(std::make_unique<ImmOperand>(-stack_space));
CurMBB->addInstruction(std::move(alloc_instr));
// --- 步骤 2: 处理所有栈参数 ---
int stack_space = 0;
if (!stack_args.empty()) {
// 计算栈参数所需的总空间RV64中每个槽位为8字节
stack_space = stack_args.size() * 8;
// 根据ABI为call分配的栈空间需要16字节对齐
if (stack_space % 16 != 0) {
stack_space += 16 - (stack_space % 16);
}
// 在栈上分配空间
if (stack_space > 0) {
auto alloc_instr = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
alloc_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
alloc_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
alloc_instr->addOperand(std::make_unique<ImmOperand>(-stack_space));
CurMBB->addInstruction(std::move(alloc_instr));
}
// 将每个参数存储到栈上对应的位置
for (size_t i = 0; i < stack_args.size(); ++i) {
DAGNode* arg_node = stack_args[i];
Value* arg_val = arg_node->value;
Type* arg_type = arg_val->getType();
int offset = i * 8;
// 2b. 存储每个栈参数
for (size_t i = 8; i < num_operands; ++i) {
DAGNode* arg_node = node->operands[i];
unsigned src_vreg;
// 准备源寄存器
if (arg_node->kind == DAGNode::CONSTANT) {
// 如果是常量,先加载到临时寄存器
src_vreg = getNewVReg();
auto const_val = dynamic_cast<ConstantValue*>(arg_node->value);
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(src_vreg));
li->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li));
// 如果是常量先加载到临时vreg
if (auto const_val = dynamic_cast<ConstantValue*>(arg_val)) {
src_vreg = getNewVReg(arg_type);
if(arg_type->isFloat()) {
auto temp_int_vreg = getNewVReg(Type::getIntType());
float f_val = const_val->getFloat();
uint32_t float_bits = *reinterpret_cast<uint32_t*>(&f_val);
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));
auto fmv_wx = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
fmv_wx->addOperand(std::make_unique<RegOperand>(src_vreg));
fmv_wx->addOperand(std::make_unique<RegOperand>(temp_int_vreg));
CurMBB->addInstruction(std::move(fmv_wx));
} else {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(src_vreg));
li->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li));
}
} else {
src_vreg = getVReg(arg_node->value);
src_vreg = getVReg(arg_val);
}
// 计算在栈上的偏移量
int offset = (i - 8) * 8;
// 生成 sd 指令
auto sd_instr = std::make_unique<MachineInstr>(RVOpcodes::SD);
sd_instr->addOperand(std::make_unique<RegOperand>(src_vreg));
sd_instr->addOperand(std::make_unique<MemOperand>(
// 根据类型选择 fsw (浮点) 或 sd (整型/指针) 存储指令
std::unique_ptr<MachineInstr> store_instr;
if (arg_type->isFloat()) {
store_instr = std::make_unique<MachineInstr>(RVOpcodes::FSW);
} else {
store_instr = std::make_unique<MachineInstr>(RVOpcodes::SD);
}
store_instr->addOperand(std::make_unique<RegOperand>(src_vreg));
store_instr->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::SP),
std::make_unique<ImmOperand>(offset)
));
CurMBB->addInstruction(std::move(sd_instr));
CurMBB->addInstruction(std::move(store_instr));
}
}
// --- 步骤 3: 生成CALL指令 ---
auto call_instr = std::make_unique<MachineInstr>(RVOpcodes::CALL);
// [协议] 如果函数有返回值,将它的目标虚拟寄存器作为第一个操作数
if (!call->getType()->isVoid()) {
unsigned dest_vreg = getVReg(call);
call_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
}
// 将函数名标签作为后续操作数
call_instr->addOperand(std::make_unique<LabelOperand>(call->getCallee()->getName()));
// 将所有参数的虚拟寄存器也作为后续操作数供getInstrUseDef分析
for (size_t i = 0; i < num_operands; ++i) {
if (node->operands[i]->kind != DAGNode::CONSTANT) { // 常量参数已直接加载无需作为use
if (node->operands[i]->kind != DAGNode::CONSTANT && node->operands[i]->kind != DAGNode::FP_CONSTANT) {
call_instr->addOperand(std::make_unique<RegOperand>(getVReg(node->operands[i]->value)));
}
}
CurMBB->addInstruction(std::move(call_instr));
if (num_operands > 8) {
size_t stack_arg_count = num_operands - 8;
int stack_space = stack_arg_count * 8;
// --- 步骤 4: 处理返回值 ---
if (!call->getType()->isVoid()) {
unsigned dest_vreg = getVReg(call);
if (call->getType()->isFloat()) {
// 浮点返回值在 fa0 (物理寄存器 F10)
auto fmv_s = std::make_unique<MachineInstr>(RVOpcodes::FMV_S);
fmv_s->addOperand(std::make_unique<RegOperand>(dest_vreg));
fmv_s->addOperand(std::make_unique<RegOperand>(PhysicalReg::F10)); // fa0
CurMBB->addInstruction(std::move(fmv_s));
} else {
// 整数/指针返回值在 a0
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(dest_vreg));
mv->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
CurMBB->addInstruction(std::move(mv));
}
}
// --- 步骤 5: 回收为栈参数分配的空间 ---
if (stack_space > 0) {
auto dealloc_instr = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
dealloc_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
dealloc_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
dealloc_instr->addOperand(std::make_unique<ImmOperand>(stack_space));
CurMBB->addInstruction(std::move(dealloc_instr));
}
// 处理返回值从a0移动到目标虚拟寄存器
// if (!call->getType()->isVoid()) {
// auto mv_instr = std::make_unique<MachineInstr>(RVOpcodes::MV);
// mv_instr->addOperand(std::make_unique<RegOperand>(getVReg(call)));
// mv_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
// CurMBB->addInstruction(std::move(mv_instr));
// }
break;
}
@ -868,17 +963,47 @@ void RISCv64ISel::selectNode(DAGNode* node) {
auto ret_inst_ir = dynamic_cast<ReturnInst*>(node->value);
if (ret_inst_ir && ret_inst_ir->hasReturnValue()) {
Value* ret_val = ret_inst_ir->getReturnValue();
// [V2优点] 在RETURN节点内加载常量返回值
if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) {
auto li_instr = std::make_unique<MachineInstr>(RVOpcodes::LI);
li_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
li_instr->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li_instr));
Type* ret_type = ret_val->getType();
if (ret_type->isFloat()) {
// --- 处理浮点返回值 ---
// 返回值需要被放入 fa0 (物理寄存器 F10)
if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) {
// 如果是浮点常量需要先物化到fa0
float f_val = const_val->getFloat();
uint32_t float_bits = *reinterpret_cast<uint32_t*>(&f_val);
// 1. 加载位模式到临时整数寄存器 (t0)
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(PhysicalReg::T0));
li->addOperand(std::make_unique<ImmOperand>(float_bits));
CurMBB->addInstruction(std::move(li));
// 2. 将位模式从 t0 移动到 fa0
auto fmv_wx = std::make_unique<MachineInstr>(RVOpcodes::FMV_W_X);
fmv_wx->addOperand(std::make_unique<RegOperand>(PhysicalReg::F10)); // fa0
fmv_wx->addOperand(std::make_unique<RegOperand>(PhysicalReg::T0));
CurMBB->addInstruction(std::move(fmv_wx));
} else {
// 如果是vreg直接用 fmv.s 移动到 fa0
auto fmv_s = std::make_unique<MachineInstr>(RVOpcodes::FMV_S);
fmv_s->addOperand(std::make_unique<RegOperand>(PhysicalReg::F10)); // fa0
fmv_s->addOperand(std::make_unique<RegOperand>(getVReg(ret_val)));
CurMBB->addInstruction(std::move(fmv_s));
}
} else {
auto mv_instr = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
mv_instr->addOperand(std::make_unique<RegOperand>(getVReg(ret_val)));
CurMBB->addInstruction(std::move(mv_instr));
// --- 处理整数/指针返回值 ---
// 返回值需要被放入 a0
// [V2优点] 在RETURN节点内加载常量返回值
if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) {
auto li_instr = std::make_unique<MachineInstr>(RVOpcodes::LI);
li_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
li_instr->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li_instr));
} else {
auto mv_instr = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
mv_instr->addOperand(std::make_unique<RegOperand>(getVReg(ret_val)));
CurMBB->addInstruction(std::move(mv_instr));
}
}
}
// [V1设计保留] 函数尾声epilogue不由RETURN节点生成

View File

@ -47,6 +47,13 @@ RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc) : MFunc(mfunc) {
// 寄存器分配的主入口点
void RISCv64RegAlloc::run() {
// --- 在所有流程开始前构建完整的vreg到Value的反向映射 ---
const auto& vreg_map_from_isel = MFunc->getISel()->getVRegMap();
for (const auto& pair : vreg_map_from_isel) {
Value* val = pair.first;
unsigned vreg = pair.second;
vreg_to_value_map[vreg] = val;
}
// 阶段 1: 处理函数调用约定(参数寄存器预着色)
handleCallingConvention();
// 阶段 2: 消除帧索引(为局部变量和栈参数分配栈偏移)

View File

@ -17,9 +17,11 @@ public:
// 公开接口以便后续模块如RegAlloc可以查询或创建vreg
unsigned getVReg(Value* val);
unsigned getNewVReg() { return vreg_counter++; }
unsigned getNewVReg(Type* type);
// 获取 vreg_map 的公共接口
const std::map<Value*, unsigned>& getVRegMap() const { return vreg_map; }
const std::map<unsigned, Value*>& getVRegValueMap() const { return vreg_to_value_map; }
const std::map<unsigned, Type*>& getVRegTypeMap() const { return vreg_type_map; }
private:
// DAG节点定义作为ISel的内部实现细节
@ -50,6 +52,7 @@ private:
// 映射关系
std::map<Value*, unsigned> vreg_map;
std::map<unsigned, Value*> vreg_to_value_map;
std::map<unsigned, Type*> vreg_type_map;
std::map<const BasicBlock*, MachineBasicBlock*> bb_map;
unsigned vreg_counter;