mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-03 06:38:46 +00:00
ssa_rewrite: Correct recursive trivial phi elimination
This commit is contained in:
parent
b5ac4c5569
commit
a86b855b38
4 changed files with 8 additions and 7 deletions
|
@ -19,12 +19,14 @@ void Block::AppendNewInst(Opcode op, std::initializer_list<Value> args) {
|
||||||
|
|
||||||
Block::iterator Block::PrependNewInst(iterator insertion_point, const Inst& base_inst) {
|
Block::iterator Block::PrependNewInst(iterator insertion_point, const Inst& base_inst) {
|
||||||
Inst* const inst{inst_pool->Create(base_inst)};
|
Inst* const inst{inst_pool->Create(base_inst)};
|
||||||
|
inst->SetParent(this);
|
||||||
return instructions.insert(insertion_point, *inst);
|
return instructions.insert(insertion_point, *inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode op,
|
Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode op,
|
||||||
std::initializer_list<Value> args, u32 flags) {
|
std::initializer_list<Value> args, u32 flags) {
|
||||||
Inst* const inst{inst_pool->Create(op, flags)};
|
Inst* const inst{inst_pool->Create(op, flags)};
|
||||||
|
inst->SetParent(this);
|
||||||
const auto result_it{instructions.insert(insertion_point, *inst)};
|
const auto result_it{instructions.insert(insertion_point, *inst)};
|
||||||
|
|
||||||
if (inst->NumArgs() != args.size()) {
|
if (inst->NumArgs() != args.size()) {
|
||||||
|
|
|
@ -330,7 +330,6 @@ private:
|
||||||
template <typename T = Value, typename... Args>
|
template <typename T = Value, typename... Args>
|
||||||
T Inst(Opcode op, Args... args) {
|
T Inst(Opcode op, Args... args) {
|
||||||
auto it{block->PrependNewInst(insertion_point, op, {Value{args}...})};
|
auto it{block->PrependNewInst(insertion_point, op, {Value{args}...})};
|
||||||
it->SetParent(block);
|
|
||||||
return T{Value{&*it}};
|
return T{Value{&*it}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +347,6 @@ private:
|
||||||
u32 raw_flags{};
|
u32 raw_flags{};
|
||||||
std::memcpy(&raw_flags, &flags.proxy, sizeof(flags.proxy));
|
std::memcpy(&raw_flags, &flags.proxy, sizeof(flags.proxy));
|
||||||
auto it{block->PrependNewInst(insertion_point, op, {Value{args}...}, raw_flags)};
|
auto it{block->PrependNewInst(insertion_point, op, {Value{args}...}, raw_flags)};
|
||||||
it->SetParent(block);
|
|
||||||
return T{Value{&*it}};
|
return T{Value{&*it}};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -180,8 +180,8 @@ void Inst::ClearArgs() {
|
||||||
void Inst::ReplaceUsesWith(Value replacement, bool preserve) {
|
void Inst::ReplaceUsesWith(Value replacement, bool preserve) {
|
||||||
// Copy since user->SetArg will mutate this->uses
|
// Copy since user->SetArg will mutate this->uses
|
||||||
// Could also do temp_uses = std::move(uses) but more readable
|
// Could also do temp_uses = std::move(uses) but more readable
|
||||||
boost::container::list<IR::Use> temp_uses = uses;
|
const auto temp_uses = uses;
|
||||||
for (auto& [user, operand] : temp_uses) {
|
for (const auto& [user, operand] : temp_uses) {
|
||||||
DEBUG_ASSERT(user->Arg(operand).Inst() == this);
|
DEBUG_ASSERT(user->Arg(operand).Inst() == this);
|
||||||
user->SetArg(operand, replacement);
|
user->SetArg(operand, replacement);
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,6 +270,7 @@ public:
|
||||||
block->SsaSeal();
|
block->SsaSeal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
IR::Value AddPhiOperands(Type variable, IR::Inst& phi, IR::Block* block) {
|
IR::Value AddPhiOperands(Type variable, IR::Inst& phi, IR::Block* block) {
|
||||||
for (IR::Block* const imm_pred : block->ImmPredecessors()) {
|
for (IR::Block* const imm_pred : block->ImmPredecessors()) {
|
||||||
|
@ -283,7 +284,7 @@ public:
|
||||||
const size_t num_args{phi.NumArgs()};
|
const size_t num_args{phi.NumArgs()};
|
||||||
for (size_t arg_index = 0; arg_index < num_args; ++arg_index) {
|
for (size_t arg_index = 0; arg_index < num_args; ++arg_index) {
|
||||||
const IR::Value& op{phi.Arg(arg_index)};
|
const IR::Value& op{phi.Arg(arg_index)};
|
||||||
if (op.Resolve() == same.Resolve() || op == IR::Value{&phi}) {
|
if (op.Resolve() == same.Resolve() || op.Resolve() == IR::Value{&phi}) {
|
||||||
// Unique value or self-reference
|
// Unique value or self-reference
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -308,10 +309,10 @@ public:
|
||||||
++reinsert_point;
|
++reinsert_point;
|
||||||
}
|
}
|
||||||
// Reinsert the phi node and reroute all its uses to the "same" value
|
// Reinsert the phi node and reroute all its uses to the "same" value
|
||||||
|
const auto users = phi.Uses();
|
||||||
list.insert(reinsert_point, phi);
|
list.insert(reinsert_point, phi);
|
||||||
phi.ReplaceUsesWith(same);
|
phi.ReplaceUsesWith(same);
|
||||||
// TODO: Try to recursively remove all phi users, which might have become trivial
|
// Try to recursively remove all phi users, which might have become trivial
|
||||||
const auto users = phi.Uses();
|
|
||||||
for (const auto& [user, arg_index] : users) {
|
for (const auto& [user, arg_index] : users) {
|
||||||
if (user->GetOpcode() == IR::Opcode::Phi) {
|
if (user->GetOpcode() == IR::Opcode::Phi) {
|
||||||
TryRemoveTrivialPhi(*user, user->GetParent(), undef_opcode);
|
TryRemoveTrivialPhi(*user, user->GetParent(), undef_opcode);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue