Stabilize the output of spirv-diff (#4698)

* Reimplement LCS used by spirv-diff

Two improvements are made to the LCS algorithm:

- The LCS algorithm is reimplemented to use a std::stack instead of
  being recursive.  This prevents stack overflow in the LCSTest.Large
  test.
- The LCS algorithm uses an NxM table.  Previously, entries of this
  table were {size_t, bool, bool}, which is now packed in 32 bits.  The
  first entry can assume a maximum value of min(N, M), which
  realistically for SPIR-V diff will not be larger than 1 billion
  instructions.  This reduces memory usage of LCS by 75%.

This partially reverts 845f3efb8a4eb32e5f484aa6ea9b9e3716d6f7ec and
enables LCS tests.

* Stabilize the output of spirv-diff

std::map is used instead of std::unordered_map to ensure the output of
spirv-diff is identical everywhere.

This partially reverts 845f3efb8a4eb32e5f484aa6ea9b9e3716d6f7ec and
enables spirv-diff tests.
diff --git a/source/diff/diff.cpp b/source/diff/diff.cpp
index f44a9ba..13e1ffa 100644
--- a/source/diff/diff.cpp
+++ b/source/diff/diff.cpp
@@ -36,7 +36,7 @@
 // A flat list of instructions in a function for easier iteration.
 using InstructionList = std::vector<const opt::Instruction*>;
 // A map from a function to its list of instructions.
-using FunctionInstMap = std::unordered_map<uint32_t, InstructionList>;
+using FunctionInstMap = std::map<uint32_t, InstructionList>;
 // A list of ids with some similar property, for example functions with the same
 // name.
 using IdGroup = std::vector<uint32_t>;
@@ -1486,7 +1486,7 @@
   LongestCommonSubsequence<std::vector<const opt::Instruction*>> lcs(src_body,
                                                                      dst_body);
 
-  size_t best_match_length = lcs.Get<const opt::Instruction*>(
+  uint32_t best_match_length = lcs.Get<const opt::Instruction*>(
       [this](const opt::Instruction* src_inst,
              const opt::Instruction* dst_inst) {
         return DoInstructionsMatchFuzzy(src_inst, dst_inst);