From 1109db86b7259857762fc29b2ff8c9f95e92353e Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Tue, 16 Jul 2019 11:22:40 -0400
Subject: [PATCH 01/10] video_core/shader/decode: Prevent sign-conversion
 warnings

Makes it explicit that the conversions here are intentional.
---
 src/video_core/shader/decode.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp
index afffd157f..b547d8323 100644
--- a/src/video_core/shader/decode.cpp
+++ b/src/video_core/shader/decode.cpp
@@ -47,14 +47,14 @@ void ShaderIR::Decode() {
         if (shader_info.decompilable) {
             disable_flow_stack = true;
             const auto insert_block = [this](NodeBlock& nodes, u32 label) {
-                if (label == exit_branch) {
+                if (label == static_cast<u32>(exit_branch)) {
                     return;
                 }
                 basic_blocks.insert({label, nodes});
             };
             const auto& blocks = shader_info.blocks;
             NodeBlock current_block;
-            u32 current_label = exit_branch;
+            u32 current_label = static_cast<u32>(exit_branch);
             for (auto& block : blocks) {
                 if (shader_info.labels.count(block.start) != 0) {
                     insert_block(current_block, current_label);

From 3df9558593d41b8c9bda905dd745a67ff00db033 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Tue, 16 Jul 2019 11:32:35 -0400
Subject: [PATCH 02/10] video_core/control_flow: Place all internally linked
 types/functions within an anonymous namespace

Previously, quite a few functions were being linked with external
linkage.
---
 src/video_core/shader/control_flow.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index fdcc970ff..440729258 100644
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -15,7 +15,7 @@
 #include "video_core/shader/shader_ir.h"
 
 namespace VideoCommon::Shader {
-
+namespace {
 using Tegra::Shader::Instruction;
 using Tegra::Shader::OpCode;
 
@@ -411,6 +411,7 @@ bool TryQuery(CFGRebuildState& state) {
     state.queries.push_back(conditional_query);
     return true;
 }
+} // Anonymous namespace
 
 std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 program_size,
                                               u32 start_address) {

From 47df844338a6ad59189cad060cbeced1bc306e73 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Tue, 16 Jul 2019 11:35:33 -0400
Subject: [PATCH 03/10] video_core/control_flow: Make program_size for
 ScanFlow() a std::size_t

Prevents a truncation warning from occurring with MSVC. Also the
internal data structures already treat it as a size_t, so this is just a
discrepancy in the interface.
---
 src/video_core/shader/control_flow.cpp | 4 ++--
 src/video_core/shader/control_flow.h   | 5 ++---
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index 440729258..20f9a6480 100644
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -413,8 +413,8 @@ bool TryQuery(CFGRebuildState& state) {
 }
 } // Anonymous namespace
 
-std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 program_size,
-                                              u32 start_address) {
+std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
+                                              std::size_t program_size, u32 start_address) {
     CFGRebuildState state{program_code, program_size, start_address};
     // Inspect Code and generate blocks
     state.labels.clear();
diff --git a/src/video_core/shader/control_flow.h b/src/video_core/shader/control_flow.h
index 5e8ea3271..728286d70 100644
--- a/src/video_core/shader/control_flow.h
+++ b/src/video_core/shader/control_flow.h
@@ -4,7 +4,6 @@
 
 #pragma once
 
-#include <cstring>
 #include <list>
 #include <optional>
 #include <unordered_set>
@@ -57,7 +56,7 @@ struct ShaderCharacteristics {
     std::unordered_set<u32> labels{};
 };
 
-std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 program_size,
-                                              u32 start_address);
+std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
+                                              std::size_t program_size, u32 start_address);
 
 } // namespace VideoCommon::Shader

From 45fa12a05c8ba20259979d4b9e40d7401d825502 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Tue, 16 Jul 2019 11:38:48 -0400
Subject: [PATCH 04/10] video_core: Resolve -Wreorder warnings

Ensures that the constructor members are always initialized in the order
that they're declared in.
---
 src/video_core/shader/control_flow.cpp        | 2 +-
 src/video_core/texture_cache/surface_base.cpp | 5 ++---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index 20f9a6480..6a92c540e 100644
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -58,7 +58,7 @@ struct BlockInfo {
 struct CFGRebuildState {
     explicit CFGRebuildState(const ProgramCode& program_code, const std::size_t program_size,
                              const u32 start)
-        : program_code{program_code}, program_size{program_size}, start{start} {}
+        : start{start}, program_code{program_code}, program_size{program_size} {}
 
     u32 start{};
     std::vector<BlockInfo> block_info{};
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp
index 6af9044ca..683c49207 100644
--- a/src/video_core/texture_cache/surface_base.cpp
+++ b/src/video_core/texture_cache/surface_base.cpp
@@ -24,9 +24,8 @@ StagingCache::StagingCache() = default;
 StagingCache::~StagingCache() = default;
 
 SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params)
-    : params{params}, mipmap_sizes(params.num_levels),
-      mipmap_offsets(params.num_levels), gpu_addr{gpu_addr}, host_memory_size{
-                                                                 params.GetHostSizeInBytes()} {
+    : params{params}, host_memory_size{params.GetHostSizeInBytes()}, gpu_addr{gpu_addr},
+      mipmap_sizes(params.num_levels), mipmap_offsets(params.num_levels) {
     std::size_t offset = 0;
     for (u32 level = 0; level < params.num_levels; ++level) {
         const std::size_t mipmap_size{params.GetGuestMipmapSize(level)};

From 6885e7e7ec4919cd66ee0294fdbd9aea8935c50d Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Tue, 16 Jul 2019 11:40:58 -0400
Subject: [PATCH 05/10] video_core/control_flow: Use empty() member function
 for checking emptiness

It's what it's there for.
---
 src/video_core/shader/control_flow.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index 6a92c540e..83549c082 100644
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -379,8 +379,8 @@ bool TryQuery(CFGRebuildState& state) {
     // consumes a label. Schedule new queries accordingly
     if (block.visited) {
         BlockStack& stack = state.stacks[q.address];
-        const bool all_okay = (stack.ssy_stack.size() == 0 || q.ssy_stack == stack.ssy_stack) &&
-                              (stack.pbk_stack.size() == 0 || q.pbk_stack == stack.pbk_stack);
+        const bool all_okay = (stack.ssy_stack.empty() || q.ssy_stack == stack.ssy_stack) &&
+                              (stack.pbk_stack.empty() || q.pbk_stack == stack.pbk_stack);
         state.queries.pop_front();
         return all_okay;
     }

From e7b39f47f86ee2c3656340b8af7747848ddc1f2e Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Tue, 16 Jul 2019 11:42:05 -0400
Subject: [PATCH 06/10] video_core/control_flow: Use the prefix variant of
 operator++ for iterators

Same thing, but potentially allows a standard library implementation to
pick a more efficient codepath.
---
 src/video_core/shader/control_flow.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index 83549c082..c2243337c 100644
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -365,7 +365,7 @@ bool TryQuery(CFGRebuildState& state) {
         const auto gather_end = labels.upper_bound(block.end);
         while (gather_start != gather_end) {
             cc.push(gather_start->second);
-            gather_start++;
+            ++gather_start;
         }
     };
     if (state.queries.empty()) {
@@ -470,7 +470,7 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
             continue;
         }
         back = next;
-        next++;
+        ++next;
     }
     return {result_out};
 }

From 56bc11d952fa228475d09891e01b3d1c6d32f015 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Tue, 16 Jul 2019 11:50:36 -0400
Subject: [PATCH 07/10] video_core/control_flow: Use std::move where applicable

Results in less work being done where avoidable.
---
 src/video_core/shader/control_flow.cpp | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index c2243337c..4d500320a 100644
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -371,10 +371,11 @@ bool TryQuery(CFGRebuildState& state) {
     if (state.queries.empty()) {
         return false;
     }
+
     Query& q = state.queries.front();
     const u32 block_index = state.registered[q.address];
     BlockInfo& block = state.block_info[block_index];
-    // If the block is visted, check if the stacks match, else gather the ssy/pbk
+    // If the block is visited, check if the stacks match, else gather the ssy/pbk
     // labels into the current stack and look if the branch at the end of the block
     // consumes a label. Schedule new queries accordingly
     if (block.visited) {
@@ -385,7 +386,8 @@ bool TryQuery(CFGRebuildState& state) {
         return all_okay;
     }
     block.visited = true;
-    state.stacks[q.address] = BlockStack{q};
+    state.stacks.insert_or_assign(q.address, BlockStack{q});
+
     Query q2(q);
     state.queries.pop_front();
     gather_labels(q2.ssy_stack, state.ssy_labels, block);
@@ -394,6 +396,7 @@ bool TryQuery(CFGRebuildState& state) {
         q2.address = block.end + 1;
         state.queries.push_back(q2);
     }
+
     Query conditional_query{q2};
     if (block.branch.is_sync) {
         if (block.branch.address == unassigned_branch) {
@@ -408,7 +411,7 @@ bool TryQuery(CFGRebuildState& state) {
         conditional_query.pbk_stack.pop();
     }
     conditional_query.address = block.branch.address;
-    state.queries.push_back(conditional_query);
+    state.queries.push_back(std::move(conditional_query));
     return true;
 }
 } // Anonymous namespace
@@ -416,6 +419,7 @@ bool TryQuery(CFGRebuildState& state) {
 std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
                                               std::size_t program_size, u32 start_address) {
     CFGRebuildState state{program_code, program_size, start_address};
+
     // Inspect Code and generate blocks
     state.labels.clear();
     state.labels.emplace(start_address);
@@ -425,10 +429,9 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
             return {};
         }
     }
+
     // Decompile Stacks
-    Query start_query{};
-    start_query.address = state.start;
-    state.queries.push_back(start_query);
+    state.queries.push_back(Query{state.start, {}, {}});
     bool decompiled = true;
     while (!state.queries.empty()) {
         if (!TryQuery(state)) {
@@ -436,14 +439,15 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
             break;
         }
     }
+
     // Sort and organize results
     std::sort(state.block_info.begin(), state.block_info.end(),
-              [](const BlockInfo& a, const BlockInfo& b) -> bool { return a.start < b.start; });
+              [](const BlockInfo& a, const BlockInfo& b) { return a.start < b.start; });
     ShaderCharacteristics result_out{};
     result_out.decompilable = decompiled;
     result_out.start = start_address;
     result_out.end = start_address;
-    for (auto& block : state.block_info) {
+    for (const auto& block : state.block_info) {
         ShaderBlock new_block{};
         new_block.start = block.start;
         new_block.end = block.end;
@@ -458,8 +462,9 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
     }
     if (result_out.decompilable) {
         result_out.labels = std::move(state.labels);
-        return {result_out};
+        return {std::move(result_out)};
     }
+
     // If it's not decompilable, merge the unlabelled blocks together
     auto back = result_out.blocks.begin();
     auto next = std::next(back);
@@ -472,6 +477,6 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
         back = next;
         ++next;
     }
-    return {result_out};
+    return {std::move(result_out)};
 }
 } // namespace VideoCommon::Shader

From a162a844d2ede2b13d4a52f2dae37980be91cb1a Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Tue, 16 Jul 2019 11:52:08 -0400
Subject: [PATCH 08/10] video_core/control_flow: Remove unnecessary BlockStack
 copy constructor

This is the default behavior of the copy constructor, so it doesn't need
to be specified.

While we're at it we can make the other non-default constructor
explicit.
---
 src/video_core/shader/control_flow.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index 4d500320a..37792d420 100644
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -29,8 +29,7 @@ struct Query {
 
 struct BlockStack {
     BlockStack() = default;
-    BlockStack(const BlockStack& b) = default;
-    BlockStack(const Query& q) : ssy_stack{q.ssy_stack}, pbk_stack{q.pbk_stack} {}
+    explicit BlockStack(const Query& q) : ssy_stack{q.ssy_stack}, pbk_stack{q.pbk_stack} {}
     std::stack<u32> ssy_stack{};
     std::stack<u32> pbk_stack{};
 };

From 1780e0e3d04fe7d8edd0b7b691198f31f23140ce Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Tue, 16 Jul 2019 11:56:37 -0400
Subject: [PATCH 09/10] video_core/control_flow: Prevent sign conversion in
 TryGetBlock()

The return value is a u32, not an s32, so this would result in an
implicit signedness conversion.
---
 src/video_core/shader/control_flow.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index 37792d420..ec3a76690 100644
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -84,7 +84,7 @@ std::pair<BlockCollision, u32> TryGetBlock(CFGRebuildState& state, u32 address)
             return {BlockCollision::Inside, index};
         }
     }
-    return {BlockCollision::None, -1};
+    return {BlockCollision::None, 0xFFFFFFFF};
 }
 
 struct ParseInfo {

From c1c89411da173cf76de2a2ec19fd26247648cc3c Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Tue, 16 Jul 2019 11:59:57 -0400
Subject: [PATCH 10/10] video_core/control_flow: Provide operator!= for types
 with operator==

Provides operational symmetry for the respective structures.
---
 src/video_core/shader/control_flow.h | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/src/video_core/shader/control_flow.h b/src/video_core/shader/control_flow.h
index 728286d70..b0a5e4f8c 100644
--- a/src/video_core/shader/control_flow.h
+++ b/src/video_core/shader/control_flow.h
@@ -25,27 +25,44 @@ struct Condition {
     bool IsUnconditional() const {
         return predicate == Pred::UnusedIndex && cc == ConditionCode::T;
     }
+
     bool operator==(const Condition& other) const {
         return std::tie(predicate, cc) == std::tie(other.predicate, other.cc);
     }
+
+    bool operator!=(const Condition& other) const {
+        return !operator==(other);
+    }
 };
 
 struct ShaderBlock {
-    u32 start{};
-    u32 end{};
-    bool ignore_branch{};
     struct Branch {
         Condition cond{};
         bool kills{};
         s32 address{};
+
         bool operator==(const Branch& b) const {
             return std::tie(cond, kills, address) == std::tie(b.cond, b.kills, b.address);
         }
-    } branch{};
+
+        bool operator!=(const Branch& b) const {
+            return !operator==(b);
+        }
+    };
+
+    u32 start{};
+    u32 end{};
+    bool ignore_branch{};
+    Branch branch{};
+
     bool operator==(const ShaderBlock& sb) const {
         return std::tie(start, end, ignore_branch, branch) ==
                std::tie(sb.start, sb.end, sb.ignore_branch, sb.branch);
     }
+
+    bool operator!=(const ShaderBlock& sb) const {
+        return !operator==(sb);
+    }
 };
 
 struct ShaderCharacteristics {