rsx: Add flow information to flow edges

This commit is contained in:
kd-11 2025-11-23 19:25:07 +03:00 committed by kd-11
parent f300832edb
commit 42d9065c11
4 changed files with 40 additions and 19 deletions

View file

@ -13,7 +13,7 @@ namespace rsx::assembler
{ {
std::list<BasicBlock> blocks; std::list<BasicBlock> blocks;
BasicBlock* push(BasicBlock* parent = nullptr, u32 pc = 0) BasicBlock* push(BasicBlock* parent = nullptr, u32 pc = 0, EdgeType edge_type = EdgeType::NONE)
{ {
if (!parent && !blocks.empty()) if (!parent && !blocks.empty())
{ {
@ -25,8 +25,8 @@ namespace rsx::assembler
if (parent) if (parent)
{ {
parent->insert_succ(new_block); parent->insert_succ(new_block, edge_type);
new_block->insert_pred(parent); new_block->insert_pred(parent, edge_type);
} }
new_block->id = pc; new_block->id = pc;

View file

@ -63,16 +63,16 @@ namespace rsx::assembler
return nullptr; return nullptr;
}; };
auto safe_insert_block = [&](BasicBlock* parent, u32 id) -> BasicBlock* auto safe_insert_block = [&](BasicBlock* parent, u32 id, EdgeType edge_type) -> BasicBlock*
{ {
if (auto found = find_block_for_pc(id)) if (auto found = find_block_for_pc(id))
{ {
parent->insert_succ(found); parent->insert_succ(found, edge_type);
found->insert_pred(parent); found->insert_pred(parent, edge_type);
return found; return found;
} }
return graph.push(parent, id); return graph.push(parent, id, edge_type);
}; };
while (!end) while (!end)
@ -125,12 +125,12 @@ namespace rsx::assembler
{ {
// Inserts if and else and end blocks // Inserts if and else and end blocks
auto parent = bb; auto parent = bb;
bb = safe_insert_block(parent, pc + 1); bb = safe_insert_block(parent, pc + 1, EdgeType::IF);
if (src2.end_offset != src1.else_offset) if (src2.end_offset != src1.else_offset)
{ {
else_blocks.push_back(safe_insert_block(parent, src1.else_offset >> 2)); else_blocks.push_back(safe_insert_block(parent, src1.else_offset >> 2, EdgeType::ELSE));
} }
end_blocks.push_back(safe_insert_block(parent, src2.end_offset >> 2)); end_blocks.push_back(safe_insert_block(parent, src2.end_offset >> 2, EdgeType::ENDIF));
break; break;
} }
case RSX_FP_OPCODE_LOOP: case RSX_FP_OPCODE_LOOP:
@ -138,8 +138,8 @@ namespace rsx::assembler
{ {
// Inserts for and end blocks // Inserts for and end blocks
auto parent = bb; auto parent = bb;
bb = safe_insert_block(parent, pc + 1); bb = safe_insert_block(parent, pc + 1, EdgeType::LOOP);
end_blocks.push_back(safe_insert_block(parent, src2.end_offset >> 2)); end_blocks.push_back(safe_insert_block(parent, src2.end_offset >> 2, EdgeType::ENDLOOP));
break; break;
} }
default: default:

View file

@ -42,8 +42,19 @@ namespace rsx::assembler
std::vector<RegisterRef> dsts; std::vector<RegisterRef> dsts;
}; };
enum class EdgeType
{
NONE,
IF,
ELSE,
ENDIF,
LOOP,
ENDLOOP
};
struct FlowEdge struct FlowEdge
{ {
EdgeType type = EdgeType::NONE;
BasicBlock* from = nullptr; BasicBlock* from = nullptr;
BasicBlock* to = nullptr; BasicBlock* to = nullptr;
}; };
@ -51,20 +62,25 @@ namespace rsx::assembler
struct BasicBlock struct BasicBlock
{ {
u32 id = 0; u32 id = 0;
std::vector<Instruction> instructions; std::vector<Instruction> instructions; // Program instructions for the RSX processor
std::vector<FlowEdge> succ; // [0] = if/loop, [1] = else std::vector<FlowEdge> succ; // [0] = if/loop, [1] = else
std::vector<FlowEdge> pred; // Back edge. std::vector<FlowEdge> pred; // Back edge.
void insert_succ(BasicBlock* b) std::vector<Instruction> prologue; // Prologue, created by passes
std::vector<Instruction> epilogue; // Epilogue, created by passes
FlowEdge* insert_succ(BasicBlock* b, EdgeType type = EdgeType::NONE)
{ {
FlowEdge e{ .from = this, .to = b }; FlowEdge e{ .type = type, .from = this, .to = b };
succ.push_back(e); succ.push_back(e);
return &succ.back();
} }
void insert_pred(BasicBlock* b) FlowEdge* insert_pred(BasicBlock* b, EdgeType type = EdgeType::NONE)
{ {
FlowEdge e{ .from = this, .to = b }; FlowEdge e{ .type = type, .from = this, .to = b };
pred.push_back(e); pred.push_back(e);
return &pred.back();
} }
}; };
} }

View file

@ -104,6 +104,11 @@ namespace rsx::assembler
EXPECT_EQ(it->id, expected.first); EXPECT_EQ(it->id, expected.first);
EXPECT_EQ(it->instructions.size(), expected.second); EXPECT_EQ(it->instructions.size(), expected.second);
} }
// Check edges
EXPECT_EQ(std::find_if(graph.blocks.begin(), graph.blocks.end(), FN(x.id == 3))->pred[0].type, EdgeType::IF);
EXPECT_EQ(std::find_if(graph.blocks.begin(), graph.blocks.end(), FN(x.id == 0))->succ[0].type, EdgeType::IF);
EXPECT_EQ(std::find_if(graph.blocks.begin(), graph.blocks.end(), FN(x.id == 4))->pred[0].type, EdgeType::ENDIF);
} }
TEST(CFG, FpToCFG_NestedIF) TEST(CFG, FpToCFG_NestedIF)