Merge pull request #7262 from FernandoS27/Buffalo-buffalo-Buffalo-buffalo-buffalo
ShaderCache: Order Phi Arguments from farthest away to nearest.
This commit is contained in:
		| @@ -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: | ||||
|   | ||||
| @@ -68,7 +68,7 @@ void EmitPhi(EmitContext& ctx, IR::Inst& phi) { | ||||
|     } | ||||
|     if (!phi.Definition<Id>().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<Id>().is_valid) { | ||||
|         // The phi node wasn't forward defined | ||||
|         ctx.var_alloc.PhiDefine(phi, phi_type); | ||||
|   | ||||
| @@ -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>* 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<Block*>; | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| #include <memory> | ||||
|  | ||||
| #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" | ||||
|  | ||||
| @@ -253,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<IR::Type>(); | ||||
|     } | ||||
|     return TypeOf(op); | ||||
| } | ||||
|  | ||||
| @@ -291,6 +296,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<Block*, Value>& a, const std::pair<Block*, Value>& b) { | ||||
|                   return a.first->GetOrder() < b.first->GetOrder(); | ||||
|               }); | ||||
| } | ||||
|  | ||||
| void Inst::Invalidate() { | ||||
|     ClearArgs(); | ||||
|     ReplaceOpcode(Opcode::Void); | ||||
|   | ||||
| @@ -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(); | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
| //      https://link.springer.com/chapter/10.1007/978-3-642-37051-9_6 | ||||
| // | ||||
|  | ||||
| #include <deque> | ||||
| #include <span> | ||||
| #include <variant> | ||||
| #include <vector> | ||||
| @@ -370,6 +371,26 @@ void VisitBlock(Pass& pass, IR::Block* block) { | ||||
|     } | ||||
|     pass.SealBlock(block); | ||||
| } | ||||
|  | ||||
| IR::Type GetConcreteType(IR::Inst* inst) { | ||||
|     std::deque<IR::Inst*> 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) { | ||||
| @@ -378,6 +399,16 @@ 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) { | ||||
|                 if (inst.Type() == IR::Type::Opaque) { | ||||
|                     inst.SetFlags(GetConcreteType(&inst)); | ||||
|                 } | ||||
|                 inst.OrderPhiArgs(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| } // namespace Shader::Optimization | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 bunnei
					bunnei