Merge branch 'backend-O1-1' into backend

This commit is contained in:
Lixuanwang
2025-08-20 02:52:21 +08:00
24 changed files with 530 additions and 327 deletions

View File

@@ -103,6 +103,81 @@ void RISCv64ISel::select() {
}
}
// 仅当函数满足特定条件时,才需要保存参数寄存器,应用更精细的过滤规则
// 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<CallInst*>(inst.get()) || dynamic_cast<AllocaInst*>(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();
CurMBB = bb_map.at(first_ir_block);
int int_arg_idx = 0;
int fp_arg_idx = 0;
for (Argument* arg : F->getArguments()) {
Type* arg_type = arg->getType();
// --- 处理整数/指针参数 ---
if (!arg_type->isFloat() && int_arg_idx < 8) {
// 1. 获取参数原始的、将被预着色为 a0-a7 的 vreg
unsigned original_vreg = getVReg(arg);
// 2. 创建一个新的、安全的 vreg 来持有参数的值
unsigned saved_vreg = getNewVReg(arg_type);
// 3. 生成 mv saved_vreg, original_vreg 指令
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(saved_vreg));
mv->addOperand(std::make_unique<RegOperand>(original_vreg));
CurMBB->addInstruction(std::move(mv));
MFunc->addProtectedArgumentVReg(saved_vreg);
// 4.【关键】更新vreg映射表将arg的vreg指向新的、安全的vreg
// 这样,后续所有对该参数的 getVReg(arg) 调用都会自动获得 saved_vreg
// 使得函数体内的代码都使用这个被保存过的值。
vreg_map[arg] = saved_vreg;
int_arg_idx++;
}
// --- 处理浮点参数 ---
else if (arg_type->isFloat() && fp_arg_idx < 8) {
unsigned original_vreg = getVReg(arg);
unsigned saved_vreg = getNewVReg(arg_type);
// 对于浮点数,使用 fmv.s 指令
auto fmv = std::make_unique<MachineInstr>(RVOpcodes::FMV_S);
fmv->addOperand(std::make_unique<RegOperand>(saved_vreg));
fmv->addOperand(std::make_unique<RegOperand>(original_vreg));
CurMBB->addInstruction(std::move(fmv));
MFunc->addProtectedArgumentVReg(saved_vreg);
vreg_map[arg] = saved_vreg;
fp_arg_idx++;
}
// 对于栈传递的参数,则无需处理
}
}
}
// 遍历基本块,进行指令选择
for (const auto& bb_ptr : F->getBasicBlocks()) {
selectBasicBlock(bb_ptr.get());
@@ -501,6 +576,14 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(instr));
break;
}
case BinaryInst::kMulh: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::MULH);
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::kDiv: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::DIVW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
@@ -612,6 +695,22 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(xori));
break;
}
case BinaryInst::kAnd: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::AND);
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 BinaryInst::kOr: {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::OR);
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;
}
default:
throw std::runtime_error("Unsupported binary instruction in ISel");
}
@@ -1257,6 +1356,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
auto gep = dynamic_cast<GetElementPtrInst*>(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());
@@ -1363,6 +1463,106 @@ void RISCv64ISel::selectNode(DAGNode* node) {
final_mv->addOperand(std::make_unique<RegOperand>(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<AllocaInst*>(base_ptr_val)) {
last_step_addr_vreg = getNewVReg(gep->getType());
auto frame_addr_instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_ADDR);
frame_addr_instr->addOperand(std::make_unique<RegOperand>(last_step_addr_vreg));
frame_addr_instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca_base)));
CurMBB->addInstruction(std::move(frame_addr_instr));
} else if (auto global_base = dynamic_cast<GlobalValue*>(base_ptr_val)) {
last_step_addr_vreg = getNewVReg(gep->getType());
auto la_instr = std::make_unique<MachineInstr>(RVOpcodes::LA);
la_instr->addOperand(std::make_unique<RegOperand>(last_step_addr_vreg));
la_instr->addOperand(std::make_unique<LabelOperand>(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<PointerType>()->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<ConstantValue*>(indexValue)) {
index_vreg = getNewVReg(Type::getIntType());
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(index_vreg));
li->addOperand(std::make_unique<ImmOperand>(const_index->getInt()));
CurMBB->addInstruction(std::move(li));
} else {
index_vreg = getVReg(indexValue);
}
if (stride == 1) {
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(offset_vreg));
mv->addOperand(std::make_unique<RegOperand>(index_vreg));
CurMBB->addInstruction(std::move(mv));
} else {
auto size_vreg = getNewVReg(Type::getIntType());
auto li_size = std::make_unique<MachineInstr>(RVOpcodes::LI);
li_size->addOperand(std::make_unique<RegOperand>(size_vreg));
li_size->addOperand(std::make_unique<ImmOperand>(stride));
CurMBB->addInstruction(std::move(li_size));
auto mul = std::make_unique<MachineInstr>(RVOpcodes::MULW);
mul->addOperand(std::make_unique<RegOperand>(offset_vreg));
mul->addOperand(std::make_unique<RegOperand>(index_vreg));
mul->addOperand(std::make_unique<RegOperand>(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<MachineInstr>(RVOpcodes::ADD);
add->addOperand(std::make_unique<RegOperand>(current_step_addr_vreg));
add->addOperand(std::make_unique<RegOperand>(last_step_addr_vreg));
add->addOperand(std::make_unique<RegOperand>(offset_vreg));
CurMBB->addInstruction(std::move(add));
// 本次的结果成为下一次计算的输入。
last_step_addr_vreg = current_step_addr_vreg;
}
// --- 为下一次迭代更新类型 ---
if (auto array_type = current_type->as<ArrayType>()) {
current_type = array_type->getElementType();
} else if (auto ptr_type = current_type->as<PointerType>()) {
current_type = ptr_type->getBaseType();
}
}
// --- Step 3: 将最终计算出的地址存入GEP的目标虚拟寄存器 ---
auto final_mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
final_mv->addOperand(std::make_unique<RegOperand>(result_vreg));
final_mv->addOperand(std::make_unique<RegOperand>(last_step_addr_vreg));
CurMBB->addInstruction(std::move(final_mv));
break;
}
}
default: