[backend]添加了DAG图打印函数;为分支指令引入了延迟物化;添加了函数参数溢出到栈的处理逻辑
This commit is contained in:
@@ -83,6 +83,10 @@ void RISCv64ISel::selectBasicBlock(BasicBlock* bb) {
|
|||||||
CurMBB = bb_map.at(bb);
|
CurMBB = bb_map.at(bb);
|
||||||
auto dag = build_dag(bb);
|
auto dag = build_dag(bb);
|
||||||
|
|
||||||
|
if (DEBUG) { // 使用 DEBUG 宏或变量来控制是否打印
|
||||||
|
print_dag(dag, bb->getName());
|
||||||
|
}
|
||||||
|
|
||||||
std::map<Value*, DAGNode*> value_to_node;
|
std::map<Value*, DAGNode*> value_to_node;
|
||||||
for(const auto& node : dag) {
|
for(const auto& node : dag) {
|
||||||
if (node->value) {
|
if (node->value) {
|
||||||
@@ -486,7 +490,9 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
case DAGNode::CALL: {
|
case DAGNode::CALL: {
|
||||||
auto call = dynamic_cast<CallInst*>(node->value);
|
auto call = dynamic_cast<CallInst*>(node->value);
|
||||||
// 处理函数参数,放入a0-a7物理寄存器
|
// 处理函数参数,放入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];
|
DAGNode* arg_node = node->operands[i];
|
||||||
auto arg_preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + 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));
|
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);
|
auto call_instr = std::make_unique<MachineInstr>(RVOpcodes::CALL);
|
||||||
call_instr->addOperand(std::make_unique<LabelOperand>(call->getCallee()->getName()));
|
call_instr->addOperand(std::make_unique<LabelOperand>(call->getCallee()->getName()));
|
||||||
CurMBB->addInstruction(std::move(call_instr));
|
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移动到目标虚拟寄存器
|
// 处理返回值,从a0移动到目标虚拟寄存器
|
||||||
if (!call->getType()->isVoid()) {
|
if (!call->getType()->isVoid()) {
|
||||||
auto mv_instr = std::make_unique<MachineInstr>(RVOpcodes::MV);
|
auto mv_instr = std::make_unique<MachineInstr>(RVOpcodes::MV);
|
||||||
@@ -545,33 +603,59 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case DAGNode::BRANCH: {
|
case DAGNode::BRANCH: {
|
||||||
if (auto cond_br = dynamic_cast<CondBrInst*>(node->value)) {
|
// 处理条件分支
|
||||||
// [V2优点] 采用更健壮的if-then-else分支逻辑。
|
if (auto cond_br = dynamic_cast<CondBrInst*>(node->value)) {
|
||||||
auto cond_vreg = getVReg(cond_br->getCondition());
|
Value* condition = cond_br->getCondition();
|
||||||
auto then_bb_name = cond_br->getThenBlock()->getName();
|
auto then_bb_name = cond_br->getThenBlock()->getName();
|
||||||
auto else_bb_name = cond_br->getElseBlock()->getName();
|
auto else_bb_name = cond_br->getElseBlock()->getName();
|
||||||
|
|
||||||
// bne cond, zero, then_label (如果cond不为0,则跳转到then)
|
// [优化] 检查分支条件是否为编译期常量
|
||||||
|
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)
|
||||||
auto br_instr = std::make_unique<MachineInstr>(RVOpcodes::BNE);
|
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>(cond_vreg));
|
||||||
br_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
|
br_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
|
||||||
br_instr->addOperand(std::make_unique<LabelOperand>(then_bb_name));
|
br_instr->addOperand(std::make_unique<LabelOperand>(then_bb_name));
|
||||||
CurMBB->addInstruction(std::move(br_instr));
|
CurMBB->addInstruction(std::move(br_instr));
|
||||||
|
|
||||||
// 无条件跳转到else块 (如果上面分支未发生)
|
// 为else分支生成无条件跳转 (后续Pass可以优化掉不必要的跳转)
|
||||||
// 注意:在实际的CFG中,这个J指令可能不是必须的,
|
|
||||||
// 因为else块可能是下一个块。但为了通用性,这里生成它。
|
|
||||||
auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J);
|
auto j_instr = std::make_unique<MachineInstr>(RVOpcodes::J);
|
||||||
j_instr->addOperand(std::make_unique<LabelOperand>(else_bb_name));
|
j_instr->addOperand(std::make_unique<LabelOperand>(else_bb_name));
|
||||||
CurMBB->addInstruction(std::move(j_instr));
|
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: {
|
case DAGNode::MEMSET: {
|
||||||
// [V1设计保留] Memset的核心展开逻辑在虚拟寄存器层面是正确的,无需修改。
|
// [V1设计保留] Memset的核心展开逻辑在虚拟寄存器层面是正确的,无需修改。
|
||||||
@@ -808,4 +892,98 @@ std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicB
|
|||||||
return nodes_storage;
|
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
|
} // 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* 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>>&);
|
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函数
|
Function* F; // 当前处理的高层IR函数
|
||||||
std::unique_ptr<MachineFunction> MFunc; // 正在构建的底层LLIR函数
|
std::unique_ptr<MachineFunction> MFunc; // 正在构建的底层LLIR函数
|
||||||
|
|||||||
Reference in New Issue
Block a user