[backend-llir]修复了许多重构的bug

This commit is contained in:
Lixuanwang
2025-07-19 17:50:14 +08:00
parent d4a6996d74
commit 9528335a04
11 changed files with 513 additions and 497 deletions

View File

@@ -1,22 +1,32 @@
#include "RISCv64ISel.h"
#include <stdexcept>
#include <iostream>
#include <functional>
#include <set>
#include <functional>
#include <cmath> // For std::fabs
#include <limits> // For std::numeric_limits
namespace sysy {
// DAG节点定义 (内部实现)
struct RISCv64ISel::DAGNode {
enum NodeKind { CONSTANT, LOAD, STORE, BINARY, CALL, RETURN, BRANCH, ALLOCA_ADDR, UNARY, MEMSET };
NodeKind kind;
Value* value = nullptr;
std::vector<DAGNode*> operands;
std::vector<DAGNode*> users;
DAGNode(NodeKind k) : kind(k) {}
};
RISCv64ISel::RISCv64ISel() : vreg_counter(0), local_label_counter(0) {}
// 为一个IR Value获取或分配一个新的虚拟寄存器
unsigned RISCv64ISel::getVReg(Value* val) {
if (!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_counter = 1; // vreg 0 保留
}
vreg_map[val] = vreg_counter++;
}
@@ -27,7 +37,7 @@ unsigned RISCv64ISel::getVReg(Value* val) {
std::unique_ptr<MachineFunction> RISCv64ISel::runOnFunction(Function* func) {
F = func;
if (!F) return nullptr;
MFunc = std::make_unique<MachineFunction>(F->getName());
MFunc = std::make_unique<MachineFunction>(F, this);
vreg_map.clear();
bb_map.clear();
vreg_counter = 0;
@@ -40,37 +50,28 @@ std::unique_ptr<MachineFunction> RISCv64ISel::runOnFunction(Function* func) {
// 指令选择主流程
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();
auto mbb = std::make_unique<MachineBasicBlock>(bb_ptr->getName(), MFunc.get());
bb_map[bb_ptr.get()] = 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 = bb_map.at(bb_ptr.get());
for (auto succ : bb_ptr->getSuccessors()) {
CurMBB->successors.push_back(bb_map.at(succ));
}
for (auto pred : bb->getPredecessors()) {
for (auto pred : bb_ptr->getPredecessors()) {
CurMBB->predecessors.push_back(bb_map.at(pred));
}
}
@@ -87,29 +88,23 @@ void RISCv64ISel::selectBasicBlock(BasicBlock* bb) {
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();
@@ -123,88 +118,105 @@ void RISCv64ISel::selectBasicBlock(BasicBlock* bb) {
}
}
// 核心函数为DAG节点选择并生成MachineInstr (忠实移植版)
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);
Value* ptr_val = 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));
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_LOAD);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca)));
CurMBB->addInstruction(std::move(instr));
} else if (auto global = dynamic_cast<GlobalValue*>(ptr_val)) {
auto addr_vreg = getNewVReg();
auto la = std::make_unique<MachineInstr>(RVOpcodes::LA);
la->addOperand(std::make_unique<RegOperand>(addr_vreg));
la->addOperand(std::make_unique<LabelOperand>(global->getName()));
CurMBB->addInstruction(std::move(la));
auto lw = std::make_unique<MachineInstr>(RVOpcodes::LW);
lw->addOperand(std::make_unique<RegOperand>(dest_vreg));
lw->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(lw));
} else {
auto ptr_vreg = getVReg(ptr_val);
auto lw = std::make_unique<MachineInstr>(RVOpcodes::LW);
lw->addOperand(std::make_unique<RegOperand>(dest_vreg));
lw->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(ptr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(lw));
}
break;
}
case DAGNode::STORE: {
// sw rs2, offset(rs1)
// 先加载常量
if (auto val_const = dynamic_cast<ConstantValue*>(node->operands[0]->value)) {
Value* val_to_store = node->operands[0]->value;
Value* ptr_val = node->operands[1]->value;
if (auto val_const = dynamic_cast<ConstantValue*>(val_to_store)) {
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(val_to_store);
auto val_vreg = getVReg(node->operands[0]->value);
auto ptr_vreg = getVReg(node->operands[1]->value);
if (auto alloca = dynamic_cast<AllocaInst*>(ptr_val)) {
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_STORE);
instr->addOperand(std::make_unique<RegOperand>(val_vreg));
instr->addOperand(std::make_unique<RegOperand>(getVReg(alloca)));
CurMBB->addInstruction(std::move(instr));
} else if (auto global = dynamic_cast<GlobalValue*>(ptr_val)) {
auto addr_vreg = getNewVReg();
auto la = std::make_unique<MachineInstr>(RVOpcodes::LA);
la->addOperand(std::make_unique<RegOperand>(addr_vreg));
la->addOperand(std::make_unique<LabelOperand>(global->getName()));
CurMBB->addInstruction(std::move(la));
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));
auto sw = std::make_unique<MachineInstr>(RVOpcodes::SW);
sw->addOperand(std::make_unique<RegOperand>(val_vreg));
sw->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(addr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(sw));
} else {
auto ptr_vreg = getVReg(ptr_val);
auto sw = std::make_unique<MachineInstr>(RVOpcodes::SW);
sw->addOperand(std::make_unique<RegOperand>(val_vreg));
sw->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(ptr_vreg),
std::make_unique<ImmOperand>(0)
));
CurMBB->addInstruction(std::move(sw));
}
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);
@@ -214,7 +226,19 @@ void RISCv64ISel::selectNode(DAGNode* node) {
auto lhs_vreg = getVReg(lhs);
auto rhs_vreg = getVReg(rhs);
// 生成二元运算指令
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>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<ImmOperand>(rhs_const->getInt()));
CurMBB->addInstruction(std::move(instr));
return;
}
}
}
switch (bin->getKind()) {
case BinaryInst::kAdd: {
RVOpcodes opcode = (lhs->getType()->isPointer() || rhs->getType()->isPointer()) ? RVOpcodes::ADD : RVOpcodes::ADDW;
@@ -294,16 +318,16 @@ void RISCv64ISel::selectNode(DAGNode* node) {
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
instr->addOperand(std::make_unique<RegOperand>(rhs_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
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
slt->addOperand(std::make_unique<RegOperand>(rhs_vreg));
slt->addOperand(std::make_unique<RegOperand>(lhs_vreg));
CurMBB->addInstruction(std::move(slt));
auto xori = std::make_unique<MachineInstr>(RVOpcodes::XORI);
@@ -335,8 +359,6 @@ void RISCv64ISel::selectNode(DAGNode* node) {
case DAGNode::UNARY: {
auto unary = dynamic_cast<UnaryInst*>(node->value);
if (!unary) break;
auto dest_vreg = getVReg(unary);
auto src_vreg = getVReg(unary->getOperand());
@@ -344,7 +366,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
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>(PhysicalReg::ZERO));
instr->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(instr));
break;
@@ -364,51 +386,67 @@ void RISCv64ISel::selectNode(DAGNode* node) {
case DAGNode::CALL: {
auto call = dynamic_cast<CallInst*>(node->value);
if (!call) break;
for (size_t i = 0; i < node->operands.size() && i < 8; ++i) {
DAGNode* arg_node = node->operands[i];
auto arg_preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + i);
if (arg_node->kind == DAGNode::CONSTANT) {
if (auto const_val = dynamic_cast<ConstantValue*>(arg_node->value)) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(arg_preg));
li->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li));
}
} else {
auto src_vreg = getVReg(arg_node->value);
auto mv = std::make_unique<MachineInstr>(RVOpcodes::MV);
mv->addOperand(std::make_unique<RegOperand>(arg_preg));
mv->addOperand(std::make_unique<RegOperand>(src_vreg));
CurMBB->addInstruction(std::move(mv));
}
}
// 在此阶段,我们只处理函数调用本身和返回值的移动
// 参数的传递将在一个专门的 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
mv_instr->addOperand(std::make_unique<RegOperand>(getVReg(call)));
mv_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
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));
auto ret_inst_ir = dynamic_cast<ReturnInst*>(node->value);
if (ret_inst_ir && ret_inst_ir->hasReturnValue()) {
Value* ret_val = ret_inst_ir->getReturnValue();
if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) {
auto li_instr = std::make_unique<MachineInstr>(RVOpcodes::LI);
li_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
li_instr->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
CurMBB->addInstruction(std::move(li_instr));
} else {
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_val)));
CurMBB->addInstruction(std::move(mv_instr));
}
}
// 生成ret伪指令
auto instr = std::make_unique<MachineInstr>(RVOpcodes::RET);
CurMBB->addInstruction(std::move(instr));
auto ret_mi = std::make_unique<MachineInstr>(RVOpcodes::RET);
CurMBB->addInstruction(std::move(ret_mi));
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()));
@@ -416,20 +454,16 @@ void RISCv64ISel::selectNode(DAGNode* node) {
}
break;
}
case DAGNode::MEMSET: {
// 这是对原memset逻辑的完整LLIR翻译
auto memset = dynamic_cast<MemsetInst*>(node->value);
if (!memset) break;
case DAGNode::MEMSET: {
auto memset = dynamic_cast<MemsetInst*>(node->value);
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 r_counter = getNewVReg();
auto r_end_addr = getNewVReg();
auto r_current_addr = getNewVReg();
auto r_temp_val = getNewVReg();
auto add_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, unsigned rs2) {
auto i = std::make_unique<MachineInstr>(op);
@@ -470,12 +504,11 @@ void RISCv64ISel::selectNode(DAGNode* node) {
};
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位的填充值
std::string loop_start_label = MFunc->getName() + "_memset_loop_start_" + std::to_string(unique_id);
std::string loop_end_label = MFunc->getName() + "_memset_loop_end_" + std::to_string(unique_id);
std::string remainder_label = MFunc->getName() + "_memset_remainder_" + std::to_string(unique_id);
std::string done_label = MFunc->getName() + "_memset_done_" + std::to_string(unique_id);
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);
@@ -483,8 +516,6 @@ void RISCv64ISel::selectNode(DAGNode* node) {
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));
@@ -492,16 +523,12 @@ void RISCv64ISel::selectNode(DAGNode* node) {
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);
@@ -512,13 +539,13 @@ void RISCv64ISel::selectNode(DAGNode* node) {
}
default:
throw std::runtime_error("Unsupported DAGNode kind in ISel: " + std::to_string(node->kind));
throw std::runtime_error("Unsupported DAGNode kind in ISel");
}
}
// --- 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) {
// 以下是忠实移植的DAG构建函数
RISCv64ISel::DAGNode* RISCv64ISel::create_node(int kind_int, Value* val, std::map<Value*, DAGNode*>& value_to_node, std::vector<std::unique_ptr<DAGNode>>& nodes_storage) {
auto kind = static_cast<DAGNode::NodeKind>(kind_int);
if (val && value_to_node.count(val) && kind != DAGNode::STORE && kind != DAGNode::RETURN && kind != DAGNode::BRANCH && kind != DAGNode::MEMSET) {
return value_to_node[val];
}
@@ -526,10 +553,7 @@ RISCv64ISel::DAGNode* RISCv64ISel::create_node(DAGNode::NodeKind kind, Value* va
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)) {
if (val && !val->getType()->isVoid() && (dynamic_cast<Instruction*>(val) || dynamic_cast<GlobalValue*>(val))) {
value_to_node[val] = raw_node_ptr;
}
return raw_node_ptr;
@@ -545,7 +569,6 @@ RISCv64ISel::DAGNode* RISCv64ISel::get_operand_node(Value* val_ir, std::map<Valu
} 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);
}
@@ -567,12 +590,20 @@ std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicB
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)) {
} 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;
if (bin->getKind() == BinaryInst::kSub) {
if (auto const_lhs = dynamic_cast<ConstantValue*>(bin->getLhs())) {
if (const_lhs->getInt() == 0) {
auto unary_node = create_node(DAGNode::UNARY, bin, value_to_node, nodes_storage);
unary_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
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));
@@ -580,8 +611,7 @@ std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicB
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)) {
} 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()) {