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;
|
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;
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue