From c50ad56bf59169bd0fc808ebecfb4a69376f10df Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 31 Oct 2021 17:46:46 +0100 Subject: [PATCH 1/3] ShaderCache: Order Phi Arguments from farthest away to nearest. --- src/shader_recompiler/frontend/ir/basic_block.h | 14 ++++++++++++++ .../frontend/ir/microinstruction.cpp | 11 +++++++++++ src/shader_recompiler/frontend/ir/value.h | 3 +++ .../frontend/maxwell/translate_program.cpp | 2 ++ src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | 7 +++++++ 5 files changed, 37 insertions(+) diff --git a/src/shader_recompiler/frontend/ir/basic_block.h b/src/shader_recompiler/frontend/ir/basic_block.h index 7e134b4c7..9ce1ed07e 100644 --- a/src/shader_recompiler/frontend/ir/basic_block.h +++ b/src/shader_recompiler/frontend/ir/basic_block.h @@ -152,6 +152,17 @@ public: return instructions.crend(); } + // Set the order of the block, it can be set pre order, the user decides + void SetOrder(u32 new_order) { + order = new_order; + } + + // Get the order of the block. + // The higher, the closer is the block to the end. + [[nodiscard]] u32 GetOrder() const { + return order; + } + private: /// Memory pool for instruction list ObjectPool* inst_pool; @@ -171,6 +182,9 @@ private: /// Intrusively stored host definition of this block. u32 definition{}; + + /// Order of the block. + u32 order{}; }; using BlockList = std::vector; diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp index 3dfa5a880..e563b4022 100644 --- a/src/shader_recompiler/frontend/ir/microinstruction.cpp +++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp @@ -6,6 +6,7 @@ #include #include "shader_recompiler/exception.h" +#include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/frontend/ir/type.h" #include "shader_recompiler/frontend/ir/value.h" @@ -291,6 +292,16 @@ void Inst::AddPhiOperand(Block* predecessor, const Value& value) { phi_args.emplace_back(predecessor, value); } +void Inst::OrderPhiArgs() { + if (op != Opcode::Phi) { + throw LogicError("{} is not a Phi instruction", op); + } + std::sort(phi_args.begin(), phi_args.end(), + [](const std::pair& a, const std::pair& b) { + return a.first->GetOrder() < b.first->GetOrder(); + }); +} + void Inst::Invalidate() { ClearArgs(); ReplaceOpcode(Opcode::Void); diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 334bb47aa..6c9ef6bdd 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h @@ -182,6 +182,9 @@ public: /// Add phi operand to a phi instruction. void AddPhiOperand(Block* predecessor, const Value& value); + /// Orders the Phi arguments from farthest away to nearest. + void OrderPhiArgs(); + void Invalidate(); void ClearArgs(); diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp index 012d55357..2fc542f0e 100644 --- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp @@ -27,9 +27,11 @@ IR::BlockList GenerateBlocks(const IR::AbstractSyntaxList& syntax_list) { } IR::BlockList blocks; blocks.reserve(num_syntax_blocks); + u32 order_index{}; for (const auto& node : syntax_list) { if (node.type == IR::AbstractSyntaxNode::Type::Block) { blocks.push_back(node.data.block); + blocks.back()->SetOrder(order_index++); } } return blocks; diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp index 53145fb5e..5545f8197 100644 --- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp @@ -378,6 +378,13 @@ void SsaRewritePass(IR::Program& program) { for (auto block = program.post_order_blocks.rbegin(); block != end; ++block) { VisitBlock(pass, *block); } + for (auto block = program.post_order_blocks.rbegin(); block != end; ++block) { + for (IR::Inst& inst : (*block)->Instructions()) { + if (inst.GetOpcode() == IR::Opcode::Phi) { + inst.OrderPhiArgs(); + } + } + } } } // namespace Shader::Optimization From 194579bc4f409ba9a232afc54f19d0610102954e Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 1 Nov 2021 22:26:17 +0100 Subject: [PATCH 2/3] ShaderCache: Fix Phi Nodes Type on OGL. --- .../backend/glsl/emit_glsl_special.cpp | 4 ++-- .../frontend/ir/microinstruction.cpp | 4 ++++ .../ir_opt/ssa_rewrite_pass.cpp | 24 +++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp index 9b866f889..67f9dad68 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp @@ -68,7 +68,7 @@ void EmitPhi(EmitContext& ctx, IR::Inst& phi) { } if (!phi.Definition().is_valid) { // The phi node wasn't forward defined - ctx.var_alloc.PhiDefine(phi, phi.Arg(0).Type()); + ctx.var_alloc.PhiDefine(phi, phi.Type()); } } @@ -80,7 +80,7 @@ void EmitReference(EmitContext& ctx, const IR::Value& value) { void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& value) { IR::Inst& phi{*phi_value.InstRecursive()}; - const auto phi_type{phi.Arg(0).Type()}; + const auto phi_type{phi.Type()}; if (!phi.Definition().is_valid) { // The phi node wasn't forward defined ctx.var_alloc.PhiDefine(phi, phi_type); diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp index e563b4022..30b470bdd 100644 --- a/src/shader_recompiler/frontend/ir/microinstruction.cpp +++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp @@ -254,6 +254,10 @@ Inst* Inst::GetAssociatedPseudoOperation(IR::Opcode opcode) { } IR::Type Inst::Type() const { + if (op == IR::Opcode::Phi) { + // The type of a phi node is stored in its flags + return Flags(); + } return TypeOf(op); } diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp index 5545f8197..87aa09358 100644 --- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp @@ -14,6 +14,7 @@ // https://link.springer.com/chapter/10.1007/978-3-642-37051-9_6 // +#include #include #include #include @@ -370,6 +371,26 @@ void VisitBlock(Pass& pass, IR::Block* block) { } pass.SealBlock(block); } + +IR::Type GetConcreteType(IR::Inst* inst) { + std::deque queue; + queue.push_back(inst); + while (!queue.empty()) { + IR::Inst* current = queue.front(); + queue.pop_front(); + const size_t num_args{current->NumArgs()}; + for (size_t i = 0; i < num_args; ++i) { + const auto set_type = current->Arg(i).Type(); + if (set_type != IR::Type::Opaque) { + return set_type; + } + if (!current->Arg(i).IsImmediate()) { + queue.push_back(current->Arg(i).Inst()); + } + } + } + return IR::Type::Opaque; +} } // Anonymous namespace void SsaRewritePass(IR::Program& program) { @@ -381,6 +402,9 @@ void SsaRewritePass(IR::Program& program) { for (auto block = program.post_order_blocks.rbegin(); block != end; ++block) { for (IR::Inst& inst : (*block)->Instructions()) { if (inst.GetOpcode() == IR::Opcode::Phi) { + if (inst.Type() == IR::Type::Opaque) { + inst.SetFlags(GetConcreteType(&inst)); + } inst.OrderPhiArgs(); } } From 2d4bbd83e6f29850558fc6d741a93b5bf0d9bbb9 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 2 Nov 2021 00:59:25 +0100 Subject: [PATCH 3/3] Shader Cahe: Fix Phi Nodes on GLASM. --- .../backend/glasm/emit_glasm_not_implemented.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index ff64c6924..e537f6073 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp @@ -18,7 +18,7 @@ namespace Shader::Backend::GLASM { #define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__) static void DefinePhi(EmitContext& ctx, IR::Inst& phi) { - switch (phi.Arg(0).Type()) { + switch (phi.Type()) { case IR::Type::U1: case IR::Type::U32: case IR::Type::F32: