diff options
Diffstat (limited to 'src')
12 files changed, 117 insertions, 25 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index fa48ba25c..775dd9e7e 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <ranges> | ||
| 5 | #include <string> | 6 | #include <string> |
| 6 | #include <tuple> | 7 | #include <tuple> |
| 7 | 8 | ||
| @@ -9,6 +10,7 @@ | |||
| 9 | #include "shader_recompiler/backend/glasm/emit_context.h" | 10 | #include "shader_recompiler/backend/glasm/emit_context.h" |
| 10 | #include "shader_recompiler/backend/glasm/emit_glasm.h" | 11 | #include "shader_recompiler/backend/glasm/emit_glasm.h" |
| 11 | #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" | 12 | #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" |
| 13 | #include "shader_recompiler/frontend/ir/ir_emitter.h" | ||
| 12 | #include "shader_recompiler/frontend/ir/program.h" | 14 | #include "shader_recompiler/frontend/ir/program.h" |
| 13 | #include "shader_recompiler/profile.h" | 15 | #include "shader_recompiler/profile.h" |
| 14 | 16 | ||
| @@ -175,6 +177,34 @@ void EmitInst(EmitContext& ctx, IR::Inst* inst) { | |||
| 175 | throw LogicError("Invalid opcode {}", inst->GetOpcode()); | 177 | throw LogicError("Invalid opcode {}", inst->GetOpcode()); |
| 176 | } | 178 | } |
| 177 | 179 | ||
| 180 | void Precolor(EmitContext& ctx, const IR::Program& program) { | ||
| 181 | for (IR::Block* const block : program.blocks) { | ||
| 182 | for (IR::Inst& phi : block->Instructions() | std::views::take_while(IR::IsPhi)) { | ||
| 183 | switch (phi.Arg(0).Type()) { | ||
| 184 | case IR::Type::U1: | ||
| 185 | case IR::Type::U32: | ||
| 186 | case IR::Type::F32: | ||
| 187 | ctx.reg_alloc.Define(phi); | ||
| 188 | break; | ||
| 189 | case IR::Type::U64: | ||
| 190 | case IR::Type::F64: | ||
| 191 | ctx.reg_alloc.LongDefine(phi); | ||
| 192 | break; | ||
| 193 | default: | ||
| 194 | throw NotImplementedException("Phi node type {}", phi.Type()); | ||
| 195 | } | ||
| 196 | const size_t num_args{phi.NumArgs()}; | ||
| 197 | for (size_t i = 0; i < num_args; ++i) { | ||
| 198 | IR::IREmitter{*phi.PhiBlock(i)}.PhiMove(phi, phi.Arg(i)); | ||
| 199 | } | ||
| 200 | // Add reference to the phi node on the phi predecessor to avoid overwritting it | ||
| 201 | for (size_t i = 0; i < num_args; ++i) { | ||
| 202 | IR::IREmitter{*phi.PhiBlock(i)}.DummyReference(IR::Value{&phi}); | ||
| 203 | } | ||
| 204 | } | ||
| 205 | } | ||
| 206 | } | ||
| 207 | |||
| 178 | void EmitCode(EmitContext& ctx, const IR::Program& program) { | 208 | void EmitCode(EmitContext& ctx, const IR::Program& program) { |
| 179 | const auto eval{ | 209 | const auto eval{ |
| 180 | [&](const IR::U1& cond) { return ScalarS32{ctx.reg_alloc.Consume(IR::Value{cond})}; }}; | 210 | [&](const IR::U1& cond) { return ScalarS32{ctx.reg_alloc.Consume(IR::Value{cond})}; }}; |
| @@ -186,7 +216,9 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { | |||
| 186 | } | 216 | } |
| 187 | break; | 217 | break; |
| 188 | case IR::AbstractSyntaxNode::Type::If: | 218 | case IR::AbstractSyntaxNode::Type::If: |
| 189 | ctx.Add("MOV.S.CC RC,{};IF NE.x;", eval(node.if_node.cond)); | 219 | ctx.Add("MOV.S.CC RC,{};" |
| 220 | "IF NE.x;", | ||
| 221 | eval(node.if_node.cond)); | ||
| 190 | break; | 222 | break; |
| 191 | case IR::AbstractSyntaxNode::Type::EndIf: | 223 | case IR::AbstractSyntaxNode::Type::EndIf: |
| 192 | ctx.Add("ENDIF;"); | 224 | ctx.Add("ENDIF;"); |
| @@ -195,10 +227,30 @@ void EmitCode(EmitContext& ctx, const IR::Program& program) { | |||
| 195 | ctx.Add("REP;"); | 227 | ctx.Add("REP;"); |
| 196 | break; | 228 | break; |
| 197 | case IR::AbstractSyntaxNode::Type::Repeat: | 229 | case IR::AbstractSyntaxNode::Type::Repeat: |
| 198 | ctx.Add("MOV.S.CC RC,{};BRK NE.x;ENDREP;", eval(node.repeat.cond)); | 230 | if (node.repeat.cond.IsImmediate()) { |
| 231 | if (node.repeat.cond.U1()) { | ||
| 232 | ctx.Add("ENDREP;"); | ||
| 233 | } else { | ||
| 234 | ctx.Add("BRK;" | ||
| 235 | "ENDREP;"); | ||
| 236 | } | ||
| 237 | } else { | ||
| 238 | ctx.Add("MOV.S.CC RC,{};" | ||
| 239 | "BRK (EQ.x);" | ||
| 240 | "ENDREP;", | ||
| 241 | eval(node.repeat.cond)); | ||
| 242 | } | ||
| 199 | break; | 243 | break; |
| 200 | case IR::AbstractSyntaxNode::Type::Break: | 244 | case IR::AbstractSyntaxNode::Type::Break: |
| 201 | ctx.Add("MOV.S.CC RC,{};BRK NE.x;", eval(node.repeat.cond)); | 245 | if (node.break_node.cond.IsImmediate()) { |
| 246 | if (node.break_node.cond.U1()) { | ||
| 247 | ctx.Add("BRK;"); | ||
| 248 | } | ||
| 249 | } else { | ||
| 250 | ctx.Add("MOV.S.CC RC,{};" | ||
| 251 | "BRK (NE.x);", | ||
| 252 | eval(node.break_node.cond)); | ||
| 253 | } | ||
| 202 | break; | 254 | break; |
| 203 | case IR::AbstractSyntaxNode::Type::Return: | 255 | case IR::AbstractSyntaxNode::Type::Return: |
| 204 | case IR::AbstractSyntaxNode::Type::Unreachable: | 256 | case IR::AbstractSyntaxNode::Type::Unreachable: |
| @@ -233,6 +285,7 @@ void SetupOptions(std::string& header, Info info) { | |||
| 233 | 285 | ||
| 234 | std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { | 286 | std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { |
| 235 | EmitContext ctx{program}; | 287 | EmitContext ctx{program}; |
| 288 | Precolor(ctx, program); | ||
| 236 | EmitCode(ctx, program); | 289 | EmitCode(ctx, program); |
| 237 | std::string header = "!!NVcp5.0\n" | 290 | std::string header = "!!NVcp5.0\n" |
| 238 | "OPTION NV_internal;"; | 291 | "OPTION NV_internal;"; |
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 0f7f16e6e..a74e422d6 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | |||
| @@ -22,7 +22,8 @@ class EmitContext; | |||
| 22 | void EmitPhi(EmitContext& ctx, IR::Inst& inst); | 22 | void EmitPhi(EmitContext& ctx, IR::Inst& inst); |
| 23 | void EmitVoid(EmitContext& ctx); | 23 | void EmitVoid(EmitContext& ctx); |
| 24 | void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); | 24 | void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); |
| 25 | void EmitBranchConditionRef(EmitContext&); | 25 | void EmitDummyReference(EmitContext&); |
| 26 | void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value); | ||
| 26 | void EmitJoin(EmitContext& ctx); | 27 | void EmitJoin(EmitContext& ctx); |
| 27 | void EmitDemoteToHelperInvocation(EmitContext& ctx); | 28 | void EmitDemoteToHelperInvocation(EmitContext& ctx); |
| 28 | void EmitBarrier(EmitContext& ctx); | 29 | void EmitBarrier(EmitContext& ctx); |
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 f37ad5587..969b91a81 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | |||
| @@ -17,13 +17,32 @@ 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 | void EmitPhi(EmitContext&, IR::Inst&) {} |
| 21 | NotImplemented(); | ||
| 22 | } | ||
| 23 | 21 | ||
| 24 | void EmitVoid(EmitContext&) {} | 22 | void EmitVoid(EmitContext&) {} |
| 25 | 23 | ||
| 26 | void EmitBranchConditionRef(EmitContext&) {} | 24 | void EmitDummyReference(EmitContext&) {} |
| 25 | |||
| 26 | void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value) { | ||
| 27 | if (phi == value) { | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | const Register phi_reg{ctx.reg_alloc.Consume(phi)}; | ||
| 31 | const Value eval_value{ctx.reg_alloc.Consume(value)}; | ||
| 32 | switch (phi.InstRecursive()->Arg(0).Type()) { | ||
| 33 | case IR::Type::U1: | ||
| 34 | case IR::Type::U32: | ||
| 35 | case IR::Type::F32: | ||
| 36 | ctx.Add("MOV.S {}.x,{};", phi_reg, ScalarS32{eval_value}); | ||
| 37 | break; | ||
| 38 | case IR::Type::U64: | ||
| 39 | case IR::Type::F64: | ||
| 40 | ctx.Add("MOV.U64 {}.x,{};", phi_reg, ScalarRegister{eval_value}); | ||
| 41 | break; | ||
| 42 | default: | ||
| 43 | throw NotImplementedException("Phi node type {}", phi.Type()); | ||
| 44 | } | ||
| 45 | } | ||
| 27 | 46 | ||
| 28 | void EmitJoin(EmitContext& ctx) { | 47 | void EmitJoin(EmitContext& ctx) { |
| 29 | NotImplemented(); | 48 | NotImplemented(); |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index c22edfec2..7bf8c78de 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp | |||
| @@ -468,7 +468,11 @@ Id EmitIdentity(EmitContext& ctx, const IR::Value& value) { | |||
| 468 | return id; | 468 | return id; |
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | void EmitBranchConditionRef(EmitContext&) {} | 471 | void EmitDummyReference(EmitContext&) {} |
| 472 | |||
| 473 | void EmitPhiMove(EmitContext&) { | ||
| 474 | throw LogicError("Unreachable instruction"); | ||
| 475 | } | ||
| 472 | 476 | ||
| 473 | void EmitGetZeroFromOp(EmitContext&) { | 477 | void EmitGetZeroFromOp(EmitContext&) { |
| 474 | throw LogicError("Unreachable instruction"); | 478 | throw LogicError("Unreachable instruction"); |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 2f4f6e59e..0a2b31772 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h | |||
| @@ -23,7 +23,8 @@ class EmitContext; | |||
| 23 | Id EmitPhi(EmitContext& ctx, IR::Inst* inst); | 23 | Id EmitPhi(EmitContext& ctx, IR::Inst* inst); |
| 24 | void EmitVoid(EmitContext& ctx); | 24 | void EmitVoid(EmitContext& ctx); |
| 25 | Id EmitIdentity(EmitContext& ctx, const IR::Value& value); | 25 | Id EmitIdentity(EmitContext& ctx, const IR::Value& value); |
| 26 | void EmitBranchConditionRef(EmitContext&); | 26 | void EmitDummyReference(EmitContext&); |
| 27 | void EmitPhiMove(EmitContext&); | ||
| 27 | void EmitJoin(EmitContext& ctx); | 28 | void EmitJoin(EmitContext& ctx); |
| 28 | void EmitDemoteToHelperInvocation(EmitContext& ctx); | 29 | void EmitDemoteToHelperInvocation(EmitContext& ctx); |
| 29 | void EmitBarrier(EmitContext& ctx); | 30 | void EmitBarrier(EmitContext& ctx); |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index eb45aa477..def29143e 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -61,6 +61,14 @@ F64 IREmitter::Imm64(f64 value) const { | |||
| 61 | return F64{Value{value}}; | 61 | return F64{Value{value}}; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | void IREmitter::DummyReference(const Value& value) { | ||
| 65 | Inst(Opcode::DummyReference, value); | ||
| 66 | } | ||
| 67 | |||
| 68 | void IREmitter::PhiMove(IR::Inst& phi, const Value& value) { | ||
| 69 | Inst(Opcode::PhiMove, Value{&phi}, value); | ||
| 70 | } | ||
| 71 | |||
| 64 | void IREmitter::Prologue() { | 72 | void IREmitter::Prologue() { |
| 65 | Inst(Opcode::Prologue); | 73 | Inst(Opcode::Prologue); |
| 66 | } | 74 | } |
| @@ -69,10 +77,6 @@ void IREmitter::Epilogue() { | |||
| 69 | Inst(Opcode::Epilogue); | 77 | Inst(Opcode::Epilogue); |
| 70 | } | 78 | } |
| 71 | 79 | ||
| 72 | void IREmitter::BranchConditionRef(const U1& cond) { | ||
| 73 | Inst(Opcode::BranchConditionRef, cond); | ||
| 74 | } | ||
| 75 | |||
| 76 | void IREmitter::DemoteToHelperInvocation() { | 80 | void IREmitter::DemoteToHelperInvocation() { |
| 77 | Inst(Opcode::DemoteToHelperInvocation); | 81 | Inst(Opcode::DemoteToHelperInvocation); |
| 78 | } | 82 | } |
| @@ -106,6 +110,9 @@ void IREmitter::SetReg(IR::Reg reg, const U32& value) { | |||
| 106 | } | 110 | } |
| 107 | 111 | ||
| 108 | U1 IREmitter::GetPred(IR::Pred pred, bool is_negated) { | 112 | U1 IREmitter::GetPred(IR::Pred pred, bool is_negated) { |
| 113 | if (pred == Pred::PT) { | ||
| 114 | return Imm1(!is_negated); | ||
| 115 | } | ||
| 109 | const U1 value{Inst<U1>(Opcode::GetPred, pred)}; | 116 | const U1 value{Inst<U1>(Opcode::GetPred, pred)}; |
| 110 | if (is_negated) { | 117 | if (is_negated) { |
| 111 | return Inst<U1>(Opcode::LogicalNot, value); | 118 | return Inst<U1>(Opcode::LogicalNot, value); |
| @@ -264,6 +271,9 @@ static U1 GetFlowTest(IREmitter& ir, FlowTest flow_test) { | |||
| 264 | U1 IREmitter::Condition(IR::Condition cond) { | 271 | U1 IREmitter::Condition(IR::Condition cond) { |
| 265 | const FlowTest flow_test{cond.GetFlowTest()}; | 272 | const FlowTest flow_test{cond.GetFlowTest()}; |
| 266 | const auto [pred, is_negated]{cond.GetPred()}; | 273 | const auto [pred, is_negated]{cond.GetPred()}; |
| 274 | if (flow_test == FlowTest::T) { | ||
| 275 | return GetPred(pred, is_negated); | ||
| 276 | } | ||
| 267 | return LogicalAnd(GetPred(pred, is_negated), GetFlowTest(*this, flow_test)); | 277 | return LogicalAnd(GetPred(pred, is_negated), GetFlowTest(*this, flow_test)); |
| 268 | } | 278 | } |
| 269 | 279 | ||
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 7a83c33d3..4f7c820fe 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -32,9 +32,11 @@ public: | |||
| 32 | [[nodiscard]] U64 Imm64(s64 value) const; | 32 | [[nodiscard]] U64 Imm64(s64 value) const; |
| 33 | [[nodiscard]] F64 Imm64(f64 value) const; | 33 | [[nodiscard]] F64 Imm64(f64 value) const; |
| 34 | 34 | ||
| 35 | void DummyReference(const Value& value); | ||
| 36 | void PhiMove(IR::Inst& phi, const Value& value); | ||
| 37 | |||
| 35 | void Prologue(); | 38 | void Prologue(); |
| 36 | void Epilogue(); | 39 | void Epilogue(); |
| 37 | void BranchConditionRef(const U1& cond); | ||
| 38 | void DemoteToHelperInvocation(); | 40 | void DemoteToHelperInvocation(); |
| 39 | void EmitVertex(const U32& stream); | 41 | void EmitVertex(const U32& stream); |
| 40 | void EndPrimitive(const U32& stream); | 42 | void EndPrimitive(const U32& stream); |
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp index 364574240..267aebc61 100644 --- a/src/shader_recompiler/frontend/ir/microinstruction.cpp +++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp | |||
| @@ -56,9 +56,10 @@ Inst::~Inst() { | |||
| 56 | 56 | ||
| 57 | bool Inst::MayHaveSideEffects() const noexcept { | 57 | bool Inst::MayHaveSideEffects() const noexcept { |
| 58 | switch (op) { | 58 | switch (op) { |
| 59 | case Opcode::DummyReference: | ||
| 60 | case Opcode::PhiMove: | ||
| 59 | case Opcode::Prologue: | 61 | case Opcode::Prologue: |
| 60 | case Opcode::Epilogue: | 62 | case Opcode::Epilogue: |
| 61 | case Opcode::BranchConditionRef: | ||
| 62 | case Opcode::Join: | 63 | case Opcode::Join: |
| 63 | case Opcode::DemoteToHelperInvocation: | 64 | case Opcode::DemoteToHelperInvocation: |
| 64 | case Opcode::Barrier: | 65 | case Opcode::Barrier: |
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 75ddb6b6f..6196b867d 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc | |||
| @@ -6,11 +6,12 @@ | |||
| 6 | OPCODE(Phi, Opaque, ) | 6 | OPCODE(Phi, Opaque, ) |
| 7 | OPCODE(Identity, Opaque, Opaque, ) | 7 | OPCODE(Identity, Opaque, Opaque, ) |
| 8 | OPCODE(Void, Void, ) | 8 | OPCODE(Void, Void, ) |
| 9 | OPCODE(DummyReference, Void, Opaque, ) | ||
| 10 | OPCODE(PhiMove, Void, Opaque, Opaque, ) | ||
| 9 | 11 | ||
| 10 | // Special operations | 12 | // Special operations |
| 11 | OPCODE(Prologue, Void, ) | 13 | OPCODE(Prologue, Void, ) |
| 12 | OPCODE(Epilogue, Void, ) | 14 | OPCODE(Epilogue, Void, ) |
| 13 | OPCODE(BranchConditionRef, Void, U1, ) | ||
| 14 | OPCODE(Join, Void, ) | 15 | OPCODE(Join, Void, ) |
| 15 | OPCODE(DemoteToHelperInvocation, Void, ) | 16 | OPCODE(DemoteToHelperInvocation, Void, ) |
| 16 | OPCODE(EmitVertex, Void, U32, ) | 17 | OPCODE(EmitVertex, Void, U32, ) |
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 2ce49f953..0c6bf684d 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h | |||
| @@ -391,4 +391,8 @@ inline f64 Value::F64() const { | |||
| 391 | return imm_f64; | 391 | return imm_f64; |
| 392 | } | 392 | } |
| 393 | 393 | ||
| 394 | [[nodiscard]] inline bool IsPhi(const Inst& inst) { | ||
| 395 | return inst.GetOpcode() == Opcode::Phi; | ||
| 396 | } | ||
| 397 | |||
| 394 | } // namespace Shader::IR | 398 | } // namespace Shader::IR |
diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index e7e2e9c82..836d4b8aa 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp | |||
| @@ -704,7 +704,7 @@ private: | |||
| 704 | // Implement if header block | 704 | // Implement if header block |
| 705 | IR::IREmitter ir{*current_block}; | 705 | IR::IREmitter ir{*current_block}; |
| 706 | const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; | 706 | const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; |
| 707 | ir.BranchConditionRef(cond); | 707 | ir.DummyReference(cond); |
| 708 | 708 | ||
| 709 | const size_t if_node_index{syntax_list.size()}; | 709 | const size_t if_node_index{syntax_list.size()}; |
| 710 | syntax_list.emplace_back(); | 710 | syntax_list.emplace_back(); |
| @@ -755,7 +755,7 @@ private: | |||
| 755 | // The continue block is located at the end of the loop | 755 | // The continue block is located at the end of the loop |
| 756 | IR::IREmitter ir{*continue_block}; | 756 | IR::IREmitter ir{*continue_block}; |
| 757 | const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; | 757 | const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; |
| 758 | ir.BranchConditionRef(cond); | 758 | ir.DummyReference(cond); |
| 759 | 759 | ||
| 760 | IR::Block* const body_block{syntax_list.at(body_block_index).block}; | 760 | IR::Block* const body_block{syntax_list.at(body_block_index).block}; |
| 761 | loop_header_block->AddBranch(body_block); | 761 | loop_header_block->AddBranch(body_block); |
| @@ -792,7 +792,7 @@ private: | |||
| 792 | 792 | ||
| 793 | IR::IREmitter ir{*current_block}; | 793 | IR::IREmitter ir{*current_block}; |
| 794 | const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; | 794 | const IR::U1 cond{VisitExpr(ir, *stmt.cond)}; |
| 795 | ir.BranchConditionRef(cond); | 795 | ir.DummyReference(cond); |
| 796 | current_block->AddBranch(break_block); | 796 | current_block->AddBranch(break_block); |
| 797 | current_block->AddBranch(skip_block); | 797 | current_block->AddBranch(skip_block); |
| 798 | current_block = skip_block; | 798 | current_block = skip_block; |
diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp index 26eb3a3ab..e54499ba5 100644 --- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | |||
| @@ -138,10 +138,6 @@ IR::Opcode UndefOpcode(IndirectBranchVariable) noexcept { | |||
| 138 | return IR::Opcode::UndefU32; | 138 | return IR::Opcode::UndefU32; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | [[nodiscard]] bool IsPhi(const IR::Inst& inst) noexcept { | ||
| 142 | return inst.GetOpcode() == IR::Opcode::Phi; | ||
| 143 | } | ||
| 144 | |||
| 145 | enum class Status { | 141 | enum class Status { |
| 146 | Start, | 142 | Start, |
| 147 | SetValue, | 143 | SetValue, |
| @@ -283,7 +279,7 @@ private: | |||
| 283 | list.erase(IR::Block::InstructionList::s_iterator_to(phi)); | 279 | list.erase(IR::Block::InstructionList::s_iterator_to(phi)); |
| 284 | 280 | ||
| 285 | // Find the first non-phi instruction and use it as an insertion point | 281 | // Find the first non-phi instruction and use it as an insertion point |
| 286 | IR::Block::iterator reinsert_point{std::ranges::find_if_not(list, IsPhi)}; | 282 | IR::Block::iterator reinsert_point{std::ranges::find_if_not(list, IR::IsPhi)}; |
| 287 | if (same.IsEmpty()) { | 283 | if (same.IsEmpty()) { |
| 288 | // The phi is unreachable or in the start block | 284 | // The phi is unreachable or in the start block |
| 289 | // Insert an undefined instruction and make it the phi node replacement | 285 | // Insert an undefined instruction and make it the phi node replacement |