diff options
Diffstat (limited to 'src/shader_recompiler/backend/glasm')
| -rw-r--r-- | src/shader_recompiler/backend/glasm/emit_glasm.cpp | 53 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | 39 |
2 files changed, 54 insertions, 38 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 5ffefaad2..4f838b699 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp | |||
| @@ -172,38 +172,29 @@ bool IsReference(IR::Inst& inst) { | |||
| 172 | return inst.GetOpcode() == IR::Opcode::Reference; | 172 | return inst.GetOpcode() == IR::Opcode::Reference; |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | void Precolor(EmitContext& ctx, const IR::Program& program) { | 175 | void PrecolorInst(IR::Inst& phi) { |
| 176 | // Insert phi moves before references to avoid overwritting other phis | ||
| 177 | const size_t num_args{phi.NumArgs()}; | ||
| 178 | for (size_t i = 0; i < num_args; ++i) { | ||
| 179 | IR::Block& phi_block{*phi.PhiBlock(i)}; | ||
| 180 | auto it{std::find_if_not(phi_block.rbegin(), phi_block.rend(), IsReference).base()}; | ||
| 181 | IR::IREmitter ir{phi_block, it}; | ||
| 182 | const IR::Value arg{phi.Arg(i)}; | ||
| 183 | if (arg.IsImmediate()) { | ||
| 184 | ir.PhiMove(phi, arg); | ||
| 185 | } else { | ||
| 186 | ir.PhiMove(phi, IR::Value{&RegAlloc::AliasInst(*arg.Inst())}); | ||
| 187 | } | ||
| 188 | } | ||
| 189 | for (size_t i = 0; i < num_args; ++i) { | ||
| 190 | IR::IREmitter{*phi.PhiBlock(i)}.Reference(IR::Value{&phi}); | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | void Precolor(const IR::Program& program) { | ||
| 176 | for (IR::Block* const block : program.blocks) { | 195 | for (IR::Block* const block : program.blocks) { |
| 177 | for (IR::Inst& phi : block->Instructions() | std::views::take_while(IR::IsPhi)) { | 196 | for (IR::Inst& phi : block->Instructions() | std::views::take_while(IR::IsPhi)) { |
| 178 | switch (phi.Arg(0).Type()) { | 197 | PrecolorInst(phi); |
| 179 | case IR::Type::U1: | ||
| 180 | case IR::Type::U32: | ||
| 181 | case IR::Type::F32: | ||
| 182 | ctx.reg_alloc.Define(phi); | ||
| 183 | break; | ||
| 184 | case IR::Type::U64: | ||
| 185 | case IR::Type::F64: | ||
| 186 | ctx.reg_alloc.LongDefine(phi); | ||
| 187 | break; | ||
| 188 | default: | ||
| 189 | throw NotImplementedException("Phi node type {}", phi.Type()); | ||
| 190 | } | ||
| 191 | // Insert phi moves before references to avoid overwritting them | ||
| 192 | const size_t num_args{phi.NumArgs()}; | ||
| 193 | for (size_t i = 0; i < num_args; ++i) { | ||
| 194 | IR::Block& phi_block{*phi.PhiBlock(i)}; | ||
| 195 | auto it{std::find_if_not(phi_block.rbegin(), phi_block.rend(), IsReference).base()}; | ||
| 196 | IR::IREmitter ir{phi_block, it}; | ||
| 197 | const IR::Value arg{phi.Arg(i)}; | ||
| 198 | if (arg.IsImmediate()) { | ||
| 199 | ir.PhiMove(phi, arg); | ||
| 200 | } else { | ||
| 201 | ir.PhiMove(phi, IR::Value{&RegAlloc::AliasInst(*arg.Inst())}); | ||
| 202 | } | ||
| 203 | } | ||
| 204 | for (size_t i = 0; i < num_args; ++i) { | ||
| 205 | IR::IREmitter{*phi.PhiBlock(i)}.Reference(IR::Value{&phi}); | ||
| 206 | } | ||
| 207 | } | 198 | } |
| 208 | } | 199 | } |
| 209 | } | 200 | } |
| @@ -388,7 +379,7 @@ std::string_view GetTessSpacing(TessSpacing spacing) { | |||
| 388 | std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, IR::Program& program, | 379 | std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, IR::Program& program, |
| 389 | Bindings& bindings) { | 380 | Bindings& bindings) { |
| 390 | EmitContext ctx{program, bindings, profile, runtime_info}; | 381 | EmitContext ctx{program, bindings, profile, runtime_info}; |
| 391 | Precolor(ctx, program); | 382 | Precolor(program); |
| 392 | EmitCode(ctx, program); | 383 | EmitCode(ctx, program); |
| 393 | std::string header{StageHeader(program.stage)}; | 384 | std::string header{StageHeader(program.stage)}; |
| 394 | SetupOptions(program, profile, runtime_info, header); | 385 | SetupOptions(program, profile, runtime_info, header); |
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 3d7a3ebb4..e9d1e0d6b 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | |||
| @@ -17,10 +17,30 @@ namespace Shader::Backend::GLASM { | |||
| 17 | 17 | ||
| 18 | #define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__) | 18 | #define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__) |
| 19 | 19 | ||
| 20 | void EmitPhi(EmitContext& ctx, IR::Inst& inst) { | 20 | static void DefinePhi(EmitContext& ctx, IR::Inst& phi) { |
| 21 | const size_t num_args{inst.NumArgs()}; | 21 | switch (phi.Arg(0).Type()) { |
| 22 | case IR::Type::U1: | ||
| 23 | case IR::Type::U32: | ||
| 24 | case IR::Type::F32: | ||
| 25 | ctx.reg_alloc.Define(phi); | ||
| 26 | break; | ||
| 27 | case IR::Type::U64: | ||
| 28 | case IR::Type::F64: | ||
| 29 | ctx.reg_alloc.LongDefine(phi); | ||
| 30 | break; | ||
| 31 | default: | ||
| 32 | throw NotImplementedException("Phi node type {}", phi.Type()); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | void EmitPhi(EmitContext& ctx, IR::Inst& phi) { | ||
| 37 | const size_t num_args{phi.NumArgs()}; | ||
| 22 | for (size_t i = 0; i < num_args; ++i) { | 38 | for (size_t i = 0; i < num_args; ++i) { |
| 23 | ctx.reg_alloc.Consume(inst.Arg(i)); | 39 | ctx.reg_alloc.Consume(phi.Arg(i)); |
| 40 | } | ||
| 41 | if (!phi.Definition<Id>().is_valid) { | ||
| 42 | // The phi node wasn't forward defined | ||
| 43 | DefinePhi(ctx, phi); | ||
| 24 | } | 44 | } |
| 25 | } | 45 | } |
| 26 | 46 | ||
| @@ -30,14 +50,19 @@ void EmitReference(EmitContext& ctx, const IR::Value& value) { | |||
| 30 | ctx.reg_alloc.Consume(value); | 50 | ctx.reg_alloc.Consume(value); |
| 31 | } | 51 | } |
| 32 | 52 | ||
| 33 | void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value) { | 53 | void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& value) { |
| 34 | const Register phi_reg{ctx.reg_alloc.Consume(phi)}; | 54 | IR::Inst& phi{RegAlloc::AliasInst(*phi_value.Inst())}; |
| 55 | if (!phi.Definition<Id>().is_valid) { | ||
| 56 | // The phi node wasn't forward defined | ||
| 57 | DefinePhi(ctx, phi); | ||
| 58 | } | ||
| 59 | const Register phi_reg{ctx.reg_alloc.Consume(IR::Value{&phi})}; | ||
| 35 | const Value eval_value{ctx.reg_alloc.Consume(value)}; | 60 | const Value eval_value{ctx.reg_alloc.Consume(value)}; |
| 36 | 61 | ||
| 37 | if (phi == value) { | 62 | if (phi_reg == eval_value) { |
| 38 | return; | 63 | return; |
| 39 | } | 64 | } |
| 40 | switch (phi.Inst()->Flags<IR::Type>()) { | 65 | switch (phi.Flags<IR::Type>()) { |
| 41 | case IR::Type::U1: | 66 | case IR::Type::U1: |
| 42 | case IR::Type::U32: | 67 | case IR::Type::U32: |
| 43 | case IR::Type::F32: | 68 | case IR::Type::F32: |