[backend]重构了后端
This commit is contained in:
605
src/RISCv64ISel.cpp
Normal file
605
src/RISCv64ISel.cpp
Normal file
@@ -0,0 +1,605 @@
|
||||
#include "RISCv64ISel.h"
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <set>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
RISCv64ISel::RISCv64ISel() : vreg_counter(0), local_label_counter(0) {}
|
||||
|
||||
// 为一个IR Value获取或分配一个新的虚拟寄存器
|
||||
unsigned RISCv64ISel::getVReg(Value* val) {
|
||||
if (!val) { // 安全检查
|
||||
throw std::runtime_error("Cannot get vreg for a null Value.");
|
||||
}
|
||||
if (vreg_map.find(val) == vreg_map.end()) {
|
||||
if (vreg_counter == 0) {
|
||||
// vreg 0 通常保留给物理寄存器x0(zero),我们从1开始分配
|
||||
vreg_counter = 1;
|
||||
}
|
||||
vreg_map[val] = vreg_counter++;
|
||||
}
|
||||
return vreg_map.at(val);
|
||||
}
|
||||
|
||||
// 主入口函数
|
||||
std::unique_ptr<MachineFunction> RISCv64ISel::runOnFunction(Function* func) {
|
||||
F = func;
|
||||
if (!F) return nullptr;
|
||||
MFunc = std::make_unique<MachineFunction>(F->getName());
|
||||
vreg_map.clear();
|
||||
bb_map.clear();
|
||||
vreg_counter = 0;
|
||||
local_label_counter = 0;
|
||||
|
||||
select();
|
||||
|
||||
return std::move(MFunc);
|
||||
}
|
||||
|
||||
// 指令选择主流程
|
||||
void RISCv64ISel::select() {
|
||||
// 1. 为所有基本块创建对应的MachineBasicBlock
|
||||
for (const auto& bb_ptr : F->getBasicBlocks()) {
|
||||
BasicBlock* bb = bb_ptr.get();
|
||||
auto mbb = std::make_unique<MachineBasicBlock>(bb->getName(), MFunc.get());
|
||||
bb_map[bb] = mbb.get();
|
||||
MFunc->addBlock(std::move(mbb));
|
||||
}
|
||||
|
||||
// 2. 为函数参数创建虚拟寄存器
|
||||
// ====================== 已修正 ======================
|
||||
// 根据 IR.h, 参数列表存储在入口基本块中
|
||||
if (F->getEntryBlock()) {
|
||||
for (auto* arg_alloca : F->getEntryBlock()->getArguments()) {
|
||||
getVReg(arg_alloca);
|
||||
}
|
||||
}
|
||||
// =====================================================
|
||||
|
||||
// 3. 遍历每个基本块,生成指令
|
||||
for (const auto& bb_ptr : F->getBasicBlocks()) {
|
||||
selectBasicBlock(bb_ptr.get());
|
||||
}
|
||||
|
||||
// 4. 设置基本块的前驱后继关系
|
||||
for (const auto& bb_ptr : F->getBasicBlocks()) {
|
||||
BasicBlock* bb = bb_ptr.get();
|
||||
CurMBB = bb_map.at(bb);
|
||||
for (auto succ : bb->getSuccessors()) {
|
||||
CurMBB->successors.push_back(bb_map.at(succ));
|
||||
}
|
||||
for (auto pred : bb->getPredecessors()) {
|
||||
CurMBB->predecessors.push_back(bb_map.at(pred));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理单个基本块
|
||||
void RISCv64ISel::selectBasicBlock(BasicBlock* bb) {
|
||||
CurMBB = bb_map.at(bb);
|
||||
auto dag = build_dag(bb);
|
||||
|
||||
std::map<Value*, DAGNode*> value_to_node;
|
||||
for(const auto& node : dag) {
|
||||
if (node->value) {
|
||||
value_to_node[node->value] = node.get();
|
||||
}
|
||||
}
|
||||
|
||||
std::set<DAGNode*> selected_nodes;
|
||||
std::function<void(DAGNode*)> select_recursive =
|
||||
[&](DAGNode* node) {
|
||||
if (!node || selected_nodes.count(node)) return;
|
||||
|
||||
for (auto operand : node->operands) {
|
||||
select_recursive(operand);
|
||||
}
|
||||
|
||||
// 只有当所有操作数都选择完毕后,才选择当前节点
|
||||
selectNode(node);
|
||||
selected_nodes.insert(node);
|
||||
};
|
||||
|
||||
// 按照IR指令的原始顺序来驱动指令选择
|
||||
for (const auto& inst_ptr : bb->getInstructions()) {
|
||||
DAGNode* node_to_select = nullptr;
|
||||
// 查找当前IR指令对应的DAG节点
|
||||
if (value_to_node.count(inst_ptr.get())) {
|
||||
node_to_select = value_to_node.at(inst_ptr.get());
|
||||
} else {
|
||||
// 对于没有返回值的指令或某些特殊情况
|
||||
for(const auto& node : dag) {
|
||||
if(node->value == inst_ptr.get()) {
|
||||
node_to_select = node.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(node_to_select) {
|
||||
select_recursive(node_to_select);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
// 注意:不再生成字符串,而是创建MachineInstr对象并加入到CurMBB
|
||||
switch (node->kind) {
|
||||
case DAGNode::CONSTANT:
|
||||
case DAGNode::ALLOCA_ADDR:
|
||||
// 这些节点本身不生成指令。使用它们的指令会按需处理。
|
||||
// 为Alloca地址分配一个vreg是必要的,代表地址。
|
||||
if (node->value) getVReg(node->value);
|
||||
break;
|
||||
|
||||
case DAGNode::LOAD: {
|
||||
// lw rd, offset(base)
|
||||
auto dest_vreg = getVReg(node->value);
|
||||
auto ptr_vreg = getVReg(node->operands[0]->value);
|
||||
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::LW);
|
||||
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
// 暂时生成0(ptr),后续pass会将其优化为 offset(s0)
|
||||
instr->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(ptr_vreg),
|
||||
std::make_unique<ImmOperand>(0)
|
||||
));
|
||||
CurMBB->addInstruction(std::move(instr));
|
||||
break;
|
||||
}
|
||||
|
||||
case DAGNode::STORE: {
|
||||
// sw rs2, offset(rs1)
|
||||
// 先加载常量
|
||||
if (auto val_const = dynamic_cast<ConstantValue*>(node->operands[0]->value)) {
|
||||
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
||||
li->addOperand(std::make_unique<RegOperand>(getVReg(val_const)));
|
||||
li->addOperand(std::make_unique<ImmOperand>(val_const->getInt()));
|
||||
CurMBB->addInstruction(std::move(li));
|
||||
}
|
||||
|
||||
auto val_vreg = getVReg(node->operands[0]->value);
|
||||
auto ptr_vreg = getVReg(node->operands[1]->value);
|
||||
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SW);
|
||||
instr->addOperand(std::make_unique<RegOperand>(val_vreg)); // value to store
|
||||
instr->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(ptr_vreg), // base address
|
||||
std::make_unique<ImmOperand>(0) // offset
|
||||
));
|
||||
CurMBB->addInstruction(std::move(instr));
|
||||
break;
|
||||
}
|
||||
|
||||
case DAGNode::BINARY: {
|
||||
auto bin = dynamic_cast<BinaryInst*>(node->value);
|
||||
if (!bin) break;
|
||||
|
||||
Value* lhs = bin->getLhs();
|
||||
Value* rhs = bin->getRhs();
|
||||
|
||||
// 检查是否为 addi 优化
|
||||
if (bin->getKind() == BinaryInst::kAdd) {
|
||||
if (auto rhs_const = dynamic_cast<ConstantValue*>(rhs)) {
|
||||
if (rhs_const->getInt() >= -2048 && rhs_const->getInt() < 2048) {
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::ADDIW);
|
||||
instr->addOperand(std::make_unique<RegOperand>(getVReg(bin)));
|
||||
instr->addOperand(std::make_unique<RegOperand>(getVReg(lhs)));
|
||||
instr->addOperand(std::make_unique<ImmOperand>(rhs_const->getInt()));
|
||||
CurMBB->addInstruction(std::move(instr));
|
||||
return; // 指令已生成,提前返回
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 为操作数加载立即数或地址
|
||||
auto load_val_if_const = [&](Value* val) {
|
||||
if (auto c = dynamic_cast<ConstantValue*>(val)) {
|
||||
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
||||
li->addOperand(std::make_unique<RegOperand>(getVReg(c)));
|
||||
li->addOperand(std::make_unique<ImmOperand>(c->getInt()));
|
||||
CurMBB->addInstruction(std::move(li));
|
||||
} else if (auto g = dynamic_cast<GlobalValue*>(val)) {
|
||||
auto la = std::make_unique<MachineInstr>(RVOpcodes::LA);
|
||||
la->addOperand(std::make_unique<RegOperand>(getVReg(g)));
|
||||
la->addOperand(std::make_unique<LabelOperand>(g->getName()));
|
||||
CurMBB->addInstruction(std::move(la));
|
||||
}
|
||||
};
|
||||
load_val_if_const(lhs);
|
||||
load_val_if_const(rhs);
|
||||
|
||||
auto dest_vreg = getVReg(bin);
|
||||
auto lhs_vreg = getVReg(lhs);
|
||||
auto rhs_vreg = getVReg(rhs);
|
||||
|
||||
// 生成二元运算指令
|
||||
switch (bin->getKind()) {
|
||||
case BinaryInst::kAdd: {
|
||||
RVOpcodes opcode = (lhs->getType()->isPointer() || rhs->getType()->isPointer()) ? RVOpcodes::ADD : RVOpcodes::ADDW;
|
||||
auto instr = std::make_unique<MachineInstr>(opcode);
|
||||
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::kSub: {
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
|
||||
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::kMul: {
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::MULW);
|
||||
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));
|
||||
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
|
||||
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
|
||||
CurMBB->addInstruction(std::move(instr));
|
||||
break;
|
||||
}
|
||||
case Instruction::kRem: {
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::REMW);
|
||||
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::kICmpEQ: {
|
||||
auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
|
||||
sub->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
sub->addOperand(std::make_unique<RegOperand>(lhs_vreg));
|
||||
sub->addOperand(std::make_unique<RegOperand>(rhs_vreg));
|
||||
CurMBB->addInstruction(std::move(sub));
|
||||
|
||||
auto seqz = std::make_unique<MachineInstr>(RVOpcodes::SEQZ);
|
||||
seqz->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
seqz->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
CurMBB->addInstruction(std::move(seqz));
|
||||
break;
|
||||
}
|
||||
case BinaryInst::kICmpNE: {
|
||||
auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
|
||||
sub->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
sub->addOperand(std::make_unique<RegOperand>(lhs_vreg));
|
||||
sub->addOperand(std::make_unique<RegOperand>(rhs_vreg));
|
||||
CurMBB->addInstruction(std::move(sub));
|
||||
|
||||
auto snez = std::make_unique<MachineInstr>(RVOpcodes::SNEZ);
|
||||
snez->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
snez->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
CurMBB->addInstruction(std::move(snez));
|
||||
break;
|
||||
}
|
||||
case BinaryInst::kICmpLT: {
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SLT);
|
||||
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::kICmpGT: {
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SLT);
|
||||
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg)); // Swapped
|
||||
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg)); // Swapped
|
||||
CurMBB->addInstruction(std::move(instr));
|
||||
break;
|
||||
}
|
||||
case BinaryInst::kICmpLE: {
|
||||
auto slt = std::make_unique<MachineInstr>(RVOpcodes::SLT);
|
||||
slt->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
slt->addOperand(std::make_unique<RegOperand>(rhs_vreg)); // Swapped
|
||||
slt->addOperand(std::make_unique<RegOperand>(lhs_vreg)); // Swapped
|
||||
CurMBB->addInstruction(std::move(slt));
|
||||
|
||||
auto xori = std::make_unique<MachineInstr>(RVOpcodes::XORI);
|
||||
xori->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
xori->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
xori->addOperand(std::make_unique<ImmOperand>(1));
|
||||
CurMBB->addInstruction(std::move(xori));
|
||||
break;
|
||||
}
|
||||
case BinaryInst::kICmpGE: {
|
||||
auto slt = std::make_unique<MachineInstr>(RVOpcodes::SLT);
|
||||
slt->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
slt->addOperand(std::make_unique<RegOperand>(lhs_vreg));
|
||||
slt->addOperand(std::make_unique<RegOperand>(rhs_vreg));
|
||||
CurMBB->addInstruction(std::move(slt));
|
||||
|
||||
auto xori = std::make_unique<MachineInstr>(RVOpcodes::XORI);
|
||||
xori->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
xori->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
xori->addOperand(std::make_unique<ImmOperand>(1));
|
||||
CurMBB->addInstruction(std::move(xori));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("Unsupported binary instruction in ISel");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DAGNode::UNARY: {
|
||||
auto unary = dynamic_cast<UnaryInst*>(node->value);
|
||||
if (!unary) break;
|
||||
|
||||
auto dest_vreg = getVReg(unary);
|
||||
auto src_vreg = getVReg(unary->getOperand());
|
||||
|
||||
switch (unary->getKind()) {
|
||||
case UnaryInst::kNeg: {
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
|
||||
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO)); // x0
|
||||
instr->addOperand(std::make_unique<RegOperand>(src_vreg));
|
||||
CurMBB->addInstruction(std::move(instr));
|
||||
break;
|
||||
}
|
||||
case UnaryInst::kNot: {
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SEQZ);
|
||||
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
instr->addOperand(std::make_unique<RegOperand>(src_vreg));
|
||||
CurMBB->addInstruction(std::move(instr));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error("Unsupported unary instruction in ISel");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DAGNode::CALL: {
|
||||
auto call = dynamic_cast<CallInst*>(node->value);
|
||||
if (!call) break;
|
||||
|
||||
// 在此阶段,我们只处理函数调用本身和返回值的移动
|
||||
// 参数的传递将在一个专门的 Calling Convention Pass 中处理
|
||||
|
||||
auto call_instr = std::make_unique<MachineInstr>(RVOpcodes::CALL);
|
||||
call_instr->addOperand(std::make_unique<LabelOperand>(call->getCallee()->getName()));
|
||||
CurMBB->addInstruction(std::move(call_instr));
|
||||
|
||||
if (!call->getType()->isVoid()) {
|
||||
auto mv_instr = std::make_unique<MachineInstr>(RVOpcodes::MV);
|
||||
mv_instr->addOperand(std::make_unique<RegOperand>(getVReg(call))); // dest
|
||||
mv_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0)); // src
|
||||
CurMBB->addInstruction(std::move(mv_instr));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DAGNode::RETURN: {
|
||||
auto ret_inst = dynamic_cast<ReturnInst*>(node->value);
|
||||
if (ret_inst && ret_inst->hasReturnValue()) {
|
||||
// 如果有返回值,生成一条mv指令将其放入a0
|
||||
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_inst->getReturnValue())));
|
||||
CurMBB->addInstruction(std::move(mv_instr));
|
||||
}
|
||||
// 生成ret伪指令
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::RET);
|
||||
CurMBB->addInstruction(std::move(instr));
|
||||
break;
|
||||
}
|
||||
|
||||
case DAGNode::BRANCH: {
|
||||
if (auto cond_br = dynamic_cast<CondBrInst*>(node->value)) {
|
||||
// bne cond, x0, then_block
|
||||
auto br_instr = std::make_unique<MachineInstr>(RVOpcodes::BNE);
|
||||
br_instr->addOperand(std::make_unique<RegOperand>(getVReg(cond_br->getCondition())));
|
||||
br_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
|
||||
br_instr->addOperand(std::make_unique<LabelOperand>(cond_br->getThenBlock()->getName()));
|
||||
CurMBB->addInstruction(std::move(br_instr));
|
||||
|
||||
// j else_block
|
||||
// 注意:这里会产生一个fallthrough问题,后续的分支优化pass会解决它
|
||||
// 一个更健壮的生成方式是 bne -> j else; then: ...; else: ...
|
||||
} else if (auto uncond_br = dynamic_cast<UncondBrInst*>(node->value)) {
|
||||
auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J);
|
||||
j_instr->addOperand(std::make_unique<LabelOperand>(uncond_br->getBlock()->getName()));
|
||||
CurMBB->addInstruction(std::move(j_instr));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DAGNode::MEMSET: {
|
||||
// 这是对原memset逻辑的完整LLIR翻译
|
||||
auto memset = dynamic_cast<MemsetInst*>(node->value);
|
||||
if (!memset) break;
|
||||
|
||||
auto r_dest_addr = getVReg(memset->getPointer());
|
||||
auto r_num_bytes = getVReg(memset->getSize());
|
||||
auto r_value_byte = getVReg(memset->getValue());
|
||||
|
||||
// 为临时值创建虚拟寄存器
|
||||
auto r_counter = vreg_counter++;
|
||||
auto r_end_addr = vreg_counter++;
|
||||
auto r_current_addr = vreg_counter++;
|
||||
auto r_temp_val = vreg_counter++;
|
||||
|
||||
auto add_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, unsigned rs2) {
|
||||
auto i = std::make_unique<MachineInstr>(op);
|
||||
i->addOperand(std::make_unique<RegOperand>(rd));
|
||||
i->addOperand(std::make_unique<RegOperand>(rs1));
|
||||
i->addOperand(std::make_unique<RegOperand>(rs2));
|
||||
CurMBB->addInstruction(std::move(i));
|
||||
};
|
||||
auto addi_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, int64_t imm) {
|
||||
auto i = std::make_unique<MachineInstr>(op);
|
||||
i->addOperand(std::make_unique<RegOperand>(rd));
|
||||
i->addOperand(std::make_unique<RegOperand>(rs1));
|
||||
i->addOperand(std::make_unique<ImmOperand>(imm));
|
||||
CurMBB->addInstruction(std::move(i));
|
||||
};
|
||||
auto store_instr = [&](RVOpcodes op, unsigned src, unsigned base, int64_t off) {
|
||||
auto i = std::make_unique<MachineInstr>(op);
|
||||
i->addOperand(std::make_unique<RegOperand>(src));
|
||||
i->addOperand(std::make_unique<MemOperand>(std::make_unique<RegOperand>(base), std::make_unique<ImmOperand>(off)));
|
||||
CurMBB->addInstruction(std::move(i));
|
||||
};
|
||||
auto branch_instr = [&](RVOpcodes op, unsigned rs1, unsigned rs2, const std::string& label) {
|
||||
auto i = std::make_unique<MachineInstr>(op);
|
||||
i->addOperand(std::make_unique<RegOperand>(rs1));
|
||||
i->addOperand(std::make_unique<RegOperand>(rs2));
|
||||
i->addOperand(std::make_unique<LabelOperand>(label));
|
||||
CurMBB->addInstruction(std::move(i));
|
||||
};
|
||||
auto jump_instr = [&](const std::string& label) {
|
||||
auto i = std::make_unique<MachineInstr>(RVOpcodes::J);
|
||||
i->addOperand(std::make_unique<LabelOperand>(label));
|
||||
CurMBB->addInstruction(std::move(i));
|
||||
};
|
||||
auto label_instr = [&](const std::string& name) {
|
||||
auto i = std::make_unique<MachineInstr>(RVOpcodes::LABEL);
|
||||
i->addOperand(std::make_unique<LabelOperand>(name));
|
||||
CurMBB->addInstruction(std::move(i));
|
||||
};
|
||||
|
||||
int unique_id = this->local_label_counter++;
|
||||
std::string loop_start_label = "memset_loop_start_" + std::to_string(unique_id);
|
||||
std::string loop_end_label = "memset_loop_end_" + std::to_string(unique_id);
|
||||
std::string remainder_label = "memset_remainder_" + std::to_string(unique_id);
|
||||
std::string done_label = "memset_done_" + std::to_string(unique_id);
|
||||
|
||||
// 构造64位的填充值
|
||||
addi_instr(RVOpcodes::ANDI, r_temp_val, r_value_byte, 255);
|
||||
addi_instr(RVOpcodes::SLLI, r_value_byte, r_temp_val, 8);
|
||||
add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte);
|
||||
addi_instr(RVOpcodes::SLLI, r_value_byte, r_temp_val, 16);
|
||||
add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte);
|
||||
addi_instr(RVOpcodes::SLLI, r_value_byte, r_temp_val, 32);
|
||||
add_instr(RVOpcodes::OR, r_temp_val, r_temp_val, r_value_byte);
|
||||
|
||||
// 设置循环变量
|
||||
add_instr(RVOpcodes::ADD, r_end_addr, r_dest_addr, r_num_bytes);
|
||||
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
|
||||
mv->addOperand(std::make_unique<RegOperand>(r_current_addr));
|
||||
mv->addOperand(std::make_unique<RegOperand>(r_dest_addr));
|
||||
CurMBB->addInstruction(std::move(mv));
|
||||
addi_instr(RVOpcodes::ANDI, r_counter, r_num_bytes, -8);
|
||||
add_instr(RVOpcodes::ADD, r_counter, r_dest_addr, r_counter);
|
||||
|
||||
// 64位写入循环
|
||||
label_instr(loop_start_label);
|
||||
branch_instr(RVOpcodes::BGEU, r_current_addr, r_counter, loop_end_label);
|
||||
store_instr(RVOpcodes::SD, r_temp_val, r_current_addr, 0);
|
||||
addi_instr(RVOpcodes::ADDI, r_current_addr, r_current_addr, 8);
|
||||
jump_instr(loop_start_label);
|
||||
label_instr(loop_end_label);
|
||||
|
||||
// 剩余字节写入循环
|
||||
label_instr(remainder_label);
|
||||
branch_instr(RVOpcodes::BGEU, r_current_addr, r_end_addr, done_label);
|
||||
store_instr(RVOpcodes::SB, r_temp_val, r_current_addr, 0);
|
||||
addi_instr(RVOpcodes::ADDI, r_current_addr, r_current_addr, 1);
|
||||
jump_instr(remainder_label);
|
||||
label_instr(done_label);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw std::runtime_error("Unsupported DAGNode kind in ISel: " + std::to_string(node->kind));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- DAG构建函数 (从原RISCv64Backend.cpp几乎原样迁移, 保持不变) ---
|
||||
RISCv64ISel::DAGNode* RISCv64ISel::create_node(DAGNode::NodeKind kind, Value* val, std::map<Value*, DAGNode*>& value_to_node, std::vector<std::unique_ptr<DAGNode>>& nodes_storage) {
|
||||
if (val && value_to_node.count(val) && kind != DAGNode::STORE && kind != DAGNode::RETURN && kind != DAGNode::BRANCH && kind != DAGNode::MEMSET) {
|
||||
return value_to_node[val];
|
||||
}
|
||||
auto node = std::make_unique<DAGNode>(kind);
|
||||
node->value = val;
|
||||
DAGNode* raw_node_ptr = node.get();
|
||||
nodes_storage.push_back(std::move(node));
|
||||
// 只有产生值的节点才应该被记录,以备复用
|
||||
if (val && !val->getType()->isVoid() && dynamic_cast<Instruction*>(val)) {
|
||||
value_to_node[val] = raw_node_ptr;
|
||||
} else if (val && dynamic_cast<GlobalValue*>(val)) {
|
||||
value_to_node[val] = raw_node_ptr;
|
||||
}
|
||||
return raw_node_ptr;
|
||||
}
|
||||
|
||||
RISCv64ISel::DAGNode* RISCv64ISel::get_operand_node(Value* val_ir, std::map<Value*, DAGNode*>& value_to_node, std::vector<std::unique_ptr<DAGNode>>& nodes_storage) {
|
||||
if (value_to_node.count(val_ir)) {
|
||||
return value_to_node[val_ir];
|
||||
} else if (dynamic_cast<ConstantValue*>(val_ir)) {
|
||||
return create_node(DAGNode::CONSTANT, val_ir, value_to_node, nodes_storage);
|
||||
} else if (dynamic_cast<GlobalValue*>(val_ir)) {
|
||||
return create_node(DAGNode::CONSTANT, val_ir, value_to_node, nodes_storage);
|
||||
} else if (dynamic_cast<AllocaInst*>(val_ir)) {
|
||||
return create_node(DAGNode::ALLOCA_ADDR, val_ir, value_to_node, nodes_storage);
|
||||
}
|
||||
// Fallback: Assume it needs to be loaded if not found (might be a parameter or a value from another block)
|
||||
return create_node(DAGNode::LOAD, val_ir, value_to_node, nodes_storage);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicBlock* bb) {
|
||||
std::vector<std::unique_ptr<DAGNode>> nodes_storage;
|
||||
std::map<Value*, DAGNode*> value_to_node;
|
||||
|
||||
for (const auto& inst_ptr : bb->getInstructions()) {
|
||||
Instruction* inst = inst_ptr.get();
|
||||
if (auto alloca = dynamic_cast<AllocaInst*>(inst)) {
|
||||
create_node(DAGNode::ALLOCA_ADDR, alloca, value_to_node, nodes_storage);
|
||||
} else if (auto store = dynamic_cast<StoreInst*>(inst)) {
|
||||
auto store_node = create_node(DAGNode::STORE, store, value_to_node, nodes_storage);
|
||||
store_node->operands.push_back(get_operand_node(store->getValue(), value_to_node, nodes_storage));
|
||||
store_node->operands.push_back(get_operand_node(store->getPointer(), value_to_node, nodes_storage));
|
||||
} else if (auto memset = dynamic_cast<MemsetInst*>(inst)) {
|
||||
auto memset_node = create_node(DAGNode::MEMSET, memset, value_to_node, nodes_storage);
|
||||
memset_node->operands.push_back(get_operand_node(memset->getPointer(), value_to_node, nodes_storage));
|
||||
memset_node->operands.push_back(get_operand_node(memset->getBegin(), value_to_node, nodes_storage));
|
||||
memset_node->operands.push_back(get_operand_node(memset->getSize(), value_to_node, nodes_storage));
|
||||
memset_node->operands.push_back(get_operand_node(memset->getValue(), value_to_node, nodes_storage));
|
||||
}
|
||||
else if (auto load = dynamic_cast<LoadInst*>(inst)) {
|
||||
auto load_node = create_node(DAGNode::LOAD, load, value_to_node, nodes_storage);
|
||||
load_node->operands.push_back(get_operand_node(load->getPointer(), value_to_node, nodes_storage));
|
||||
} else if (auto bin = dynamic_cast<BinaryInst*>(inst)) {
|
||||
if(value_to_node.count(bin)) continue;
|
||||
auto bin_node = create_node(DAGNode::BINARY, bin, value_to_node, nodes_storage);
|
||||
bin_node->operands.push_back(get_operand_node(bin->getLhs(), value_to_node, nodes_storage));
|
||||
bin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
|
||||
} else if (auto un = dynamic_cast<UnaryInst*>(inst)) {
|
||||
if(value_to_node.count(un)) continue;
|
||||
auto unary_node = create_node(DAGNode::UNARY, un, value_to_node, nodes_storage);
|
||||
unary_node->operands.push_back(get_operand_node(un->getOperand(), value_to_node, nodes_storage));
|
||||
}
|
||||
else if (auto call = dynamic_cast<CallInst*>(inst)) {
|
||||
if(value_to_node.count(call)) continue;
|
||||
auto call_node = create_node(DAGNode::CALL, call, value_to_node, nodes_storage);
|
||||
for (auto arg : call->getArguments()) {
|
||||
call_node->operands.push_back(get_operand_node(arg->getValue(), value_to_node, nodes_storage));
|
||||
}
|
||||
} else if (auto ret = dynamic_cast<ReturnInst*>(inst)) {
|
||||
auto ret_node = create_node(DAGNode::RETURN, ret, value_to_node, nodes_storage);
|
||||
if (ret->hasReturnValue()) {
|
||||
ret_node->operands.push_back(get_operand_node(ret->getReturnValue(), value_to_node, nodes_storage));
|
||||
}
|
||||
} else if (auto cond_br = dynamic_cast<CondBrInst*>(inst)) {
|
||||
auto br_node = create_node(DAGNode::BRANCH, cond_br, value_to_node, nodes_storage);
|
||||
br_node->operands.push_back(get_operand_node(cond_br->getCondition(), value_to_node, nodes_storage));
|
||||
} else if (auto uncond_br = dynamic_cast<UncondBrInst*>(inst)) {
|
||||
create_node(DAGNode::BRANCH, uncond_br, value_to_node, nodes_storage);
|
||||
}
|
||||
}
|
||||
return nodes_storage;
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
Reference in New Issue
Block a user