[backend]添加了DAG图打印函数;为分支指令引入了延迟物化;添加了函数参数溢出到栈的处理逻辑
This commit is contained in:
@@ -83,6 +83,10 @@ void RISCv64ISel::selectBasicBlock(BasicBlock* bb) {
|
||||
CurMBB = bb_map.at(bb);
|
||||
auto dag = build_dag(bb);
|
||||
|
||||
if (DEBUG) { // 使用 DEBUG 宏或变量来控制是否打印
|
||||
print_dag(dag, bb->getName());
|
||||
}
|
||||
|
||||
std::map<Value*, DAGNode*> value_to_node;
|
||||
for(const auto& node : dag) {
|
||||
if (node->value) {
|
||||
@@ -486,7 +490,9 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
case DAGNode::CALL: {
|
||||
auto call = dynamic_cast<CallInst*>(node->value);
|
||||
// 处理函数参数,放入a0-a7物理寄存器
|
||||
for (size_t i = 0; i < node->operands.size() && i < 8; ++i) {
|
||||
size_t num_operands = node->operands.size();
|
||||
size_t reg_arg_count = std::min(num_operands, (size_t)8);
|
||||
for (size_t i = 0; i < reg_arg_count; ++i) {
|
||||
DAGNode* arg_node = node->operands[i];
|
||||
auto arg_preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + i);
|
||||
|
||||
@@ -505,11 +511,63 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
CurMBB->addInstruction(std::move(mv));
|
||||
}
|
||||
}
|
||||
if (num_operands > 8) {
|
||||
size_t stack_arg_count = num_operands - 8;
|
||||
int stack_space = stack_arg_count * 8; // RV64中每个参数槽位8字节
|
||||
|
||||
// 2a. 在栈上分配空间
|
||||
auto alloc_instr = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||
alloc_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||
alloc_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||
alloc_instr->addOperand(std::make_unique<ImmOperand>(-stack_space));
|
||||
CurMBB->addInstruction(std::move(alloc_instr));
|
||||
|
||||
// 2b. 存储每个栈参数
|
||||
for (size_t i = 8; i < num_operands; ++i) {
|
||||
DAGNode* arg_node = node->operands[i];
|
||||
unsigned src_vreg;
|
||||
|
||||
// 准备源寄存器
|
||||
if (arg_node->kind == DAGNode::CONSTANT) {
|
||||
// 如果是常量,先加载到临时寄存器
|
||||
src_vreg = getNewVReg();
|
||||
auto const_val = dynamic_cast<ConstantValue*>(arg_node->value);
|
||||
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
||||
li->addOperand(std::make_unique<RegOperand>(src_vreg));
|
||||
li->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
|
||||
CurMBB->addInstruction(std::move(li));
|
||||
} else {
|
||||
src_vreg = getVReg(arg_node->value);
|
||||
}
|
||||
|
||||
// 计算在栈上的偏移量
|
||||
int offset = (i - 8) * 8;
|
||||
|
||||
// 生成 sd 指令
|
||||
auto sd_instr = std::make_unique<MachineInstr>(RVOpcodes::SD);
|
||||
sd_instr->addOperand(std::make_unique<RegOperand>(src_vreg));
|
||||
sd_instr->addOperand(std::make_unique<MemOperand>(
|
||||
std::make_unique<RegOperand>(PhysicalReg::SP),
|
||||
std::make_unique<ImmOperand>(offset)
|
||||
));
|
||||
CurMBB->addInstruction(std::move(sd_instr));
|
||||
}
|
||||
}
|
||||
|
||||
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 (num_operands > 8) {
|
||||
size_t stack_arg_count = num_operands - 8;
|
||||
int stack_space = stack_arg_count * 8;
|
||||
|
||||
auto dealloc_instr = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
|
||||
dealloc_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||
dealloc_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
|
||||
dealloc_instr->addOperand(std::make_unique<ImmOperand>(stack_space));
|
||||
CurMBB->addInstruction(std::move(dealloc_instr));
|
||||
}
|
||||
// 处理返回值,从a0移动到目标虚拟寄存器
|
||||
if (!call->getType()->isVoid()) {
|
||||
auto mv_instr = std::make_unique<MachineInstr>(RVOpcodes::MV);
|
||||
@@ -545,33 +603,59 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
}
|
||||
|
||||
case DAGNode::BRANCH: {
|
||||
if (auto cond_br = dynamic_cast<CondBrInst*>(node->value)) {
|
||||
// [V2优点] 采用更健壮的if-then-else分支逻辑。
|
||||
auto cond_vreg = getVReg(cond_br->getCondition());
|
||||
auto then_bb_name = cond_br->getThenBlock()->getName();
|
||||
auto else_bb_name = cond_br->getElseBlock()->getName();
|
||||
// 处理条件分支
|
||||
if (auto cond_br = dynamic_cast<CondBrInst*>(node->value)) {
|
||||
Value* condition = cond_br->getCondition();
|
||||
auto then_bb_name = cond_br->getThenBlock()->getName();
|
||||
auto else_bb_name = cond_br->getElseBlock()->getName();
|
||||
|
||||
// [优化] 检查分支条件是否为编译期常量
|
||||
if (auto const_cond = dynamic_cast<ConstantValue*>(condition)) {
|
||||
// 如果条件是常量,直接生成一个无条件跳转J,而不是BNE
|
||||
if (const_cond->getInt() != 0) { // 条件为 true
|
||||
auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J);
|
||||
j_instr->addOperand(std::make_unique<LabelOperand>(then_bb_name));
|
||||
CurMBB->addInstruction(std::move(j_instr));
|
||||
} else { // 条件为 false
|
||||
auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J);
|
||||
j_instr->addOperand(std::make_unique<LabelOperand>(else_bb_name));
|
||||
CurMBB->addInstruction(std::move(j_instr));
|
||||
}
|
||||
}
|
||||
// 如果条件不是常量,则执行标准流程
|
||||
else {
|
||||
// [修复] 为条件变量生成加载指令(如果它是常量的话,尽管上面已经处理了)
|
||||
// 这一步是为了逻辑完整,以防有其他类型的常量没有被捕获
|
||||
if (auto const_val = dynamic_cast<ConstantValue*>(condition)) {
|
||||
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
|
||||
li->addOperand(std::make_unique<RegOperand>(getVReg(const_val)));
|
||||
li->addOperand(std::make_unique<ImmOperand>(const_val->getInt()));
|
||||
CurMBB->addInstruction(std::move(li));
|
||||
}
|
||||
|
||||
auto cond_vreg = getVReg(condition);
|
||||
|
||||
// bne cond, zero, then_label (如果cond不为0,则跳转到then)
|
||||
// 生成 bne cond, zero, then_label (如果cond不为0,则跳转到then)
|
||||
auto br_instr = std::make_unique<MachineInstr>(RVOpcodes::BNE);
|
||||
br_instr->addOperand(std::make_unique<RegOperand>(cond_vreg));
|
||||
br_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
|
||||
br_instr->addOperand(std::make_unique<LabelOperand>(then_bb_name));
|
||||
CurMBB->addInstruction(std::move(br_instr));
|
||||
|
||||
// 无条件跳转到else块 (如果上面分支未发生)
|
||||
// 注意:在实际的CFG中,这个J指令可能不是必须的,
|
||||
// 因为else块可能是下一个块。但为了通用性,这里生成它。
|
||||
// 为else分支生成无条件跳转 (后续Pass可以优化掉不必要的跳转)
|
||||
auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J);
|
||||
j_instr->addOperand(std::make_unique<LabelOperand>(else_bb_name));
|
||||
CurMBB->addInstruction(std::move(j_instr));
|
||||
|
||||
} 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;
|
||||
}
|
||||
// 处理无条件分支
|
||||
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: {
|
||||
// [V1设计保留] Memset的核心展开逻辑在虚拟寄存器层面是正确的,无需修改。
|
||||
@@ -808,4 +892,98 @@ std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicB
|
||||
return nodes_storage;
|
||||
}
|
||||
|
||||
// [新] 打印DAG图以供调试的辅助函数
|
||||
void RISCv64ISel::print_dag(const std::vector<std::unique_ptr<DAGNode>>& dag, const std::string& bb_name) {
|
||||
// 检查是否有DEBUG宏或者全局变量,避免在非调试模式下打印
|
||||
// if (!DEBUG) return;
|
||||
|
||||
std::cerr << "=== DAG for Basic Block: " << bb_name << " ===\n";
|
||||
std::set<DAGNode*> visited;
|
||||
|
||||
// 为节点分配临时ID,方便阅读
|
||||
std::map<DAGNode*, int> node_to_id;
|
||||
int current_id = 0;
|
||||
for (const auto& node_ptr : dag) {
|
||||
node_to_id[node_ptr.get()] = current_id++;
|
||||
}
|
||||
|
||||
// 将NodeKind枚举转换为字符串的辅助函数
|
||||
auto get_kind_string = [](DAGNode::NodeKind kind) {
|
||||
switch (kind) {
|
||||
case DAGNode::CONSTANT: return "CONSTANT";
|
||||
case DAGNode::LOAD: return "LOAD";
|
||||
case DAGNode::STORE: return "STORE";
|
||||
case DAGNode::BINARY: return "BINARY";
|
||||
case DAGNode::CALL: return "CALL";
|
||||
case DAGNode::RETURN: return "RETURN";
|
||||
case DAGNode::BRANCH: return "BRANCH";
|
||||
case DAGNode::ALLOCA_ADDR: return "ALLOCA_ADDR";
|
||||
case DAGNode::UNARY: return "UNARY";
|
||||
case DAGNode::MEMSET: return "MEMSET";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
};
|
||||
|
||||
// 递归打印节点的lambda表达式
|
||||
std::function<void(DAGNode*, int)> print_node =
|
||||
[&](DAGNode* node, int indent) {
|
||||
if (!node) return;
|
||||
|
||||
std::string current_indent(indent, ' ');
|
||||
int node_id = node_to_id.count(node) ? node_to_id[node] : -1;
|
||||
|
||||
std::cerr << current_indent << "Node#" << node_id << ": " << get_kind_string(node->kind);
|
||||
|
||||
// 尝试打印关联的虚拟寄存器
|
||||
if (node->value && vreg_map.count(node->value)) {
|
||||
std::cerr << " (vreg: %vreg" << vreg_map.at(node->value) << ")";
|
||||
}
|
||||
|
||||
// 打印关联的IR Value信息
|
||||
if (node->value) {
|
||||
std::cerr << " [";
|
||||
if (auto inst = dynamic_cast<Instruction*>(node->value)) {
|
||||
std::cerr << inst->getKindString();
|
||||
if (!inst->getName().empty()) {
|
||||
std::cerr << "(" << inst->getName() << ")";
|
||||
}
|
||||
} else if (auto constant = dynamic_cast<ConstantValue*>(node->value)) {
|
||||
std::cerr << "Const(" << constant->getInt() << ")";
|
||||
} else if (auto global = dynamic_cast<GlobalValue*>(node->value)) {
|
||||
std::cerr << "Global(" << global->getName() << ")";
|
||||
} else if (auto alloca = dynamic_cast<AllocaInst*>(node->value)) {
|
||||
std::cerr << "Alloca(" << alloca->getName() << ")";
|
||||
}
|
||||
std::cerr << "]";
|
||||
}
|
||||
std::cerr << "\n";
|
||||
|
||||
if (visited.count(node)) {
|
||||
std::cerr << current_indent << " (已打印过子节点)\n";
|
||||
return;
|
||||
}
|
||||
visited.insert(node);
|
||||
|
||||
if (!node->operands.empty()) {
|
||||
std::cerr << current_indent << " Operands:\n";
|
||||
for (auto operand : node->operands) {
|
||||
print_node(operand, indent + 4);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 从根节点(没有用户的节点,或有副作用的节点)开始打印
|
||||
for (const auto& node_ptr : dag) {
|
||||
if (node_ptr->users.empty() ||
|
||||
node_ptr->kind == DAGNode::STORE ||
|
||||
node_ptr->kind == DAGNode::RETURN ||
|
||||
node_ptr->kind == DAGNode::BRANCH ||
|
||||
node_ptr->kind == DAGNode::MEMSET)
|
||||
{
|
||||
print_node(node_ptr.get(), 0);
|
||||
}
|
||||
}
|
||||
std::cerr << "======================================\n\n";
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
@@ -34,6 +34,8 @@ private:
|
||||
DAGNode* get_operand_node(Value* val_ir, std::map<Value*, DAGNode*>&, std::vector<std::unique_ptr<DAGNode>>&);
|
||||
DAGNode* create_node(int kind, Value* val, std::map<Value*, DAGNode*>&, std::vector<std::unique_ptr<DAGNode>>&);
|
||||
|
||||
void print_dag(const std::vector<std::unique_ptr<DAGNode>>& dag, const std::string& bb_name);
|
||||
|
||||
// 状态
|
||||
Function* F; // 当前处理的高层IR函数
|
||||
std::unique_ptr<MachineFunction> MFunc; // 正在构建的底层LLIR函数
|
||||
|
||||
Reference in New Issue
Block a user