diff options
Diffstat (limited to 'src/shader_recompiler/frontend')
8 files changed, 39 insertions, 20 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 8ba86e614..0209d5540 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -134,18 +134,27 @@ void IREmitter::SetOFlag(const U1& value) { | |||
| 134 | Inst(Opcode::SetOFlag, value); | 134 | Inst(Opcode::SetOFlag, value); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | U1 IREmitter::Condition(IR::Condition cond) { | 137 | static U1 GetFlowTest(IREmitter& ir, FlowTest flow_test) { |
| 138 | if (cond == IR::Condition{true}) { | 138 | switch (flow_test) { |
| 139 | return Imm1(true); | 139 | case FlowTest::T: |
| 140 | } else if (cond == IR::Condition{false}) { | 140 | return ir.Imm1(true); |
| 141 | return Imm1(false); | 141 | case FlowTest::F: |
| 142 | return ir.Imm1(false); | ||
| 143 | case FlowTest::EQ: | ||
| 144 | // TODO: Test this | ||
| 145 | return ir.GetZFlag(); | ||
| 146 | case FlowTest::NE: | ||
| 147 | // TODO: Test this | ||
| 148 | return ir.LogicalNot(ir.GetZFlag()); | ||
| 149 | default: | ||
| 150 | throw NotImplementedException("Flow test {}", flow_test); | ||
| 142 | } | 151 | } |
| 152 | } | ||
| 153 | |||
| 154 | U1 IREmitter::Condition(IR::Condition cond) { | ||
| 143 | const FlowTest flow_test{cond.FlowTest()}; | 155 | const FlowTest flow_test{cond.FlowTest()}; |
| 144 | const auto [pred, is_negated]{cond.Pred()}; | 156 | const auto [pred, is_negated]{cond.Pred()}; |
| 145 | if (flow_test == FlowTest::T) { | 157 | return LogicalAnd(GetPred(pred, is_negated), GetFlowTest(*this, flow_test)); |
| 146 | return GetPred(pred, is_negated); | ||
| 147 | } | ||
| 148 | throw NotImplementedException("Condition {}", cond); | ||
| 149 | } | 158 | } |
| 150 | 159 | ||
| 151 | F32 IREmitter::GetAttribute(IR::Attribute attribute) { | 160 | F32 IREmitter::GetAttribute(IR::Attribute attribute) { |
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index f2d71144a..289e76f32 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | // opcode name, return type, arg1 type, arg2 type, arg3 type, arg4 type, ... | 5 | // opcode name, return type, arg1 type, arg2 type, arg3 type, arg4 type, ... |
| 6 | OPCODE(Phi, Opaque, ) | 6 | OPCODE(Phi, Opaque, ) |
| 7 | OPCODE(Void, Void, ) | ||
| 8 | OPCODE(Identity, Opaque, Opaque, ) | 7 | OPCODE(Identity, Opaque, Opaque, ) |
| 8 | OPCODE(Void, Void, ) | ||
| 9 | 9 | ||
| 10 | // Control flow | 10 | // Control flow |
| 11 | OPCODE(Branch, Void, Label, ) | 11 | OPCODE(Branch, Void, Label, ) |
diff --git a/src/shader_recompiler/frontend/ir/structured_control_flow.cpp b/src/shader_recompiler/frontend/ir/structured_control_flow.cpp index 032ac8fda..bfba55a7e 100644 --- a/src/shader_recompiler/frontend/ir/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/ir/structured_control_flow.cpp | |||
| @@ -329,7 +329,6 @@ private: | |||
| 329 | if (!sibling) { | 329 | if (!sibling) { |
| 330 | throw LogicError("Not siblings"); | 330 | throw LogicError("Not siblings"); |
| 331 | } | 331 | } |
| 332 | |||
| 333 | // goto_stmt and label_stmt are guaranteed to be siblings, eliminate | 332 | // goto_stmt and label_stmt are guaranteed to be siblings, eliminate |
| 334 | if (std::next(goto_stmt) == label_stmt) { | 333 | if (std::next(goto_stmt) == label_stmt) { |
| 335 | // Simply eliminate the goto if the label is next to it | 334 | // Simply eliminate the goto if the label is next to it |
| @@ -351,9 +350,14 @@ private: | |||
| 351 | const std::unordered_map labels_map{BuildLabels(blocks)}; | 350 | const std::unordered_map labels_map{BuildLabels(blocks)}; |
| 352 | Tree& root{root_stmt.children}; | 351 | Tree& root{root_stmt.children}; |
| 353 | auto insert_point{root.begin()}; | 352 | auto insert_point{root.begin()}; |
| 353 | // Skip all goto variables zero-initialization | ||
| 354 | std::advance(insert_point, labels_map.size()); | ||
| 355 | |||
| 354 | for (Block* const block : blocks) { | 356 | for (Block* const block : blocks) { |
| 355 | ++insert_point; // Skip label | 357 | // Skip label |
| 356 | ++insert_point; // Skip set variable | 358 | ++insert_point; |
| 359 | // Skip set variable | ||
| 360 | ++insert_point; | ||
| 357 | root.insert(insert_point, *pool.Create(block, &root_stmt)); | 361 | root.insert(insert_point, *pool.Create(block, &root_stmt)); |
| 358 | 362 | ||
| 359 | if (block->IsTerminationBlock()) { | 363 | if (block->IsTerminationBlock()) { |
| @@ -391,6 +395,7 @@ private: | |||
| 391 | labels_map.emplace(block, root.insert(root.end(), *label)); | 395 | labels_map.emplace(block, root.insert(root.end(), *label)); |
| 392 | Statement* const false_stmt{pool.Create(Identity{}, Condition{false})}; | 396 | Statement* const false_stmt{pool.Create(Identity{}, Condition{false})}; |
| 393 | root.push_back(*pool.Create(SetVariable{}, label_id, false_stmt, &root_stmt)); | 397 | root.push_back(*pool.Create(SetVariable{}, label_id, false_stmt, &root_stmt)); |
| 398 | root.push_front(*pool.Create(SetVariable{}, label_id, false_stmt, &root_stmt)); | ||
| 394 | ++label_id; | 399 | ++label_id; |
| 395 | } | 400 | } |
| 396 | return labels_map; | 401 | return labels_map; |
| @@ -457,10 +462,10 @@ private: | |||
| 457 | } | 462 | } |
| 458 | body.erase(goto_stmt); | 463 | body.erase(goto_stmt); |
| 459 | 464 | ||
| 460 | // Update nested if condition | ||
| 461 | switch (label_nested_stmt->type) { | 465 | switch (label_nested_stmt->type) { |
| 462 | case StatementType::If: | 466 | case StatementType::If: |
| 463 | label_nested_stmt->cond = pool.Create(Or{}, neg_var, label_nested_stmt->cond); | 467 | // Update nested if condition |
| 468 | label_nested_stmt->cond = pool.Create(Or{}, variable, label_nested_stmt->cond); | ||
| 464 | break; | 469 | break; |
| 465 | case StatementType::Loop: | 470 | case StatementType::Loop: |
| 466 | break; | 471 | break; |
diff --git a/src/shader_recompiler/frontend/ir/value.cpp b/src/shader_recompiler/frontend/ir/value.cpp index 718314213..791ba2690 100644 --- a/src/shader_recompiler/frontend/ir/value.cpp +++ b/src/shader_recompiler/frontend/ir/value.cpp | |||
| @@ -36,6 +36,10 @@ bool Value::IsIdentity() const noexcept { | |||
| 36 | return type == Type::Opaque && inst->Opcode() == Opcode::Identity; | 36 | return type == Type::Opaque && inst->Opcode() == Opcode::Identity; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | bool Value::IsPhi() const noexcept { | ||
| 40 | return type == Type::Opaque && inst->Opcode() == Opcode::Phi; | ||
| 41 | } | ||
| 42 | |||
| 39 | bool Value::IsEmpty() const noexcept { | 43 | bool Value::IsEmpty() const noexcept { |
| 40 | return type == Type::Void; | 44 | return type == Type::Void; |
| 41 | } | 45 | } |
| @@ -52,7 +56,7 @@ bool Value::IsLabel() const noexcept { | |||
| 52 | } | 56 | } |
| 53 | 57 | ||
| 54 | IR::Type Value::Type() const noexcept { | 58 | IR::Type Value::Type() const noexcept { |
| 55 | if (IsIdentity()) { | 59 | if (IsIdentity() || IsPhi()) { |
| 56 | return inst->Arg(0).Type(); | 60 | return inst->Arg(0).Type(); |
| 57 | } | 61 | } |
| 58 | if (type == Type::Opaque) { | 62 | if (type == Type::Opaque) { |
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 8aba0bbf6..9b7e1480b 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h | |||
| @@ -33,6 +33,7 @@ public: | |||
| 33 | explicit Value(f64 value) noexcept; | 33 | explicit Value(f64 value) noexcept; |
| 34 | 34 | ||
| 35 | [[nodiscard]] bool IsIdentity() const noexcept; | 35 | [[nodiscard]] bool IsIdentity() const noexcept; |
| 36 | [[nodiscard]] bool IsPhi() const noexcept; | ||
| 36 | [[nodiscard]] bool IsEmpty() const noexcept; | 37 | [[nodiscard]] bool IsEmpty() const noexcept; |
| 37 | [[nodiscard]] bool IsImmediate() const noexcept; | 38 | [[nodiscard]] bool IsImmediate() const noexcept; |
| 38 | [[nodiscard]] bool IsLabel() const noexcept; | 39 | [[nodiscard]] bool IsLabel() const noexcept; |
diff --git a/src/shader_recompiler/frontend/maxwell/control_flow.cpp b/src/shader_recompiler/frontend/maxwell/control_flow.cpp index e766b555b..52be41b84 100644 --- a/src/shader_recompiler/frontend/maxwell/control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/control_flow.cpp | |||
| @@ -354,7 +354,7 @@ void CFG::AnalyzeCondInst(Block* block, FunctionId function_id, Location pc, | |||
| 354 | // Impersonate the visited block with a virtual block | 354 | // Impersonate the visited block with a virtual block |
| 355 | *block = std::move(virtual_block); | 355 | *block = std::move(virtual_block); |
| 356 | // Set the end properties of the conditional instruction | 356 | // Set the end properties of the conditional instruction |
| 357 | conditional_block->end = pc; | 357 | conditional_block->end = pc + 1; |
| 358 | conditional_block->end_class = insn_end_class; | 358 | conditional_block->end_class = insn_end_class; |
| 359 | // Add a label to the instruction after the conditional instruction | 359 | // Add a label to the instruction after the conditional instruction |
| 360 | Block* const endif_block{AddLabel(conditional_block, block->stack, pc + 1, function_id)}; | 360 | Block* const endif_block{AddLabel(conditional_block, block->stack, pc + 1, function_id)}; |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h index 4e722e205..672e140b2 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h | |||
| @@ -209,7 +209,7 @@ public: | |||
| 209 | void P2R_cbuf(u64 insn); | 209 | void P2R_cbuf(u64 insn); |
| 210 | void P2R_imm(u64 insn); | 210 | void P2R_imm(u64 insn); |
| 211 | void PBK(); | 211 | void PBK(); |
| 212 | void PCNT(u64 insn); | 212 | void PCNT(); |
| 213 | void PEXIT(u64 insn); | 213 | void PEXIT(u64 insn); |
| 214 | void PIXLD(u64 insn); | 214 | void PIXLD(u64 insn); |
| 215 | void PLONGJMP(u64 insn); | 215 | void PLONGJMP(u64 insn); |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp index 4114e10be..3f6dedfdd 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -637,8 +637,8 @@ void TranslatorVisitor::PBK() { | |||
| 637 | // PBK is a no-op | 637 | // PBK is a no-op |
| 638 | } | 638 | } |
| 639 | 639 | ||
| 640 | void TranslatorVisitor::PCNT(u64) { | 640 | void TranslatorVisitor::PCNT() { |
| 641 | ThrowNotImplemented(Opcode::PCNT); | 641 | // PCNT is a no-op |
| 642 | } | 642 | } |
| 643 | 643 | ||
| 644 | void TranslatorVisitor::PEXIT(u64) { | 644 | void TranslatorVisitor::PEXIT(u64) { |