diff --git a/src/backend/RISCv64/RISCv64ISel.cpp b/src/backend/RISCv64/RISCv64ISel.cpp index 0d1a201..1f5e7cb 100644 --- a/src/backend/RISCv64/RISCv64ISel.cpp +++ b/src/backend/RISCv64/RISCv64ISel.cpp @@ -103,7 +103,29 @@ void RISCv64ISel::select() { } } - if (optLevel > 0) { + // 仅当函数满足特定条件时,才需要保存参数寄存器,应用更精细的过滤规则 + // 1. 函数包含call指令 (非叶子函数): 参数寄存器(a0-a7)是调用者保存的, + // call指令可能会覆盖这些寄存器,因此必须保存。 + // 2. 函数包含alloca指令 (需要栈分配)。 + // 3. 函数的指令数量超过一个阈值(如20),意味着它是一个复杂的叶子函数, + // 为安全起见,保存其参数。 + // 简单的叶子函数 (如min) 则可以跳过这个步骤进行优化。 + auto shouldSaveArgs = [](Function* func) { + if (!func) return false; + int instruction_count = 0; + for (const auto& bb : func->getBasicBlocks()) { + for (const auto& inst : bb->getInstructions()) { + if (dynamic_cast(inst.get()) || dynamic_cast(inst.get())) { + return true; // 发现call或alloca,立即返回true + } + instruction_count++; + } + } + // 如果没有call或alloca,则检查指令数量 + return instruction_count > 45; + }; + + if (optLevel > 0 && shouldSaveArgs(F)) { if (F && !F->getBasicBlocks().empty()) { // 定位到第一个MachineBasicBlock,也就是函数入口 BasicBlock* first_ir_block = F->getBasicBlocks_NoRange().front().get(); @@ -1334,6 +1356,7 @@ void RISCv64ISel::selectNode(DAGNode* node) { auto gep = dynamic_cast(node->value); auto result_vreg = getVReg(gep); + if (optLevel == 0) { // --- Step 1: 获取基地址 (此部分逻辑正确,保持不变) --- auto base_ptr_node = node->operands[0]; auto current_addr_vreg = getNewVReg(gep->getType()); @@ -1440,6 +1463,106 @@ void RISCv64ISel::selectNode(DAGNode* node) { final_mv->addOperand(std::make_unique(current_addr_vreg)); CurMBB->addInstruction(std::move(final_mv)); break; + } else { + // 对于-O1时的处理逻辑 + // --- Step 1: 获取基地址 --- + auto base_ptr_node = node->operands[0]; + auto base_ptr_val = base_ptr_node->value; + + // last_step_addr_vreg 保存上一步计算的结果。 + // 它首先被初始化为GEP的初始基地址。 + unsigned last_step_addr_vreg; + + if (auto alloca_base = dynamic_cast(base_ptr_val)) { + last_step_addr_vreg = getNewVReg(gep->getType()); + auto frame_addr_instr = std::make_unique(RVOpcodes::FRAME_ADDR); + frame_addr_instr->addOperand(std::make_unique(last_step_addr_vreg)); + frame_addr_instr->addOperand(std::make_unique(getVReg(alloca_base))); + CurMBB->addInstruction(std::move(frame_addr_instr)); + } else if (auto global_base = dynamic_cast(base_ptr_val)) { + last_step_addr_vreg = getNewVReg(gep->getType()); + auto la_instr = std::make_unique(RVOpcodes::LA); + la_instr->addOperand(std::make_unique(last_step_addr_vreg)); + la_instr->addOperand(std::make_unique(global_base->getName())); + CurMBB->addInstruction(std::move(la_instr)); + } else { + // 对于函数参数或来自其他指令的指针,直接获取其vreg。 + // 这个vreg必须被保护,不能在计算中被修改。 + last_step_addr_vreg = getVReg(base_ptr_val); + } + + // --- Step 2: 遵循LLVM GEP语义迭代计算地址 --- + Type* current_type = gep->getBasePointer()->getType()->as()->getBaseType(); + + for (size_t i = 0; i < gep->getNumIndices(); ++i) { + Value* indexValue = gep->getIndex(i); + unsigned stride = getTypeSizeInBytes(current_type); + + if (stride != 0) { + // --- 为当前索引和步长生成偏移计算指令 --- + auto offset_vreg = getNewVReg(Type::getIntType()); + + unsigned index_vreg; + if (auto const_index = dynamic_cast(indexValue)) { + index_vreg = getNewVReg(Type::getIntType()); + auto li = std::make_unique(RVOpcodes::LI); + li->addOperand(std::make_unique(index_vreg)); + li->addOperand(std::make_unique(const_index->getInt())); + CurMBB->addInstruction(std::move(li)); + } else { + index_vreg = getVReg(indexValue); + } + + if (stride == 1) { + auto mv = std::make_unique(RVOpcodes::MV); + mv->addOperand(std::make_unique(offset_vreg)); + mv->addOperand(std::make_unique(index_vreg)); + CurMBB->addInstruction(std::move(mv)); + } else { + auto size_vreg = getNewVReg(Type::getIntType()); + auto li_size = std::make_unique(RVOpcodes::LI); + li_size->addOperand(std::make_unique(size_vreg)); + li_size->addOperand(std::make_unique(stride)); + CurMBB->addInstruction(std::move(li_size)); + + auto mul = std::make_unique(RVOpcodes::MULW); + mul->addOperand(std::make_unique(offset_vreg)); + mul->addOperand(std::make_unique(index_vreg)); + mul->addOperand(std::make_unique(size_vreg)); + CurMBB->addInstruction(std::move(mul)); + } + + // --- 关键修复点 --- + // 创建一个新的vreg来保存本次加法的结果。 + unsigned current_step_addr_vreg = getNewVReg(gep->getType()); + + // 执行 add current_step, last_step, offset + // 这确保了 last_step_addr_vreg (输入) 永远不会被直接修改。 + auto add = std::make_unique(RVOpcodes::ADD); + add->addOperand(std::make_unique(current_step_addr_vreg)); + add->addOperand(std::make_unique(last_step_addr_vreg)); + add->addOperand(std::make_unique(offset_vreg)); + CurMBB->addInstruction(std::move(add)); + + // 本次的结果成为下一次计算的输入。 + last_step_addr_vreg = current_step_addr_vreg; + } + + // --- 为下一次迭代更新类型 --- + if (auto array_type = current_type->as()) { + current_type = array_type->getElementType(); + } else if (auto ptr_type = current_type->as()) { + current_type = ptr_type->getBaseType(); + } + } + + // --- Step 3: 将最终计算出的地址存入GEP的目标虚拟寄存器 --- + auto final_mv = std::make_unique(RVOpcodes::MV); + final_mv->addOperand(std::make_unique(result_vreg)); + final_mv->addOperand(std::make_unique(last_step_addr_vreg)); + CurMBB->addInstruction(std::move(final_mv)); + break; + } } default: