summaryrefslogtreecommitdiff
path: root/src/shader_recompiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler')
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_special.cpp4
-rw-r--r--src/shader_recompiler/frontend/ir/basic_block.h14
-rw-r--r--src/shader_recompiler/frontend/ir/microinstruction.cpp15
-rw-r--r--src/shader_recompiler/frontend/ir/value.h3
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate_program.cpp2
-rw-r--r--src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp31
7 files changed, 68 insertions, 3 deletions
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 {
18#define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__) 18#define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__)
19 19
20static void DefinePhi(EmitContext& ctx, IR::Inst& phi) { 20static void DefinePhi(EmitContext& ctx, IR::Inst& phi) {
21 switch (phi.Arg(0).Type()) { 21 switch (phi.Type()) {
22 case IR::Type::U1: 22 case IR::Type::U1:
23 case IR::Type::U32: 23 case IR::Type::U32:
24 case IR::Type::F32: 24 case IR::Type::F32:
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) {
68 } 68 }
69 if (!phi.Definition<Id>().is_valid) { 69 if (!phi.Definition<Id>().is_valid) {
70 // The phi node wasn't forward defined 70 // The phi node wasn't forward defined
71 ctx.var_alloc.PhiDefine(phi, phi.Arg(0).Type()); 71 ctx.var_alloc.PhiDefine(phi, phi.Type());
72 } 72 }
73} 73}
74 74
@@ -80,7 +80,7 @@ void EmitReference(EmitContext& ctx, const IR::Value& value) {
80 80
81void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& value) { 81void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& value) {
82 IR::Inst& phi{*phi_value.InstRecursive()}; 82 IR::Inst& phi{*phi_value.InstRecursive()};
83 const auto phi_type{phi.Arg(0).Type()}; 83 const auto phi_type{phi.Type()};
84 if (!phi.Definition<Id>().is_valid) { 84 if (!phi.Definition<Id>().is_valid) {
85 // The phi node wasn't forward defined 85 // The phi node wasn't forward defined
86 ctx.var_alloc.PhiDefine(phi, phi_type); 86 ctx.var_alloc.PhiDefine(phi, phi_type);
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:
152 return instructions.crend(); 152 return instructions.crend();
153 } 153 }
154 154
155 // Set the order of the block, it can be set pre order, the user decides
156 void SetOrder(u32 new_order) {
157 order = new_order;
158 }
159
160 // Get the order of the block.
161 // The higher, the closer is the block to the end.
162 [[nodiscard]] u32 GetOrder() const {
163 return order;
164 }
165
155private: 166private:
156 /// Memory pool for instruction list 167 /// Memory pool for instruction list
157 ObjectPool<Inst>* inst_pool; 168 ObjectPool<Inst>* inst_pool;
@@ -171,6 +182,9 @@ private:
171 182
172 /// Intrusively stored host definition of this block. 183 /// Intrusively stored host definition of this block.
173 u32 definition{}; 184 u32 definition{};
185
186 /// Order of the block.
187 u32 order{};
174}; 188};
175 189
176using BlockList = std::vector<Block*>; 190using BlockList = std::vector<Block*>;
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp
index 3dfa5a880..30b470bdd 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.cpp
+++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp
@@ -6,6 +6,7 @@
6#include <memory> 6#include <memory>
7 7
8#include "shader_recompiler/exception.h" 8#include "shader_recompiler/exception.h"
9#include "shader_recompiler/frontend/ir/basic_block.h"
9#include "shader_recompiler/frontend/ir/type.h" 10#include "shader_recompiler/frontend/ir/type.h"
10#include "shader_recompiler/frontend/ir/value.h" 11#include "shader_recompiler/frontend/ir/value.h"
11 12
@@ -253,6 +254,10 @@ Inst* Inst::GetAssociatedPseudoOperation(IR::Opcode opcode) {
253} 254}
254 255
255IR::Type Inst::Type() const { 256IR::Type Inst::Type() const {
257 if (op == IR::Opcode::Phi) {
258 // The type of a phi node is stored in its flags
259 return Flags<IR::Type>();
260 }
256 return TypeOf(op); 261 return TypeOf(op);
257} 262}
258 263
@@ -291,6 +296,16 @@ void Inst::AddPhiOperand(Block* predecessor, const Value& value) {
291 phi_args.emplace_back(predecessor, value); 296 phi_args.emplace_back(predecessor, value);
292} 297}
293 298
299void Inst::OrderPhiArgs() {
300 if (op != Opcode::Phi) {
301 throw LogicError("{} is not a Phi instruction", op);
302 }
303 std::sort(phi_args.begin(), phi_args.end(),
304 [](const std::pair<Block*, Value>& a, const std::pair<Block*, Value>& b) {
305 return a.first->GetOrder() < b.first->GetOrder();
306 });
307}
308
294void Inst::Invalidate() { 309void Inst::Invalidate() {
295 ClearArgs(); 310 ClearArgs();
296 ReplaceOpcode(Opcode::Void); 311 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:
182 /// Add phi operand to a phi instruction. 182 /// Add phi operand to a phi instruction.
183 void AddPhiOperand(Block* predecessor, const Value& value); 183 void AddPhiOperand(Block* predecessor, const Value& value);
184 184
185 /// Orders the Phi arguments from farthest away to nearest.
186 void OrderPhiArgs();
187
185 void Invalidate(); 188 void Invalidate();
186 void ClearArgs(); 189 void ClearArgs();
187 190
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) {
27 } 27 }
28 IR::BlockList blocks; 28 IR::BlockList blocks;
29 blocks.reserve(num_syntax_blocks); 29 blocks.reserve(num_syntax_blocks);
30 u32 order_index{};
30 for (const auto& node : syntax_list) { 31 for (const auto& node : syntax_list) {
31 if (node.type == IR::AbstractSyntaxNode::Type::Block) { 32 if (node.type == IR::AbstractSyntaxNode::Type::Block) {
32 blocks.push_back(node.data.block); 33 blocks.push_back(node.data.block);
34 blocks.back()->SetOrder(order_index++);
33 } 35 }
34 } 36 }
35 return blocks; 37 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..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 @@
14// https://link.springer.com/chapter/10.1007/978-3-642-37051-9_6 14// https://link.springer.com/chapter/10.1007/978-3-642-37051-9_6
15// 15//
16 16
17#include <deque>
17#include <span> 18#include <span>
18#include <variant> 19#include <variant>
19#include <vector> 20#include <vector>
@@ -370,6 +371,26 @@ void VisitBlock(Pass& pass, IR::Block* block) {
370 } 371 }
371 pass.SealBlock(block); 372 pass.SealBlock(block);
372} 373}
374
375IR::Type GetConcreteType(IR::Inst* inst) {
376 std::deque<IR::Inst*> queue;
377 queue.push_back(inst);
378 while (!queue.empty()) {
379 IR::Inst* current = queue.front();
380 queue.pop_front();
381 const size_t num_args{current->NumArgs()};
382 for (size_t i = 0; i < num_args; ++i) {
383 const auto set_type = current->Arg(i).Type();
384 if (set_type != IR::Type::Opaque) {
385 return set_type;
386 }
387 if (!current->Arg(i).IsImmediate()) {
388 queue.push_back(current->Arg(i).Inst());
389 }
390 }
391 }
392 return IR::Type::Opaque;
393}
373} // Anonymous namespace 394} // Anonymous namespace
374 395
375void SsaRewritePass(IR::Program& program) { 396void SsaRewritePass(IR::Program& program) {
@@ -378,6 +399,16 @@ void SsaRewritePass(IR::Program& program) {
378 for (auto block = program.post_order_blocks.rbegin(); block != end; ++block) { 399 for (auto block = program.post_order_blocks.rbegin(); block != end; ++block) {
379 VisitBlock(pass, *block); 400 VisitBlock(pass, *block);
380 } 401 }
402 for (auto block = program.post_order_blocks.rbegin(); block != end; ++block) {
403 for (IR::Inst& inst : (*block)->Instructions()) {
404 if (inst.GetOpcode() == IR::Opcode::Phi) {
405 if (inst.Type() == IR::Type::Opaque) {
406 inst.SetFlags(GetConcreteType(&inst));
407 }
408 inst.OrderPhiArgs();
409 }
410 }
411 }
381} 412}
382 413
383} // namespace Shader::Optimization 414} // namespace Shader::Optimization