diff options
| author | ReinUsesLisp <reinuseslisp@airmail.cc> | 2021-02-24 05:21:30 -0300 | 
|---|---|---|
| committer | ameerj <52414509+ameerj@users.noreply.github.com> | 2021-07-22 21:51:22 -0400 | 
| commit | e87a502da2d5a8356a639d53c0a16a77890de4c7 (patch) | |
| tree | 00fd1a9a32c0334c49189098829b782a37533c46 | |
| parent | 9d6a98d950da39dd2a7ca5ad25525de4fb825415 (diff) | |
shader: Fix control flow
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) {      Inst(Opcode::SetOFlag, value);  } -U1 IREmitter::Condition(IR::Condition cond) { -    if (cond == IR::Condition{true}) { -        return Imm1(true); -    } else if (cond == IR::Condition{false}) { -        return Imm1(false); +static U1 GetFlowTest(IREmitter& ir, FlowTest flow_test) { +    switch (flow_test) { +    case FlowTest::T: +        return ir.Imm1(true); +    case FlowTest::F: +        return ir.Imm1(false); +    case FlowTest::EQ: +        // TODO: Test this +        return ir.GetZFlag(); +    case FlowTest::NE: +        // TODO: Test this +        return ir.LogicalNot(ir.GetZFlag()); +    default: +        throw NotImplementedException("Flow test {}", flow_test);      } +} + +U1 IREmitter::Condition(IR::Condition cond) {      const FlowTest flow_test{cond.FlowTest()};      const auto [pred, is_negated]{cond.Pred()}; -    if (flow_test == FlowTest::T) { -        return GetPred(pred, is_negated); -    } -    throw NotImplementedException("Condition {}", cond); +    return LogicalAnd(GetPred(pred, is_negated), GetFlowTest(*this, flow_test));  }  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 @@  //     opcode name,                                         return type,    arg1 type,      arg2 type,      arg3 type,      arg4 type,      ...  OPCODE(Phi,                                                 Opaque,                                                                         ) -OPCODE(Void,                                                Void,                                                                           )  OPCODE(Identity,                                            Opaque,         Opaque,                                                         ) +OPCODE(Void,                                                Void,                                                                           )  // Control flow  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:          if (!sibling) {              throw LogicError("Not siblings");          } -          // goto_stmt and label_stmt are guaranteed to be siblings, eliminate          if (std::next(goto_stmt) == label_stmt) {              // Simply eliminate the goto if the label is next to it @@ -351,9 +350,14 @@ private:          const std::unordered_map labels_map{BuildLabels(blocks)};          Tree& root{root_stmt.children};          auto insert_point{root.begin()}; +        // Skip all goto variables zero-initialization +        std::advance(insert_point, labels_map.size()); +          for (Block* const block : blocks) { -            ++insert_point; // Skip label -            ++insert_point; // Skip set variable +            // Skip label +            ++insert_point; +            // Skip set variable +            ++insert_point;              root.insert(insert_point, *pool.Create(block, &root_stmt));              if (block->IsTerminationBlock()) { @@ -391,6 +395,7 @@ private:              labels_map.emplace(block, root.insert(root.end(), *label));              Statement* const false_stmt{pool.Create(Identity{}, Condition{false})};              root.push_back(*pool.Create(SetVariable{}, label_id, false_stmt, &root_stmt)); +            root.push_front(*pool.Create(SetVariable{}, label_id, false_stmt, &root_stmt));              ++label_id;          }          return labels_map; @@ -457,10 +462,10 @@ private:          }          body.erase(goto_stmt); -        // Update nested if condition          switch (label_nested_stmt->type) {          case StatementType::If: -            label_nested_stmt->cond = pool.Create(Or{}, neg_var, label_nested_stmt->cond); +            // Update nested if condition +            label_nested_stmt->cond = pool.Create(Or{}, variable, label_nested_stmt->cond);              break;          case StatementType::Loop:              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 {      return type == Type::Opaque && inst->Opcode() == Opcode::Identity;  } +bool Value::IsPhi() const noexcept { +    return type == Type::Opaque && inst->Opcode() == Opcode::Phi; +} +  bool Value::IsEmpty() const noexcept {      return type == Type::Void;  } @@ -52,7 +56,7 @@ bool Value::IsLabel() const noexcept {  }  IR::Type Value::Type() const noexcept { -    if (IsIdentity()) { +    if (IsIdentity() || IsPhi()) {          return inst->Arg(0).Type();      }      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:      explicit Value(f64 value) noexcept;      [[nodiscard]] bool IsIdentity() const noexcept; +    [[nodiscard]] bool IsPhi() const noexcept;      [[nodiscard]] bool IsEmpty() const noexcept;      [[nodiscard]] bool IsImmediate() const noexcept;      [[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,      // Impersonate the visited block with a virtual block      *block = std::move(virtual_block);      // Set the end properties of the conditional instruction -    conditional_block->end = pc; +    conditional_block->end = pc + 1;      conditional_block->end_class = insn_end_class;      // Add a label to the instruction after the conditional instruction      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:      void P2R_cbuf(u64 insn);      void P2R_imm(u64 insn);      void PBK(); -    void PCNT(u64 insn); +    void PCNT();      void PEXIT(u64 insn);      void PIXLD(u64 insn);      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() {      // PBK is a no-op  } -void TranslatorVisitor::PCNT(u64) { -    ThrowNotImplemented(Opcode::PCNT); +void TranslatorVisitor::PCNT() { +    // PCNT is a no-op  }  void TranslatorVisitor::PEXIT(u64) { | 
