diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index cbd3780de..b50cadcef 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -330,6 +330,7 @@ private: template T Inst(Opcode op, Args... args) { auto it{block->PrependNewInst(insertion_point, op, {Value{args}...})}; + it->SetParent(block); return T{Value{&*it}}; } @@ -347,6 +348,7 @@ private: u32 raw_flags{}; std::memcpy(&raw_flags, &flags.proxy, sizeof(flags.proxy)); auto it{block->PrependNewInst(insertion_point, op, {Value{args}...}, raw_flags)}; + it->SetParent(block); return T{Value{&*it}}; } }; diff --git a/src/shader_recompiler/ir/microinstruction.cpp b/src/shader_recompiler/ir/microinstruction.cpp index e1f7129bd..064cbbbc3 100644 --- a/src/shader_recompiler/ir/microinstruction.cpp +++ b/src/shader_recompiler/ir/microinstruction.cpp @@ -150,7 +150,6 @@ void Inst::AddPhiOperand(Block* predecessor, const Value& value) { } void Inst::Invalidate() { - ASSERT(uses.empty()); ClearArgs(); ReplaceOpcode(Opcode::Void); } diff --git a/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp index df73c1bc8..872f5bd00 100644 --- a/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp @@ -164,7 +164,6 @@ IR::Opcode UndefOpcode(const FlagTag) noexcept { enum class Status { Start, SetValue, - PreparePhiArgument, PushPhiArgument, }; @@ -253,12 +252,10 @@ public: IR::Inst* const phi{stack.back().phi}; phi->AddPhiOperand(*stack.back().pred_it, stack.back().result); ++stack.back().pred_it; - } - [[fallthrough]]; - case Status::PreparePhiArgument: prepare_phi_operand(); break; } + } } while (stack.size() > 1); return stack.back().result; } @@ -266,16 +263,13 @@ public: void SealBlock(IR::Block* block) { const auto it{incomplete_phis.find(block)}; if (it != incomplete_phis.end()) { - for (auto& pair : it->second) { - auto& variant{pair.first}; - auto& phi{pair.second}; + for (auto& [variant, phi] : it->second) { std::visit([&](auto& variable) { AddPhiOperands(variable, *phi, block); }, variant); } } block->SsaSeal(); } -private: template IR::Value AddPhiOperands(Type variable, IR::Inst& phi, IR::Block* block) { for (IR::Block* const imm_pred : block->ImmPredecessors()) { @@ -317,6 +311,12 @@ private: list.insert(reinsert_point, phi); phi.ReplaceUsesWith(same); // TODO: Try to recursively remove all phi users, which might have become trivial + const auto users = phi.Uses(); + for (const auto& [user, arg_index] : users) { + if (user->GetOpcode() == IR::Opcode::Phi) { + TryRemoveTrivialPhi(*user, user->GetParent(), undef_opcode); + } + } return same; } diff --git a/src/shader_recompiler/ir/value.h b/src/shader_recompiler/ir/value.h index f4822827f..f0f511c04 100644 --- a/src/shader_recompiler/ir/value.h +++ b/src/shader_recompiler/ir/value.h @@ -129,6 +129,14 @@ public: Inst& operator=(Inst&&) = delete; Inst(Inst&&) = delete; + IR::Block* GetParent() { + ASSERT(parent); + return parent; + } + void SetParent(IR::Block* block) { + parent = block; + } + /// Get the number of uses this instruction has. [[nodiscard]] int UseCount() const noexcept { return uses.size(); @@ -214,6 +222,10 @@ public: return std::bit_cast(definition); } + const auto Uses() const { + return uses; + } + private: struct NonTriviallyDummy { NonTriviallyDummy() noexcept {} @@ -226,6 +238,7 @@ private: IR::Opcode op{}; u32 flags{}; u32 definition{}; + IR::Block* parent{}; union { NonTriviallyDummy dummy{}; boost::container::small_vector, 2> phi_args; @@ -234,7 +247,7 @@ private: boost::container::list uses; }; -static_assert(sizeof(Inst) <= 152, "Inst size unintentionally increased"); +static_assert(sizeof(Inst) <= 160, "Inst size unintentionally increased"); using U1 = TypedValue; using U8 = TypedValue; @@ -392,4 +405,4 @@ template <> struct hash { std::size_t operator()(const Shader::IR::Value& v) const; }; -} // namespace std \ No newline at end of file +} // namespace std