From 33388496d5a7327e433322da9d2e338bea8b72b2 Mon Sep 17 00:00:00 2001 From: CGH0S7 <776459475@qq.com> Date: Tue, 19 Aug 2025 22:42:30 +0800 Subject: [PATCH 1/2] =?UTF-8?q?[backend-O1]RISCv64ISel=E5=AF=B9-O1?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=B8=93=E9=97=A8=E7=9A=84=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/RISCv64/RISCv64ISel.cpp | 101 ++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/src/backend/RISCv64/RISCv64ISel.cpp b/src/backend/RISCv64/RISCv64ISel.cpp index 22ccc22..9fccba6 100644 --- a/src/backend/RISCv64/RISCv64ISel.cpp +++ b/src/backend/RISCv64/RISCv64ISel.cpp @@ -1311,6 +1311,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()); @@ -1417,6 +1418,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: From 5cf411680ef35c51ba966fb3079a8082e032f812 Mon Sep 17 00:00:00 2001 From: CGH0S7 <776459475@qq.com> Date: Wed, 20 Aug 2025 01:31:51 +0800 Subject: [PATCH 2/2] =?UTF-8?q?[backend-optpatch]=E5=AF=B9RISCv64ISel.cpp?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=88=A4=E6=96=AD=E6=8F=90=E4=BE=9B=E8=A1=A5?= =?UTF-8?q?=E4=B8=81=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/RISCv64/RISCv64ISel.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/backend/RISCv64/RISCv64ISel.cpp b/src/backend/RISCv64/RISCv64ISel.cpp index 9fccba6..6af4311 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();