mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-12-06 07:12:28 +01:00
rsx: Add flow information to flow edges
This commit is contained in:
parent
f300832edb
commit
42d9065c11
|
|
@ -13,7 +13,7 @@ namespace rsx::assembler
|
|||
{
|
||||
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())
|
||||
{
|
||||
|
|
@ -25,8 +25,8 @@ namespace rsx::assembler
|
|||
|
||||
if (parent)
|
||||
{
|
||||
parent->insert_succ(new_block);
|
||||
new_block->insert_pred(parent);
|
||||
parent->insert_succ(new_block, edge_type);
|
||||
new_block->insert_pred(parent, edge_type);
|
||||
}
|
||||
|
||||
new_block->id = pc;
|
||||
|
|
|
|||
|
|
@ -63,16 +63,16 @@ namespace rsx::assembler
|
|||
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))
|
||||
{
|
||||
parent->insert_succ(found);
|
||||
found->insert_pred(parent);
|
||||
parent->insert_succ(found, edge_type);
|
||||
found->insert_pred(parent, edge_type);
|
||||
return found;
|
||||
}
|
||||
|
||||
return graph.push(parent, id);
|
||||
return graph.push(parent, id, edge_type);
|
||||
};
|
||||
|
||||
while (!end)
|
||||
|
|
@ -125,12 +125,12 @@ namespace rsx::assembler
|
|||
{
|
||||
// Inserts if and else and end blocks
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
case RSX_FP_OPCODE_LOOP:
|
||||
|
|
@ -138,8 +138,8 @@ namespace rsx::assembler
|
|||
{
|
||||
// Inserts for and end blocks
|
||||
auto parent = bb;
|
||||
bb = safe_insert_block(parent, pc + 1);
|
||||
end_blocks.push_back(safe_insert_block(parent, src2.end_offset >> 2));
|
||||
bb = safe_insert_block(parent, pc + 1, EdgeType::LOOP);
|
||||
end_blocks.push_back(safe_insert_block(parent, src2.end_offset >> 2, EdgeType::ENDLOOP));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -42,8 +42,19 @@ namespace rsx::assembler
|
|||
std::vector<RegisterRef> dsts;
|
||||
};
|
||||
|
||||
enum class EdgeType
|
||||
{
|
||||
NONE,
|
||||
IF,
|
||||
ELSE,
|
||||
ENDIF,
|
||||
LOOP,
|
||||
ENDLOOP
|
||||
};
|
||||
|
||||
struct FlowEdge
|
||||
{
|
||||
EdgeType type = EdgeType::NONE;
|
||||
BasicBlock* from = nullptr;
|
||||
BasicBlock* to = nullptr;
|
||||
};
|
||||
|
|
@ -51,20 +62,25 @@ namespace rsx::assembler
|
|||
struct BasicBlock
|
||||
{
|
||||
u32 id = 0;
|
||||
std::vector<Instruction> instructions;
|
||||
std::vector<FlowEdge> succ; // [0] = if/loop, [1] = else
|
||||
std::vector<FlowEdge> pred; // Back edge.
|
||||
std::vector<Instruction> instructions; // Program instructions for the RSX processor
|
||||
std::vector<FlowEdge> succ; // [0] = if/loop, [1] = else
|
||||
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);
|
||||
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);
|
||||
return &pred.back();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,6 +104,11 @@ namespace rsx::assembler
|
|||
EXPECT_EQ(it->id, expected.first);
|
||||
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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue