[backend]浮点逻辑与gcc保持一致
This commit is contained in:
@ -102,6 +102,7 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
|
|||||||
case RVOpcodes::FLE_S: *OS << "fle.s "; break;
|
case RVOpcodes::FLE_S: *OS << "fle.s "; break;
|
||||||
case RVOpcodes::FCVT_S_W: *OS << "fcvt.s.w "; break;
|
case RVOpcodes::FCVT_S_W: *OS << "fcvt.s.w "; break;
|
||||||
case RVOpcodes::FCVT_W_S: *OS << "fcvt.w.s "; break;
|
case RVOpcodes::FCVT_W_S: *OS << "fcvt.w.s "; break;
|
||||||
|
case RVOpcodes::FCVT_W_S_RTZ: *OS << "fcvt.w.s "; break;
|
||||||
case RVOpcodes::FMV_S: *OS << "fmv.s "; break;
|
case RVOpcodes::FMV_S: *OS << "fmv.s "; break;
|
||||||
case RVOpcodes::FMV_W_X: *OS << "fmv.w.x "; break;
|
case RVOpcodes::FMV_W_X: *OS << "fmv.w.x "; break;
|
||||||
case RVOpcodes::FMV_X_W: *OS << "fmv.x.w "; break;
|
case RVOpcodes::FMV_X_W: *OS << "fmv.x.w "; break;
|
||||||
|
|||||||
@ -745,83 +745,12 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
CurMBB->addInstruction(std::move(instr));
|
CurMBB->addInstruction(std::move(instr));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instruction::kFtoI: { // 浮点 to 整数 (带向下取整)
|
case Instruction::kFtoI: { // 浮点 to 整数 (使用硬件指令进行向零截断)
|
||||||
// 目标:实现 floor(x) 的效果, C/C++中浮点转整数是截断(truncate)
|
// 直接生成一条带有 rtz 舍入模式的转换指令
|
||||||
// 对于正数,floor(x) == truncate(x)
|
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FCVT_W_S_RTZ);
|
||||||
// RISC-V的 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));
|
||||||
// temp_i = fcvt.w.s(x) // 四舍五入
|
|
||||||
// temp_f = fcvt.s.w(temp_i) // 转回浮点
|
|
||||||
// if (x < temp_f) { // 如果原数更小,说明被“五入”了
|
|
||||||
// result = temp_i - 1
|
|
||||||
// } else {
|
|
||||||
// result = temp_i
|
|
||||||
// }
|
|
||||||
|
|
||||||
auto temp_i_vreg = getNewVReg(Type::getIntType());
|
|
||||||
auto temp_f_vreg = getNewVReg(Type::getFloatType());
|
|
||||||
auto cmp_vreg = getNewVReg(Type::getIntType());
|
|
||||||
|
|
||||||
// 1. fcvt.w.s temp_i_vreg, src_vreg
|
|
||||||
auto fcvt_w = std::make_unique<MachineInstr>(RVOpcodes::FCVT_W_S);
|
|
||||||
fcvt_w->addOperand(std::make_unique<RegOperand>(temp_i_vreg));
|
|
||||||
fcvt_w->addOperand(std::make_unique<RegOperand>(src_vreg));
|
|
||||||
CurMBB->addInstruction(std::move(fcvt_w));
|
|
||||||
|
|
||||||
// 2. fcvt.s.w temp_f_vreg, temp_i_vreg
|
|
||||||
auto fcvt_s = std::make_unique<MachineInstr>(RVOpcodes::FCVT_S_W);
|
|
||||||
fcvt_s->addOperand(std::make_unique<RegOperand>(temp_f_vreg));
|
|
||||||
fcvt_s->addOperand(std::make_unique<RegOperand>(temp_i_vreg));
|
|
||||||
CurMBB->addInstruction(std::move(fcvt_s));
|
|
||||||
|
|
||||||
// 3. flt.s cmp_vreg, src_vreg, temp_f_vreg
|
|
||||||
auto flt = std::make_unique<MachineInstr>(RVOpcodes::FLT_S);
|
|
||||||
flt->addOperand(std::make_unique<RegOperand>(cmp_vreg));
|
|
||||||
flt->addOperand(std::make_unique<RegOperand>(src_vreg));
|
|
||||||
flt->addOperand(std::make_unique<RegOperand>(temp_f_vreg));
|
|
||||||
CurMBB->addInstruction(std::move(flt));
|
|
||||||
|
|
||||||
// 创建标签
|
|
||||||
int unique_id = this->local_label_counter++;
|
|
||||||
std::string rounded_up_label = MFunc->getName() + "_ftoi_rounded_up_" + std::to_string(unique_id);
|
|
||||||
std::string done_label = MFunc->getName() + "_ftoi_done_" + std::to_string(unique_id);
|
|
||||||
|
|
||||||
// 4. bne cmp_vreg, x0, rounded_up_label
|
|
||||||
auto bne = std::make_unique<MachineInstr>(RVOpcodes::BNE);
|
|
||||||
bne->addOperand(std::make_unique<RegOperand>(cmp_vreg));
|
|
||||||
bne->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
|
|
||||||
bne->addOperand(std::make_unique<LabelOperand>(rounded_up_label));
|
|
||||||
CurMBB->addInstruction(std::move(bne));
|
|
||||||
|
|
||||||
// 5. else 分支: mv dest_vreg, temp_i_vreg
|
|
||||||
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
|
|
||||||
mv->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
|
||||||
mv->addOperand(std::make_unique<RegOperand>(temp_i_vreg));
|
|
||||||
CurMBB->addInstruction(std::move(mv));
|
|
||||||
|
|
||||||
// 6. j done_label
|
|
||||||
auto j = std::make_unique<MachineInstr>(RVOpcodes::J);
|
|
||||||
j->addOperand(std::make_unique<LabelOperand>(done_label));
|
|
||||||
CurMBB->addInstruction(std::move(j));
|
|
||||||
|
|
||||||
// 7. rounded_up_label:
|
|
||||||
auto label_up = std::make_unique<MachineInstr>(RVOpcodes::LABEL);
|
|
||||||
label_up->addOperand(std::make_unique<LabelOperand>(rounded_up_label));
|
|
||||||
CurMBB->addInstruction(std::move(label_up));
|
|
||||||
|
|
||||||
// 8. addiw dest_vreg, temp_i_vreg, -1
|
|
||||||
auto addi = std::make_unique<MachineInstr>(RVOpcodes::ADDIW);
|
|
||||||
addi->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
|
||||||
addi->addOperand(std::make_unique<RegOperand>(temp_i_vreg));
|
|
||||||
addi->addOperand(std::make_unique<ImmOperand>(-1));
|
|
||||||
CurMBB->addInstruction(std::move(addi));
|
|
||||||
|
|
||||||
// 9. done_label:
|
|
||||||
auto label_done = std::make_unique<MachineInstr>(RVOpcodes::LABEL);
|
|
||||||
label_done->addOperand(std::make_unique<LabelOperand>(done_label));
|
|
||||||
CurMBB->addInstruction(std::move(label_done));
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instruction::kFNeg: { // 浮点取负
|
case Instruction::kFNeg: { // 浮点取负
|
||||||
@ -1202,10 +1131,11 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
auto r_value_byte = getVReg(memset->getValue());
|
auto r_value_byte = getVReg(memset->getValue());
|
||||||
|
|
||||||
// 为memset内部逻辑创建新的临时虚拟寄存器
|
// 为memset内部逻辑创建新的临时虚拟寄存器
|
||||||
auto r_counter = getNewVReg();
|
Type* ptr_type = Type::getPointerType(Type::getIntType());
|
||||||
auto r_end_addr = getNewVReg();
|
auto r_counter = getNewVReg(ptr_type);
|
||||||
auto r_current_addr = getNewVReg();
|
auto r_end_addr = getNewVReg(ptr_type);
|
||||||
auto r_temp_val = getNewVReg();
|
auto r_current_addr = getNewVReg(ptr_type);
|
||||||
|
auto r_temp_val = getNewVReg(Type::getIntType());
|
||||||
|
|
||||||
// 定义一系列lambda表达式来简化指令创建
|
// 定义一系列lambda表达式来简化指令创建
|
||||||
auto add_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, unsigned rs2) {
|
auto add_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, unsigned rs2) {
|
||||||
@ -1296,7 +1226,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
|
|
||||||
// --- Step 1: 获取基地址 (此部分逻辑正确,保持不变) ---
|
// --- Step 1: 获取基地址 (此部分逻辑正确,保持不变) ---
|
||||||
auto base_ptr_node = node->operands[0];
|
auto base_ptr_node = node->operands[0];
|
||||||
auto current_addr_vreg = getNewVReg();
|
auto current_addr_vreg = getNewVReg(gep->getType());
|
||||||
|
|
||||||
if (auto alloca_base = dynamic_cast<AllocaInst*>(base_ptr_node->value)) {
|
if (auto alloca_base = dynamic_cast<AllocaInst*>(base_ptr_node->value)) {
|
||||||
auto frame_addr_instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_ADDR);
|
auto frame_addr_instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_ADDR);
|
||||||
@ -1338,13 +1268,13 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
// 如果步长为0(例如对一个void类型或空结构体索引),则不产生任何偏移
|
// 如果步长为0(例如对一个void类型或空结构体索引),则不产生任何偏移
|
||||||
if (stride != 0) {
|
if (stride != 0) {
|
||||||
// --- 为当前索引和步长生成偏移计算指令 ---
|
// --- 为当前索引和步长生成偏移计算指令 ---
|
||||||
auto offset_vreg = getNewVReg();
|
auto offset_vreg = getNewVReg(Type::getIntType());
|
||||||
|
|
||||||
// 处理索引 - 区分常量与动态值
|
// 处理索引 - 区分常量与动态值
|
||||||
unsigned index_vreg;
|
unsigned index_vreg;
|
||||||
if (auto const_index = dynamic_cast<ConstantValue*>(indexValue)) {
|
if (auto const_index = dynamic_cast<ConstantValue*>(indexValue)) {
|
||||||
// 对于常量索引,直接创建新的虚拟寄存器
|
// 对于常量索引,直接创建新的虚拟寄存器
|
||||||
index_vreg = getNewVReg();
|
index_vreg = getNewVReg(Type::getIntType());
|
||||||
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
||||||
li->addOperand(std::make_unique<RegOperand>(index_vreg));
|
li->addOperand(std::make_unique<RegOperand>(index_vreg));
|
||||||
li->addOperand(std::make_unique<ImmOperand>(const_index->getInt()));
|
li->addOperand(std::make_unique<ImmOperand>(const_index->getInt()));
|
||||||
@ -1362,7 +1292,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
CurMBB->addInstruction(std::move(mv));
|
CurMBB->addInstruction(std::move(mv));
|
||||||
} else {
|
} else {
|
||||||
// 步长不为1,需要生成乘法指令
|
// 步长不为1,需要生成乘法指令
|
||||||
auto size_vreg = getNewVReg();
|
auto size_vreg = getNewVReg(Type::getIntType());
|
||||||
auto li_size = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
auto li_size = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
||||||
li_size->addOperand(std::make_unique<RegOperand>(size_vreg));
|
li_size->addOperand(std::make_unique<RegOperand>(size_vreg));
|
||||||
li_size->addOperand(std::make_unique<ImmOperand>(stride));
|
li_size->addOperand(std::make_unique<ImmOperand>(stride));
|
||||||
|
|||||||
@ -22,7 +22,6 @@ public:
|
|||||||
|
|
||||||
// 公开接口,以便后续模块(如RegAlloc)可以查询或创建vreg
|
// 公开接口,以便后续模块(如RegAlloc)可以查询或创建vreg
|
||||||
unsigned getVReg(Value* val);
|
unsigned getVReg(Value* val);
|
||||||
unsigned getNewVReg() { return vreg_counter++; }
|
|
||||||
unsigned getNewVReg(Type* type);
|
unsigned getNewVReg(Type* type);
|
||||||
unsigned getVRegCounter() const;
|
unsigned getVRegCounter() const;
|
||||||
// 获取 vreg_map 的公共接口
|
// 获取 vreg_map 的公共接口
|
||||||
|
|||||||
@ -88,6 +88,7 @@ enum class RVOpcodes {
|
|||||||
// 浮点转换
|
// 浮点转换
|
||||||
FCVT_S_W, // fcvt.s.w rd, rs1 (有符号整数 -> 单精度浮点)
|
FCVT_S_W, // fcvt.s.w rd, rs1 (有符号整数 -> 单精度浮点)
|
||||||
FCVT_W_S, // fcvt.w.s rd, rs1 (单精度浮点 -> 有符号整数)
|
FCVT_W_S, // fcvt.w.s rd, rs1 (单精度浮点 -> 有符号整数)
|
||||||
|
FCVT_W_S_RTZ, // fcvt.w.s rd, rs1, rtz (使用向零截断模式)
|
||||||
|
|
||||||
// 浮点传送/移动
|
// 浮点传送/移动
|
||||||
FMV_S, // fmv.s rd, rs1 (浮点寄存器之间)
|
FMV_S, // fmv.s rd, rs1 (浮点寄存器之间)
|
||||||
|
|||||||
Reference in New Issue
Block a user