From d54d7de40e7295827b0e4e4026441b53d3fc9569 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Fri, 14 May 2021 00:40:54 -0300
Subject: glasm: Rework control flow introducing a syntax list

This commit regresses VertexA shaders, their transformation pass has to
be adapted to the new control flow.
---
 .../frontend/ir/abstract_syntax_list.h             | 56 ++++++++++++++++++++
 src/shader_recompiler/frontend/ir/basic_block.cpp  | 56 +++++---------------
 src/shader_recompiler/frontend/ir/basic_block.h    | 51 ++++--------------
 src/shader_recompiler/frontend/ir/ir_emitter.cpp   | 60 ++++++----------------
 src/shader_recompiler/frontend/ir/ir_emitter.h     | 11 +---
 .../frontend/ir/microinstruction.cpp               | 11 ++--
 src/shader_recompiler/frontend/ir/opcodes.h        |  1 -
 src/shader_recompiler/frontend/ir/opcodes.inc      | 21 +++-----
 src/shader_recompiler/frontend/ir/post_order.cpp   | 36 ++++++-------
 src/shader_recompiler/frontend/ir/post_order.h     |  3 +-
 src/shader_recompiler/frontend/ir/program.h        |  4 +-
 src/shader_recompiler/frontend/ir/type.h           | 49 +++++++++---------
 src/shader_recompiler/frontend/ir/value.cpp        |  8 ---
 src/shader_recompiler/frontend/ir/value.h          |  9 ----
 14 files changed, 151 insertions(+), 225 deletions(-)
 create mode 100644 src/shader_recompiler/frontend/ir/abstract_syntax_list.h

(limited to 'src/shader_recompiler/frontend/ir')

diff --git a/src/shader_recompiler/frontend/ir/abstract_syntax_list.h b/src/shader_recompiler/frontend/ir/abstract_syntax_list.h
new file mode 100644
index 0000000000..1366414c25
--- /dev/null
+++ b/src/shader_recompiler/frontend/ir/abstract_syntax_list.h
@@ -0,0 +1,56 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <vector>
+
+#include "shader_recompiler/frontend/ir/value.h"
+
+namespace Shader::IR {
+
+class Block;
+
+struct AbstractSyntaxNode {
+    enum class Type {
+        Block,
+        If,
+        EndIf,
+        Loop,
+        Repeat,
+        Break,
+        Return,
+        Unreachable,
+    };
+    Type type{};
+    union {
+        Block* block{};
+        struct {
+            U1 cond;
+            Block* body;
+            Block* merge;
+        } if_node;
+        struct {
+            Block* merge;
+        } end_if;
+        struct {
+            Block* body;
+            Block* continue_block;
+            Block* merge;
+        } loop;
+        struct {
+            U1 cond;
+            Block* loop_header;
+            Block* merge;
+        } repeat;
+        struct {
+            U1 cond;
+            Block* merge;
+            Block* skip;
+        } break_node;
+    };
+};
+using AbstractSyntaxList = std::vector<AbstractSyntaxNode>;
+
+} // namespace Shader::IR
diff --git a/src/shader_recompiler/frontend/ir/basic_block.cpp b/src/shader_recompiler/frontend/ir/basic_block.cpp
index f92fc2571c..7c08b25ce2 100644
--- a/src/shader_recompiler/frontend/ir/basic_block.cpp
+++ b/src/shader_recompiler/frontend/ir/basic_block.cpp
@@ -14,10 +14,7 @@
 
 namespace Shader::IR {
 
-Block::Block(ObjectPool<Inst>& inst_pool_, u32 begin, u32 end)
-    : inst_pool{&inst_pool_}, location_begin{begin}, location_end{end} {}
-
-Block::Block(ObjectPool<Inst>& inst_pool_) : Block{inst_pool_, 0, 0} {}
+Block::Block(ObjectPool<Inst>& inst_pool_) : inst_pool{&inst_pool_} {}
 
 Block::~Block() = default;
 
@@ -40,39 +37,15 @@ Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode op,
     return result_it;
 }
 
-void Block::SetBranches(Condition cond, Block* branch_true_, Block* branch_false_) {
-    branch_cond = cond;
-    branch_true = branch_true_;
-    branch_false = branch_false_;
-}
-
-void Block::SetBranch(Block* branch) {
-    branch_cond = Condition{true};
-    branch_true = branch;
-}
-
-void Block::SetReturn() {
-    branch_cond = Condition{true};
-    branch_true = nullptr;
-    branch_false = nullptr;
-}
-
-bool Block::IsVirtual() const noexcept {
-    return location_begin == location_end;
-}
-
-u32 Block::LocationBegin() const noexcept {
-    return location_begin;
-}
-
-u32 Block::LocationEnd() const noexcept {
-    return location_end;
-}
-
-void Block::AddImmediatePredecessor(Block* block) {
-    if (std::ranges::find(imm_predecessors, block) == imm_predecessors.end()) {
-        imm_predecessors.push_back(block);
+void Block::AddBranch(Block* block) {
+    if (std::ranges::find(imm_successors, block) != imm_successors.end()) {
+        throw LogicError("Successor already inserted");
+    }
+    if (std::ranges::find(block->imm_predecessors, this) != block->imm_predecessors.end()) {
+        throw LogicError("Predecessor already inserted");
     }
+    imm_successors.push_back(block);
+    block->imm_predecessors.push_back(this);
 }
 
 static std::string BlockToIndex(const std::map<const Block*, size_t>& block_to_index,
@@ -92,15 +65,11 @@ static size_t InstIndex(std::map<const Inst*, size_t>& inst_to_index, size_t& in
     return it->second;
 }
 
-static std::string ArgToIndex(const std::map<const Block*, size_t>& block_to_index,
-                              std::map<const Inst*, size_t>& inst_to_index, size_t& inst_index,
+static std::string ArgToIndex(std::map<const Inst*, size_t>& inst_to_index, size_t& inst_index,
                               const Value& arg) {
     if (arg.IsEmpty()) {
         return "<null>";
     }
-    if (arg.IsLabel()) {
-        return BlockToIndex(block_to_index, arg.Label());
-    }
     if (!arg.IsImmediate() || arg.IsIdentity()) {
         return fmt::format("%{}", InstIndex(inst_to_index, inst_index, arg.Inst()));
     }
@@ -140,8 +109,7 @@ std::string DumpBlock(const Block& block, const std::map<const Block*, size_t>&
     if (const auto it{block_to_index.find(&block)}; it != block_to_index.end()) {
         ret += fmt::format(" ${}", it->second);
     }
-    ret += fmt::format(": begin={:04x} end={:04x}\n", block.LocationBegin(), block.LocationEnd());
-
+    ret += '\n';
     for (const Inst& inst : block) {
         const Opcode op{inst.GetOpcode()};
         ret += fmt::format("[{:016x}] ", reinterpret_cast<u64>(&inst));
@@ -153,7 +121,7 @@ std::string DumpBlock(const Block& block, const std::map<const Block*, size_t>&
         const size_t arg_count{inst.NumArgs()};
         for (size_t arg_index = 0; arg_index < arg_count; ++arg_index) {
             const Value arg{inst.Arg(arg_index)};
-            const std::string arg_str{ArgToIndex(block_to_index, inst_to_index, inst_index, arg)};
+            const std::string arg_str{ArgToIndex(inst_to_index, inst_index, arg)};
             ret += arg_index != 0 ? ", " : " ";
             if (op == Opcode::Phi) {
                 ret += fmt::format("[ {}, {} ]", arg_str,
diff --git a/src/shader_recompiler/frontend/ir/basic_block.h b/src/shader_recompiler/frontend/ir/basic_block.h
index 0b0c97af6b..7e134b4c78 100644
--- a/src/shader_recompiler/frontend/ir/basic_block.h
+++ b/src/shader_recompiler/frontend/ir/basic_block.h
@@ -12,6 +12,7 @@
 #include <boost/intrusive/list.hpp>
 
 #include "common/bit_cast.h"
+#include "common/common_types.h"
 #include "shader_recompiler/frontend/ir/condition.h"
 #include "shader_recompiler/frontend/ir/value.h"
 #include "shader_recompiler/object_pool.h"
@@ -27,7 +28,6 @@ public:
     using reverse_iterator = InstructionList::reverse_iterator;
     using const_reverse_iterator = InstructionList::const_reverse_iterator;
 
-    explicit Block(ObjectPool<Inst>& inst_pool_, u32 begin, u32 end);
     explicit Block(ObjectPool<Inst>& inst_pool_);
     ~Block();
 
@@ -44,22 +44,8 @@ public:
     iterator PrependNewInst(iterator insertion_point, Opcode op,
                             std::initializer_list<Value> args = {}, u32 flags = 0);
 
-    /// Set the branches to jump to when all instructions have executed.
-    void SetBranches(Condition cond, Block* branch_true, Block* branch_false);
-    /// Set the branch to unconditionally jump to when all instructions have executed.
-    void SetBranch(Block* branch);
-    /// Mark the block as a return block.
-    void SetReturn();
-
-    /// Returns true when the block does not implement any guest instructions directly.
-    [[nodiscard]] bool IsVirtual() const noexcept;
-    /// Gets the starting location of this basic block.
-    [[nodiscard]] u32 LocationBegin() const noexcept;
-    /// Gets the end location for this basic block.
-    [[nodiscard]] u32 LocationEnd() const noexcept;
-
-    /// Adds a new immediate predecessor to this basic block.
-    void AddImmediatePredecessor(Block* block);
+    /// Adds a new branch to this basic block.
+    void AddBranch(Block* block);
 
     /// Gets a mutable reference to the instruction list for this basic block.
     [[nodiscard]] InstructionList& Instructions() noexcept {
@@ -71,9 +57,13 @@ public:
     }
 
     /// Gets an immutable span to the immediate predecessors.
-    [[nodiscard]] std::span<Block* const> ImmediatePredecessors() const noexcept {
+    [[nodiscard]] std::span<Block* const> ImmPredecessors() const noexcept {
         return imm_predecessors;
     }
+    /// Gets an immutable span to the immediate successors.
+    [[nodiscard]] std::span<Block* const> ImmSuccessors() const noexcept {
+        return imm_successors;
+    }
 
     /// Intrusively store the host definition of this instruction.
     template <typename DefinitionType>
@@ -87,19 +77,6 @@ public:
         return Common::BitCast<DefinitionType>(definition);
     }
 
-    [[nodiscard]] Condition BranchCondition() const noexcept {
-        return branch_cond;
-    }
-    [[nodiscard]] bool IsTerminationBlock() const noexcept {
-        return !branch_true && !branch_false;
-    }
-    [[nodiscard]] Block* TrueBranch() const noexcept {
-        return branch_true;
-    }
-    [[nodiscard]] Block* FalseBranch() const noexcept {
-        return branch_false;
-    }
-
     void SetSsaRegValue(IR::Reg reg, const Value& value) noexcept {
         ssa_reg_values[RegIndex(reg)] = value;
     }
@@ -178,22 +155,14 @@ public:
 private:
     /// Memory pool for instruction list
     ObjectPool<Inst>* inst_pool;
-    /// Starting location of this block
-    u32 location_begin;
-    /// End location of this block
-    u32 location_end;
 
     /// List of instructions in this block
     InstructionList instructions;
 
-    /// Condition to choose the branch to take
-    Condition branch_cond{true};
-    /// Block to jump into when the branch condition evaluates as true
-    Block* branch_true{nullptr};
-    /// Block to jump into when the branch condition evaluates as false
-    Block* branch_false{nullptr};
     /// Block immediate predecessors
     std::vector<Block*> imm_predecessors;
+    /// Block immediate successors
+    std::vector<Block*> imm_successors;
 
     /// Intrusively store the value of a register in the block.
     std::array<Value, NUM_REGS> ssa_reg_values;
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index ce6c9af073..eb45aa4772 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -61,25 +61,28 @@ F64 IREmitter::Imm64(f64 value) const {
     return F64{Value{value}};
 }
 
-void IREmitter::Branch(Block* label) {
-    label->AddImmediatePredecessor(block);
-    block->SetBranch(label);
-    Inst(Opcode::Branch, label);
+void IREmitter::Prologue() {
+    Inst(Opcode::Prologue);
 }
 
-void IREmitter::BranchConditional(const U1& condition, Block* true_label, Block* false_label) {
-    block->SetBranches(IR::Condition{true}, true_label, false_label);
-    true_label->AddImmediatePredecessor(block);
-    false_label->AddImmediatePredecessor(block);
-    Inst(Opcode::BranchConditional, condition, true_label, false_label);
+void IREmitter::Epilogue() {
+    Inst(Opcode::Epilogue);
 }
 
-void IREmitter::LoopMerge(Block* merge_block, Block* continue_target) {
-    Inst(Opcode::LoopMerge, merge_block, continue_target);
+void IREmitter::BranchConditionRef(const U1& cond) {
+    Inst(Opcode::BranchConditionRef, cond);
 }
 
-void IREmitter::SelectionMerge(Block* merge_block) {
-    Inst(Opcode::SelectionMerge, merge_block);
+void IREmitter::DemoteToHelperInvocation() {
+    Inst(Opcode::DemoteToHelperInvocation);
+}
+
+void IREmitter::EmitVertex(const U32& stream) {
+    Inst(Opcode::EmitVertex, stream);
+}
+
+void IREmitter::EndPrimitive(const U32& stream) {
+    Inst(Opcode::EndPrimitive, stream);
 }
 
 void IREmitter::Barrier() {
@@ -94,37 +97,6 @@ void IREmitter::DeviceMemoryBarrier() {
     Inst(Opcode::DeviceMemoryBarrier);
 }
 
-void IREmitter::Return() {
-    block->SetReturn();
-    Inst(Opcode::Return);
-}
-
-void IREmitter::Unreachable() {
-    Inst(Opcode::Unreachable);
-}
-
-void IREmitter::DemoteToHelperInvocation(Block* continue_label) {
-    block->SetBranch(continue_label);
-    continue_label->AddImmediatePredecessor(block);
-    Inst(Opcode::DemoteToHelperInvocation, continue_label);
-}
-
-void IREmitter::Prologue() {
-    Inst(Opcode::Prologue);
-}
-
-void IREmitter::Epilogue() {
-    Inst(Opcode::Epilogue);
-}
-
-void IREmitter::EmitVertex(const U32& stream) {
-    Inst(Opcode::EmitVertex, stream);
-}
-
-void IREmitter::EndPrimitive(const U32& stream) {
-    Inst(Opcode::EndPrimitive, stream);
-}
-
 U32 IREmitter::GetReg(IR::Reg reg) {
     return Inst<U32>(Opcode::GetRegister, reg);
 }
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h
index fd41b7e893..7a83c33d33 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.h
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.h
@@ -32,17 +32,10 @@ public:
     [[nodiscard]] U64 Imm64(s64 value) const;
     [[nodiscard]] F64 Imm64(f64 value) const;
 
-    void Branch(Block* label);
-    void BranchConditional(const U1& condition, Block* true_label, Block* false_label);
-    void LoopMerge(Block* merge_block, Block* continue_target);
-    void SelectionMerge(Block* merge_block);
-    void Return();
-    void Unreachable();
-    void DemoteToHelperInvocation(Block* continue_label);
-
     void Prologue();
     void Epilogue();
-
+    void BranchConditionRef(const U1& cond);
+    void DemoteToHelperInvocation();
     void EmitVertex(const U32& stream);
     void EndPrimitive(const U32& stream);
 
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp
index 616ef17d4e..3645742401 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.cpp
+++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp
@@ -56,19 +56,14 @@ Inst::~Inst() {
 
 bool Inst::MayHaveSideEffects() const noexcept {
     switch (op) {
-    case Opcode::Branch:
-    case Opcode::BranchConditional:
-    case Opcode::LoopMerge:
-    case Opcode::SelectionMerge:
-    case Opcode::Return:
+    case Opcode::Prologue:
+    case Opcode::Epilogue:
+    case Opcode::BranchConditionRef:
     case Opcode::Join:
-    case Opcode::Unreachable:
     case Opcode::DemoteToHelperInvocation:
     case Opcode::Barrier:
     case Opcode::WorkgroupMemoryBarrier:
     case Opcode::DeviceMemoryBarrier:
-    case Opcode::Prologue:
-    case Opcode::Epilogue:
     case Opcode::EmitVertex:
     case Opcode::EndPrimitive:
     case Opcode::SetAttribute:
diff --git a/src/shader_recompiler/frontend/ir/opcodes.h b/src/shader_recompiler/frontend/ir/opcodes.h
index 2b9c0ed8cc..56b001902c 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.h
+++ b/src/shader_recompiler/frontend/ir/opcodes.h
@@ -30,7 +30,6 @@ struct OpcodeMeta {
 // using enum Type;
 constexpr Type Void{Type::Void};
 constexpr Type Opaque{Type::Opaque};
-constexpr Type Label{Type::Label};
 constexpr Type Reg{Type::Reg};
 constexpr Type Pred{Type::Pred};
 constexpr Type Attribute{Type::Attribute};
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc
index 9165421f89..75ddb6b6f8 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.inc
+++ b/src/shader_recompiler/frontend/ir/opcodes.inc
@@ -7,27 +7,20 @@ OPCODE(Phi,                                                 Opaque,
 OPCODE(Identity,                                            Opaque,         Opaque,                                                                         )
 OPCODE(Void,                                                Void,                                                                                           )
 
-// Control flow
-OPCODE(Branch,                                              Void,           Label,                                                                          )
-OPCODE(BranchConditional,                                   Void,           U1,             Label,          Label,                                          )
-OPCODE(LoopMerge,                                           Void,           Label,          Label,                                                          )
-OPCODE(SelectionMerge,                                      Void,           Label,                                                                          )
-OPCODE(Return,                                              Void,                                                                                           )
+// Special operations
+OPCODE(Prologue,                                            Void,                                                                                           )
+OPCODE(Epilogue,                                            Void,                                                                                           )
+OPCODE(BranchConditionRef,                                  Void,           U1,                                                                             )
 OPCODE(Join,                                                Void,                                                                                           )
-OPCODE(Unreachable,                                         Void,                                                                                           )
-OPCODE(DemoteToHelperInvocation,                            Void,           Label,                                                                          )
+OPCODE(DemoteToHelperInvocation,                            Void,                                                                                           )
+OPCODE(EmitVertex,                                          Void,           U32,                                                                            )
+OPCODE(EndPrimitive,                                        Void,           U32,                                                                            )
 
 // Barriers
 OPCODE(Barrier,                                             Void,                                                                                           )
 OPCODE(WorkgroupMemoryBarrier,                              Void,                                                                                           )
 OPCODE(DeviceMemoryBarrier,                                 Void,                                                                                           )
 
-// Special operations
-OPCODE(Prologue,                                            Void,                                                                                           )
-OPCODE(Epilogue,                                            Void,                                                                                           )
-OPCODE(EmitVertex,                                          Void,           U32,                                                                            )
-OPCODE(EndPrimitive,                                        Void,           U32,                                                                            )
-
 // Context getters/setters
 OPCODE(GetRegister,                                         U32,            Reg,                                                                            )
 OPCODE(SetRegister,                                         Void,           Reg,            U32,                                                            )
diff --git a/src/shader_recompiler/frontend/ir/post_order.cpp b/src/shader_recompiler/frontend/ir/post_order.cpp
index 8709a2ea1e..1a28df7fbe 100644
--- a/src/shader_recompiler/frontend/ir/post_order.cpp
+++ b/src/shader_recompiler/frontend/ir/post_order.cpp
@@ -2,6 +2,8 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include <algorithm>
+
 #include <boost/container/flat_set.hpp>
 #include <boost/container/small_vector.hpp>
 
@@ -10,35 +12,31 @@
 
 namespace Shader::IR {
 
-BlockList PostOrder(const BlockList& blocks) {
+BlockList PostOrder(const AbstractSyntaxNode& root) {
     boost::container::small_vector<Block*, 16> block_stack;
     boost::container::flat_set<Block*> visited;
-
     BlockList post_order_blocks;
-    post_order_blocks.reserve(blocks.size());
 
-    Block* const first_block{blocks.front()};
+    if (root.type != AbstractSyntaxNode::Type::Block) {
+        throw LogicError("First node in abstract syntax list root is not a block");
+    }
+    Block* const first_block{root.block};
     visited.insert(first_block);
     block_stack.push_back(first_block);
 
-    const auto visit_branch = [&](Block* block, Block* branch) {
-        if (!branch) {
-            return false;
-        }
-        if (!visited.insert(branch).second) {
-            return false;
-        }
-        // Calling push_back twice is faster than insert on MSVC
-        block_stack.push_back(block);
-        block_stack.push_back(branch);
-        return true;
-    };
     while (!block_stack.empty()) {
         Block* const block{block_stack.back()};
+        const auto visit{[&](Block* branch) {
+            if (!visited.insert(branch).second) {
+                return false;
+            }
+            // Calling push_back twice is faster than insert on MSVC
+            block_stack.push_back(block);
+            block_stack.push_back(branch);
+            return true;
+        }};
         block_stack.pop_back();
-
-        if (!visit_branch(block, block->TrueBranch()) &&
-            !visit_branch(block, block->FalseBranch())) {
+        if (std::ranges::none_of(block->ImmSuccessors(), visit)) {
             post_order_blocks.push_back(block);
         }
     }
diff --git a/src/shader_recompiler/frontend/ir/post_order.h b/src/shader_recompiler/frontend/ir/post_order.h
index 30137ff57a..58a0467a03 100644
--- a/src/shader_recompiler/frontend/ir/post_order.h
+++ b/src/shader_recompiler/frontend/ir/post_order.h
@@ -5,9 +5,10 @@
 #pragma once
 
 #include "shader_recompiler/frontend/ir/basic_block.h"
+#include "shader_recompiler/frontend/ir/abstract_syntax_list.h"
 
 namespace Shader::IR {
 
-BlockList PostOrder(const BlockList& blocks);
+BlockList PostOrder(const AbstractSyntaxNode& root);
 
 } // namespace Shader::IR
diff --git a/src/shader_recompiler/frontend/ir/program.h b/src/shader_recompiler/frontend/ir/program.h
index 51e1a8c779..9ede5b48d9 100644
--- a/src/shader_recompiler/frontend/ir/program.h
+++ b/src/shader_recompiler/frontend/ir/program.h
@@ -7,8 +7,7 @@
 #include <array>
 #include <string>
 
-#include <boost/container/small_vector.hpp>
-
+#include "shader_recompiler/frontend/ir/abstract_syntax_list.h"
 #include "shader_recompiler/frontend/ir/basic_block.h"
 #include "shader_recompiler/program_header.h"
 #include "shader_recompiler/shader_info.h"
@@ -17,6 +16,7 @@
 namespace Shader::IR {
 
 struct Program {
+    AbstractSyntaxList syntax_list;
     BlockList blocks;
     BlockList post_order_blocks;
     Info info;
diff --git a/src/shader_recompiler/frontend/ir/type.h b/src/shader_recompiler/frontend/ir/type.h
index 8b3b338528..294b230c49 100644
--- a/src/shader_recompiler/frontend/ir/type.h
+++ b/src/shader_recompiler/frontend/ir/type.h
@@ -16,31 +16,30 @@ namespace Shader::IR {
 enum class Type {
     Void = 0,
     Opaque = 1 << 0,
-    Label = 1 << 1,
-    Reg = 1 << 2,
-    Pred = 1 << 3,
-    Attribute = 1 << 4,
-    Patch = 1 << 5,
-    U1 = 1 << 6,
-    U8 = 1 << 7,
-    U16 = 1 << 8,
-    U32 = 1 << 9,
-    U64 = 1 << 10,
-    F16 = 1 << 11,
-    F32 = 1 << 12,
-    F64 = 1 << 13,
-    U32x2 = 1 << 14,
-    U32x3 = 1 << 15,
-    U32x4 = 1 << 16,
-    F16x2 = 1 << 17,
-    F16x3 = 1 << 18,
-    F16x4 = 1 << 19,
-    F32x2 = 1 << 20,
-    F32x3 = 1 << 21,
-    F32x4 = 1 << 22,
-    F64x2 = 1 << 23,
-    F64x3 = 1 << 24,
-    F64x4 = 1 << 25,
+    Reg = 1 << 1,
+    Pred = 1 << 2,
+    Attribute = 1 << 3,
+    Patch = 1 << 4,
+    U1 = 1 << 5,
+    U8 = 1 << 6,
+    U16 = 1 << 7,
+    U32 = 1 << 8,
+    U64 = 1 << 9,
+    F16 = 1 << 10,
+    F32 = 1 << 11,
+    F64 = 1 << 12,
+    U32x2 = 1 << 13,
+    U32x3 = 1 << 14,
+    U32x4 = 1 << 15,
+    F16x2 = 1 << 16,
+    F16x3 = 1 << 17,
+    F16x4 = 1 << 18,
+    F32x2 = 1 << 19,
+    F32x3 = 1 << 20,
+    F32x4 = 1 << 21,
+    F64x2 = 1 << 22,
+    F64x3 = 1 << 23,
+    F64x4 = 1 << 24,
 };
 DECLARE_ENUM_FLAG_OPERATORS(Type)
 
diff --git a/src/shader_recompiler/frontend/ir/value.cpp b/src/shader_recompiler/frontend/ir/value.cpp
index b962f170d7..d365ea1bcb 100644
--- a/src/shader_recompiler/frontend/ir/value.cpp
+++ b/src/shader_recompiler/frontend/ir/value.cpp
@@ -9,8 +9,6 @@ namespace Shader::IR {
 
 Value::Value(IR::Inst* value) noexcept : type{Type::Opaque}, inst{value} {}
 
-Value::Value(IR::Block* value) noexcept : type{Type::Label}, label{value} {}
-
 Value::Value(IR::Reg value) noexcept : type{Type::Reg}, reg{value} {}
 
 Value::Value(IR::Pred value) noexcept : type{Type::Pred}, pred{value} {}
@@ -33,10 +31,6 @@ Value::Value(u64 value) noexcept : type{Type::U64}, imm_u64{value} {}
 
 Value::Value(f64 value) noexcept : type{Type::F64}, imm_f64{value} {}
 
-bool Value::IsLabel() const noexcept {
-    return type == Type::Label;
-}
-
 IR::Type Value::Type() const noexcept {
     if (IsPhi()) {
         // The type of a phi node is stored in its flags
@@ -60,8 +54,6 @@ bool Value::operator==(const Value& other) const {
         return true;
     case Type::Opaque:
         return inst == other.inst;
-    case Type::Label:
-        return label == other.label;
     case Type::Reg:
         return reg == other.reg;
     case Type::Pred:
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h
index beaf149f3f..2ce49f953d 100644
--- a/src/shader_recompiler/frontend/ir/value.h
+++ b/src/shader_recompiler/frontend/ir/value.h
@@ -37,7 +37,6 @@ class Value {
 public:
     Value() noexcept = default;
     explicit Value(IR::Inst* value) noexcept;
-    explicit Value(IR::Block* value) noexcept;
     explicit Value(IR::Reg value) noexcept;
     explicit Value(IR::Pred value) noexcept;
     explicit Value(IR::Attribute value) noexcept;
@@ -54,11 +53,9 @@ public:
     [[nodiscard]] bool IsPhi() const noexcept;
     [[nodiscard]] bool IsEmpty() const noexcept;
     [[nodiscard]] bool IsImmediate() const noexcept;
-    [[nodiscard]] bool IsLabel() const noexcept;
     [[nodiscard]] IR::Type Type() const noexcept;
 
     [[nodiscard]] IR::Inst* Inst() const;
-    [[nodiscard]] IR::Block* Label() const;
     [[nodiscard]] IR::Inst* InstRecursive() const;
     [[nodiscard]] IR::Value Resolve() const;
     [[nodiscard]] IR::Reg Reg() const;
@@ -80,7 +77,6 @@ private:
     IR::Type type{};
     union {
         IR::Inst* inst{};
-        IR::Block* label;
         IR::Reg reg;
         IR::Pred pred;
         IR::Attribute attribute;
@@ -304,11 +300,6 @@ inline IR::Inst* Value::Inst() const {
     return inst;
 }
 
-inline IR::Block* Value::Label() const {
-    DEBUG_ASSERT(type == Type::Label);
-    return label;
-}
-
 inline IR::Inst* Value::InstRecursive() const {
     DEBUG_ASSERT(type == Type::Opaque);
     if (IsIdentity()) {
-- 
cgit v1.2.3-70-g09d2