summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend')
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp27
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.inc2
-rw-r--r--src/shader_recompiler/frontend/ir/structured_control_flow.cpp15
-rw-r--r--src/shader_recompiler/frontend/ir/value.cpp6
-rw-r--r--src/shader_recompiler/frontend/ir/value.h1
-rw-r--r--src/shader_recompiler/frontend/maxwell/control_flow.cpp2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/impl.h2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp4
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
137U1 IREmitter::Condition(IR::Condition cond) { 137static 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
154U1 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
151F32 IREmitter::GetAttribute(IR::Attribute attribute) { 160F32 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, ...
6OPCODE(Phi, Opaque, ) 6OPCODE(Phi, Opaque, )
7OPCODE(Void, Void, )
8OPCODE(Identity, Opaque, Opaque, ) 7OPCODE(Identity, Opaque, Opaque, )
8OPCODE(Void, Void, )
9 9
10// Control flow 10// Control flow
11OPCODE(Branch, Void, Label, ) 11OPCODE(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
39bool Value::IsPhi() const noexcept {
40 return type == Type::Opaque && inst->Opcode() == Opcode::Phi;
41}
42
39bool Value::IsEmpty() const noexcept { 43bool 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
54IR::Type Value::Type() const noexcept { 58IR::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
640void TranslatorVisitor::PCNT(u64) { 640void TranslatorVisitor::PCNT() {
641 ThrowNotImplemented(Opcode::PCNT); 641 // PCNT is a no-op
642} 642}
643 643
644void TranslatorVisitor::PEXIT(u64) { 644void TranslatorVisitor::PEXIT(u64) {